diff --git a/samples/opengl/isosurf/isosurf.cpp b/samples/opengl/isosurf/isosurf.cpp index f89ba3f71f..c7f47eb8f5 100644 --- a/samples/opengl/isosurf/isosurf.cpp +++ b/samples/opengl/isosurf/isosurf.cpp @@ -27,112 +27,367 @@ #include "wx/timer.h" #include "wx/glcanvas.h" #include "wx/math.h" - -#if defined(__WXMAC__) || defined(__WXCOCOA__) -# ifdef __DARWIN__ -# include -# include -# else -# include -# include -# endif -#else -# include -# include -#endif - -// disabled because this has apparently changed in OpenGL 1.2, so doesn't link -// correctly if this is on... -#ifdef GL_EXT_vertex_array -#undef GL_EXT_vertex_array -#endif - -#include +#include "wx/log.h" +#include "wx/cmdline.h" +#include "wx/archive.h" +#include "wx/wfstream.h" +#include "wx/zstream.h" #include "isosurf.h" #include "../../sample.xpm" -// The following part is taken largely unchanged from the original C Version -GLboolean speed_test = GL_FALSE; -GLboolean use_vertex_arrays = GL_FALSE; - -GLboolean doubleBuffer = GL_TRUE; - -GLboolean smooth = GL_TRUE; -GLboolean lighting = GL_TRUE; +// global options which can be set through command-line options +GLboolean g_speed_test = GL_FALSE; +GLboolean g_use_vertex_arrays = GL_FALSE; +GLboolean g_doubleBuffer = GL_TRUE; +GLboolean g_smooth = GL_TRUE; +GLboolean g_lighting = GL_TRUE; -#define MAXVERTS 10000 -static GLfloat verts[MAXVERTS][3]; -static GLfloat norms[MAXVERTS][3]; -static GLint numverts; +//--------------------------------------------------------------------------- +// MyApp +//--------------------------------------------------------------------------- -static GLfloat xrot; -static GLfloat yrot; +IMPLEMENT_APP(MyApp) - -static void read_surface(const char *filename) +// `Main program' equivalent, creating windows and returning main app frame +bool MyApp::OnInit() { - std::ifstream inFile(filename); - numverts = 0; + if ( !wxApp::OnInit() ) + return false; - if ( !inFile ) + // Create the main frame window + SetTopWindow(new MyFrame(NULL, wxT("wxWidgets OpenGL Isosurf Sample"), + wxDefaultPosition, wxDefaultSize)); + + return true; +} + +void MyApp::OnInitCmdLine(wxCmdLineParser& parser) +{ + parser.AddSwitch("", "-sb"); + parser.AddSwitch("", "-db"); + parser.AddSwitch("", "-speed"); + parser.AddSwitch("", "-va"); + + wxApp::OnInitCmdLine(parser); +} + +bool MyApp::OnCmdLineParsed(wxCmdLineParser& parser) +{ + if (parser.Found("-sb")) + g_doubleBuffer = GL_FALSE; + else if (parser.Found("-db")) + g_doubleBuffer = GL_TRUE; + + if (parser.Found("-speed")) { - wxLogError("Couldn't read \"%s\"", filename); + g_speed_test = GL_TRUE; + g_doubleBuffer = GL_TRUE; + } + + if (parser.Found("-va")) + g_use_vertex_arrays = GL_TRUE; + + return wxApp::OnCmdLineParsed(parser); +} + +//--------------------------------------------------------------------------- +// MyFrame +//--------------------------------------------------------------------------- + +BEGIN_EVENT_TABLE(MyFrame, wxFrame) + EVT_MENU(wxID_EXIT, MyFrame::OnExit) +END_EVENT_TABLE() + +// My frame constructor +MyFrame::MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos, + const wxSize& size, long style) + : wxFrame(frame, wxID_ANY, title, pos, size, style), + m_canvas(NULL) +{ + SetIcon(wxICON(sample)); + + + // Make a menubar + wxMenu *fileMenu = new wxMenu; + + fileMenu->Append(wxID_EXIT, _T("E&xit")); + wxMenuBar *menuBar = new wxMenuBar; + menuBar->Append(fileMenu, _T("&File")); + SetMenuBar(menuBar); + + + // Make a TestGLCanvas + + // JACS +#ifdef __WXMSW__ + int *gl_attrib = NULL; +#else + int gl_attrib[20] = + { WX_GL_RGBA, WX_GL_MIN_RED, 1, WX_GL_MIN_GREEN, 1, + WX_GL_MIN_BLUE, 1, WX_GL_DEPTH_SIZE, 1, + WX_GL_DOUBLEBUFFER, +# if defined(__WXMAC__) || defined(__WXCOCOA__) + GL_NONE }; +# else + None }; +# endif +#endif + + if (!g_doubleBuffer) + { + wxLogWarning("don't have double buffer, disabling\n"); + +#ifdef __WXGTK__ + gl_attrib[9] = None; +#endif + g_doubleBuffer = GL_FALSE; + } + + // Show the frame + Show(true); + + m_canvas = new TestGLCanvas(this, wxID_ANY, wxDefaultPosition, + GetClientSize(), 0, _T("TestGLCanvas"), gl_attrib); +} + +MyFrame::~MyFrame() +{ + delete m_canvas; +} + +// Intercept menu commands +void MyFrame::OnExit( wxCommandEvent& WXUNUSED(event) ) +{ + // true is to force the frame to close + Close(true); +} + + +//--------------------------------------------------------------------------- +// TestGLCanvas +//--------------------------------------------------------------------------- + +BEGIN_EVENT_TABLE(TestGLCanvas, wxGLCanvas) + EVT_SIZE(TestGLCanvas::OnSize) + EVT_PAINT(TestGLCanvas::OnPaint) + EVT_CHAR(TestGLCanvas::OnChar) + EVT_MOUSE_EVENTS(TestGLCanvas::OnMouseEvent) +END_EVENT_TABLE() + +TestGLCanvas::TestGLCanvas(wxWindow *parent, + wxWindowID id, + const wxPoint& pos, + const wxSize& size, + long style, + const wxString& name, + int* gl_attrib) + : wxGLCanvas(parent, id, gl_attrib, pos, size, + style | wxFULL_REPAINT_ON_RESIZE, name) +{ + // Explicitly create a new rendering context instance for this canvas. + m_glRC = new wxGLContext(this); + + // Make the new context current (activate it for use) with this canvas. + SetCurrent(*m_glRC); + + InitGL(); + InitMaterials(); + LoadSurface("isosurf.dat.gz"); +} + +TestGLCanvas::~TestGLCanvas() +{ + delete m_glRC; +} + +void TestGLCanvas::LoadSurface(const wxString& filename) +{ + wxZlibInputStream* stream = + new wxZlibInputStream(new wxFFileInputStream(filename)); + if (!stream || !stream->IsOk()) + { + wxLogError("Cannot load '%s' type of files!", filename.c_str()); + delete stream; return; } - while ((inFile >> verts[numverts][0] >> verts[numverts][1] >> verts[numverts][2] - >> norms[numverts][0] >> norms[numverts][1] >> norms[numverts][2]) && numvertsEof() && m_numverts < MAXVERTS) { - numverts++; + // read a vertex + for (int i=0; i<3; i++) + if (stream->Read(&m_verts[m_numverts][i], sz).LastRead() != sz) + { + wxLogError("Cannot read the %d-th vertex in '%s'!", + m_numverts, filename.c_str()); + delete stream; + return; + } + + // read its normal + for (int i=0; i<3; i++) + if (stream->Read(&m_norms[m_numverts][i], sz).LastRead() != sz) + { + wxLogError("Cannot read the %d-th vertex in '%s'!", + m_numverts, filename.c_str()); + delete stream; + return; + } + + m_numverts++; } - wxPrintf(_T("%d vertices, %d triangles\n"), numverts, numverts-2); + delete stream; + + wxLogMessage(_T("Loaded %d vertices, %d triangles from '%s'"), + m_numverts, m_numverts-2, filename.c_str()); } - -static void draw_surface() +void TestGLCanvas::OnPaint( wxPaintEvent& WXUNUSED(event) ) { - GLint i; + // This is a dummy, to avoid an endless succession of paint messages. + // OnPaint handlers must always create a wxPaintDC. + wxPaintDC dc(this); -#ifdef GL_EXT_vertex_array - if (use_vertex_arrays) - { - glDrawArraysEXT( GL_TRIANGLE_STRIP, 0, numverts ); - } - else -#endif - { - glBegin( GL_TRIANGLE_STRIP ); - for (i=0;iExitMainLoop(); + return; + + case WXK_LEFT: + m_yrot -= 15.0; + break; + + case WXK_RIGHT: + m_yrot += 15.0; + break; + + case WXK_UP: + m_xrot += 15.0; + break; + + case WXK_DOWN: + m_xrot -= 15.0; + break; + + case 's': case 'S': + g_smooth = !g_smooth; + if (g_smooth) + { + glShadeModel(GL_SMOOTH); + } + else + { + glShadeModel(GL_FLAT); + } + break; + + case 'l': case 'L': + g_lighting = !g_lighting; + if (g_lighting) + { + glEnable(GL_LIGHTING); + } + else + { + glDisable(GL_LIGHTING); + } + break; + + default: + event.Skip(); + return; + } + + Refresh(false); +} + +void TestGLCanvas::OnMouseEvent(wxMouseEvent& event) +{ + static int dragging = 0; + static float last_x, last_y; + + // Allow default processing to happen, or else the canvas cannot gain focus + // (for key events). + event.Skip(); + + if(event.LeftIsDown()) + { + if(!dragging) + { + dragging = 1; + } + else + { + m_yrot += (event.GetX() - last_x)*1.0; + m_xrot += (event.GetY() - last_y)*1.0; + Refresh(false); + } + last_x = event.GetX(); + last_y = event.GetY(); + } + else + { + dragging = 0; + } +} + +void TestGLCanvas::InitMaterials() { static const GLfloat ambient[4] = {0.1f, 0.1f, 0.1f, 1.0f}; static const GLfloat diffuse[4] = {0.5f, 1.0f, 1.0f, 1.0f}; @@ -168,8 +423,7 @@ static void InitMaterials() glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, front_mat_diffuse); } - -static void Init(void) +void TestGLCanvas::InitGL() { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); @@ -186,290 +440,12 @@ static void Init(void) glLoadIdentity(); glTranslatef( 0.0, 0.0, -6.0 ); -#ifdef GL_EXT_vertex_array - if (use_vertex_arrays) + if (g_use_vertex_arrays) { - glVertexPointerEXT( 3, GL_FLOAT, 0, numverts, verts ); - glNormalPointerEXT( GL_FLOAT, 0, numverts, norms ); + glVertexPointer( 3, GL_FLOAT, 0, m_verts ); + glNormalPointer( GL_FLOAT, 0, m_norms ); glEnable( GL_VERTEX_ARRAY_EXT ); glEnable( GL_NORMAL_ARRAY_EXT ); } -#endif -} - -static GLenum Args(int argc, wxChar **argv) -{ - GLint i; - - for (i = 1; i < argc; i++) - { - if (wxStrcmp(argv[i], _T("-sb")) == 0) - { - doubleBuffer = GL_FALSE; - } - else if (wxStrcmp(argv[i], _T("-db")) == 0) - { - doubleBuffer = GL_TRUE; - } - else if (wxStrcmp(argv[i], _T("-speed")) == 0) - { - speed_test = GL_TRUE; - doubleBuffer = GL_TRUE; - } - else if (wxStrcmp(argv[i], _T("-va")) == 0) - { - use_vertex_arrays = GL_TRUE; - } - else - { - wxString msg = _T("Bad option: "); - msg += argv[i]; - wxMessageBox(msg); - return GL_FALSE; - } - } - - return GL_TRUE; -} - - -IMPLEMENT_APP(MyApp) - -// `Main program' equivalent, creating windows and returning main app frame -bool MyApp::OnInit() -{ - if ( !wxApp::OnInit() ) - return false; - - Args(argc, argv); - - // Create the main frame window - new MyFrame(NULL, wxT("wxWidgets OpenGL Isosurf Sample"), - wxDefaultPosition, wxDefaultSize); - - read_surface("isosurf.dat"); - - Init(); - - return true; -} - -BEGIN_EVENT_TABLE(MyFrame, wxFrame) - EVT_MENU(wxID_EXIT, MyFrame::OnExit) -END_EVENT_TABLE() - -// My frame constructor -MyFrame::MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos, - const wxSize& size, long style) - : wxFrame(frame, wxID_ANY, title, pos, size, style), - m_canvas(NULL) -{ - SetIcon(wxICON(sample)); - - - // Make a menubar - wxMenu *fileMenu = new wxMenu; - - fileMenu->Append(wxID_EXIT, _T("E&xit")); - wxMenuBar *menuBar = new wxMenuBar; - menuBar->Append(fileMenu, _T("&File")); - SetMenuBar(menuBar); - - - // Make a TestGLCanvas - - // JACS -#ifdef __WXMSW__ - int *gl_attrib = NULL; -#else - int gl_attrib[20] = { WX_GL_RGBA, WX_GL_MIN_RED, 1, WX_GL_MIN_GREEN, 1, - WX_GL_MIN_BLUE, 1, WX_GL_DEPTH_SIZE, 1, - WX_GL_DOUBLEBUFFER, -# if defined(__WXMAC__) || defined(__WXCOCOA__) - GL_NONE }; -# else - None }; -# endif -#endif - - if(!doubleBuffer) - { - printf("don't have double buffer, disabling\n"); -#ifdef __WXGTK__ - gl_attrib[9] = None; -#endif - doubleBuffer = GL_FALSE; - } - - // Show the frame - Show(true); - - m_canvas = new TestGLCanvas(this, wxID_ANY, wxDefaultPosition, - GetClientSize(), 0, _T("TestGLCanvas"), gl_attrib ); -} - -MyFrame::~MyFrame() -{ - delete m_canvas; -} - -// Intercept menu commands -void MyFrame::OnExit( wxCommandEvent& WXUNUSED(event) ) -{ - // true is to force the frame to close - Close(true); -} - -/* - * TestGLCanvas implementation - */ - -BEGIN_EVENT_TABLE(TestGLCanvas, wxGLCanvas) - EVT_SIZE(TestGLCanvas::OnSize) - EVT_PAINT(TestGLCanvas::OnPaint) - EVT_CHAR(TestGLCanvas::OnChar) - EVT_MOUSE_EVENTS(TestGLCanvas::OnMouseEvent) -END_EVENT_TABLE() - -TestGLCanvas::TestGLCanvas(wxWindow *parent, - wxWindowID id, - const wxPoint& pos, - const wxSize& size, - long style, - const wxString& name, - int* gl_attrib) - : wxGLCanvas(parent, id, gl_attrib, pos, size, - style | wxFULL_REPAINT_ON_RESIZE, name) -{ - // Explicitly create a new rendering context instance for this canvas. - m_glRC = new wxGLContext(this); - - // Make the new context current (activate it for use) with this canvas. - SetCurrent(*m_glRC); - - /* Make sure server supports the vertex array extension */ - char* extensions = (char *) glGetString( GL_EXTENSIONS ); - if (!extensions || !strstr( extensions, "GL_EXT_vertex_array" )) - { - use_vertex_arrays = GL_FALSE; - } -} - -TestGLCanvas::~TestGLCanvas() -{ - delete m_glRC; -} - -void TestGLCanvas::OnPaint( wxPaintEvent& WXUNUSED(event) ) -{ - // This is a dummy, to avoid an endless succession of paint messages. - // OnPaint handlers must always create a wxPaintDC. - wxPaintDC dc(this); - - // This is normally only necessary if there is more than one wxGLCanvas - // or more than one wxGLContext in the application. - SetCurrent(*m_glRC); - - draw1(); - SwapBuffers(); -} - -void TestGLCanvas::OnSize(wxSizeEvent& event) -{ - // This is normally only necessary if there is more than one wxGLCanvas - // or more than one wxGLContext in the application. - SetCurrent(*m_glRC); - - // It's up to the application code to update the OpenGL viewport settings. - // This is OK here only because there is only one canvas that uses the - // context. See the cube sample for that case that multiple canvases are - // made current with one context. - glViewport(0, 0, event.GetSize().x, event.GetSize().y); -} - -void TestGLCanvas::OnChar(wxKeyEvent& event) -{ - switch( event.GetKeyCode() ) - { - case WXK_ESCAPE: - wxTheApp->ExitMainLoop(); - return; - - case WXK_LEFT: - yrot -= 15.0; - break; - - case WXK_RIGHT: - yrot += 15.0; - break; - - case WXK_UP: - xrot += 15.0; - break; - - case WXK_DOWN: - xrot -= 15.0; - break; - - case 's': case 'S': - smooth = !smooth; - if (smooth) - { - glShadeModel(GL_SMOOTH); - } - else - { - glShadeModel(GL_FLAT); - } - break; - - case 'l': case 'L': - lighting = !lighting; - if (lighting) - { - glEnable(GL_LIGHTING); - } - else - { - glDisable(GL_LIGHTING); - } - break; - - default: - event.Skip(); - return; - } - - Refresh(false); -} - -void TestGLCanvas::OnMouseEvent(wxMouseEvent& event) -{ - static int dragging = 0; - static float last_x, last_y; - - // Allow default processing to happen, or else the canvas cannot gain focus - // (for key events). - event.Skip(); - - if(event.LeftIsDown()) - { - if(!dragging) - { - dragging = 1; - } - else - { - yrot += (event.GetX() - last_x)*1.0; - xrot += (event.GetY() - last_y)*1.0; - Refresh(false); - } - last_x = event.GetX(); - last_y = event.GetY(); - } - else - { - dragging = 0; - } } diff --git a/samples/opengl/isosurf/isosurf.h b/samples/opengl/isosurf/isosurf.h index 15f6dc2164..6af9872cf5 100644 --- a/samples/opengl/isosurf/isosurf.h +++ b/samples/opengl/isosurf/isosurf.h @@ -12,14 +12,36 @@ #ifndef _WX_ISOSURF_H_ #define _WX_ISOSURF_H_ +// we need OpenGL headers for GLfloat/GLint types used below +#if defined(__WXMAC__) || defined(__WXCOCOA__) +# ifdef __DARWIN__ +# include +# include +# else +# include +# include +# endif +#else +# include +# include +#endif + +// the maximum number of vertex in the loaded .dat file +#define MAXVERTS 10000 + + // Define a new application type class MyApp : public wxApp { public: virtual bool OnInit(); + + virtual void OnInitCmdLine(wxCmdLineParser& parser); + virtual bool OnCmdLineParsed(wxCmdLineParser& parser); }; +// The OpenGL-enabled canvas class TestGLCanvas : public wxGLCanvas { public: @@ -38,15 +60,26 @@ public: void OnChar(wxKeyEvent& event); void OnMouseEvent(wxMouseEvent& event); + void LoadSurface(const wxString& filename); + void InitMaterials(); + void InitGL(); private: wxGLContext* m_glRC; + GLfloat m_verts[MAXVERTS][3]; + GLfloat m_norms[MAXVERTS][3]; + GLint m_numverts; + + GLfloat m_xrot; + GLfloat m_yrot; + DECLARE_NO_COPY_CLASS(TestGLCanvas) DECLARE_EVENT_TABLE() }; +// The frame containing the GL canvas class MyFrame : public wxFrame { public: @@ -66,5 +99,6 @@ private : DECLARE_EVENT_TABLE() }; + #endif // _WX_ISOSURF_H_