]> git.saurik.com Git - wxWidgets.git/blobdiff - samples/opengl/penguin/penguin.cpp
Use template class instead of template function in wxVectorSort().
[wxWidgets.git] / samples / opengl / penguin / penguin.cpp
index 077fc90bcae674e494fafe48fbffdf55a22bbf91..e18cb95adc1c5cdea3c349c7e131c43e7e94bdee 100644 (file)
@@ -2,18 +2,13 @@
 // Name:        penguin.cpp
 // Purpose:     wxGLCanvas demo program
 // Author:      Robert Roebling
-// Modified by:
+// Modified by: Sandro Sigala
 // Created:     04/01/98
 // RCS-ID:      $Id$
 // Copyright:   (c) Robert Roebling
-// Licence:    wxWindows licence
+// Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
-#ifdef __GNUG__
-#pragma implementation
-#pragma interface
-#endif
-
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
 #endif
 
 #if !wxUSE_GLCANVAS
-#error Please set wxUSE_GLCANVAS to 1 in setup.h.
+    #error "OpenGL required: set wxUSE_GLCANVAS to 1 and rebuild the library"
 #endif
 
 #include "penguin.h"
-#include <GL/glu.h>
-
-#define VIEW_ASPECT 1.3
-
-/* `Main program' equivalent, creating windows and returning main app frame */
-bool MyApp::OnInit(void)
-{
-
-  /* Create the main frame window */
-  MyFrame *frame = new MyFrame(NULL, "wxWindows OpenGL Demo", wxPoint(50, 50), wxSize(400, 300));
+#ifdef __DARWIN__
+    #include <OpenGL/glu.h>
+#else
+    #include <GL/glu.h>
+#endif
 
-  /* Make a menubar */
-  wxMenu *fileMenu = new wxMenu;
+#include "../../sample.xpm"
 
-  fileMenu->Append(wxID_EXIT, "E&xit");
-  wxMenuBar *menuBar = new wxMenuBar;
-  menuBar->Append(fileMenu, "&File");
-  frame->SetMenuBar(menuBar);
+// ---------------------------------------------------------------------------
+// MyApp
+// ---------------------------------------------------------------------------
 
-  frame->m_canvas = new TestGLCanvas(frame, -1, wxPoint(0, 0), wxSize(200, 200));
+// `Main program' equivalent, creating windows and returning main app frame
+bool MyApp::OnInit()
+{
+    if ( !wxApp::OnInit() )
+        return false;
+
+    // Create the main frame window
+    MyFrame *frame = new MyFrame(NULL, wxT("wxWidgets Penguin Sample"),
+        wxDefaultPosition, wxDefaultSize);
+
+#if wxUSE_ZLIB
+    if (wxFileExists(wxT("penguin.dxf.gz")))
+        frame->GetCanvas()->LoadDXF(wxT("penguin.dxf.gz"));
+#else
+    if (wxFileExists(wxT("penguin.dxf")))
+        frame->GetCanvas()->LoadDXF(wxT("penguin.dxf"));
+#endif
 
-  /* Load file wiht mesh data */
-  frame->m_canvas->LoadLWO( "penguin.lwo" );
+    /* Show the frame */
+    frame->Show(true);
 
-  /* Show the frame */
-  frame->Show(TRUE);
-  
-  return TRUE;
+    return true;
 }
 
 IMPLEMENT_APP(MyApp)
 
+// ---------------------------------------------------------------------------
+// MyFrame
+// ---------------------------------------------------------------------------
+
 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
-    EVT_MENU(wxID_EXIT, MyFrame::OnExit)
+    EVT_MENU(wxID_OPEN, MyFrame::OnMenuFileOpen)
+    EVT_MENU(wxID_EXIT, MyFrame::OnMenuFileExit)
+    EVT_MENU(wxID_HELP, MyFrame::OnMenuHelpAbout)
 END_EVENT_TABLE()
 
-/* My frame constructor */
+// MyFrame constructor
 MyFrame::MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos,
-    const wxSize& size, long style):
-  wxFrame(frame, -1, title, pos, size, style)
+    const wxSize& size, long style)
+    : wxFrame(frame, wxID_ANY, title, pos, size, style)
+{
+    SetIcon(wxIcon(sample_xpm));
+
+    // Make the "File" menu
+    wxMenu *fileMenu = new wxMenu;
+    fileMenu->Append(wxID_OPEN, wxT("&Open..."));
+    fileMenu->AppendSeparator();
+    fileMenu->Append(wxID_EXIT, wxT("E&xit\tALT-X"));
+    // Make the "Help" menu
+    wxMenu *helpMenu = new wxMenu;
+    helpMenu->Append(wxID_HELP, wxT("&About..."));
+
+    wxMenuBar *menuBar = new wxMenuBar;
+    menuBar->Append(fileMenu, wxT("&File"));
+    menuBar->Append(helpMenu, wxT("&Help"));
+    SetMenuBar(menuBar);
+
+    Show(true);
+
+    m_canvas = new TestGLCanvas(this, wxID_ANY, wxDefaultPosition,
+        GetClientSize(), wxSUNKEN_BORDER);
+}
+
+// File|Open... command
+void MyFrame::OnMenuFileOpen( wxCommandEvent& WXUNUSED(event) )
 {
-    m_canvas = NULL;
+    wxString filename = wxFileSelector(wxT("Choose DXF Model"), wxT(""), wxT(""), wxT(""),
+#if wxUSE_ZLIB
+        wxT("DXF Drawing (*.dxf;*.dxf.gz)|*.dxf;*.dxf.gz|All files (*.*)|*.*"),
+#else
+        wxT("DXF Drawing (*.dxf)|*.dxf)|All files (*.*)|*.*"),
+#endif
+        wxFD_OPEN);
+    if (!filename.IsEmpty())
+    {
+        m_canvas->LoadDXF(filename);
+        m_canvas->Refresh(false);
+    }
 }
 
-/* Intercept menu commands */
-void MyFrame::OnExit(wxCommandEvent& event)
+// File|Exit command
+void MyFrame::OnMenuFileExit( wxCommandEvent& WXUNUSED(event) )
 {
-    Destroy();
+    // true is to force the frame to close
+    Close(true);
 }
 
+// Help|About... command
+void MyFrame::OnMenuHelpAbout( wxCommandEvent& WXUNUSED(event) )
+{
+    wxMessageBox(wxT("OpenGL Penguin Sample (c) Robert Roebling, Sandro Sigala et al"));
+}
+
+// ---------------------------------------------------------------------------
+// TestGLCanvas
+// ---------------------------------------------------------------------------
+
 BEGIN_EVENT_TABLE(TestGLCanvas, wxGLCanvas)
     EVT_SIZE(TestGLCanvas::OnSize)
     EVT_PAINT(TestGLCanvas::OnPaint)
@@ -87,137 +141,147 @@ BEGIN_EVENT_TABLE(TestGLCanvas, wxGLCanvas)
     EVT_MOUSE_EVENTS(TestGLCanvas::OnMouse)
 END_EVENT_TABLE()
 
-TestGLCanvas::TestGLCanvas(wxWindow *parent, wxWindowID id,
-    const wxPoint& pos, const wxSize& size, long style, const wxString& name):
-  wxGLCanvas(parent, id, pos, size, style, name)
+TestGLCanvas::TestGLCanvas(wxWindow *parent,
+                           wxWindowID id,
+                           const wxPoint& pos,
+                           const wxSize& size,
+                           long style,
+                           const wxString& name)
+    : wxGLCanvas(parent, id, NULL, pos, size,
+                 style | wxFULL_REPAINT_ON_RESIZE, name)
 {
-   block = FALSE;
+    // 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);
+
+    m_gldata.initialized = false;
+
+    // initialize view matrix
+    m_gldata.beginx = 0.0f;
+    m_gldata.beginy = 0.0f;
+    m_gldata.zoom   = 45.0f;
+    trackball(m_gldata.quat, 0.0f, 0.0f, 0.0f, 0.0f);
 }
 
-TestGLCanvas::~TestGLCanvas(void)
+TestGLCanvas::~TestGLCanvas()
 {
-    /* destroy mesh */
-    lw_object_free(info.lwobject);
+    delete m_glRC;
 }
 
-void TestGLCanvas::OnPaint( wxPaintEvent& event )
+void TestGLCanvas::OnPaint( wxPaintEvent& WXUNUSED(event) )
 {
-    /* must always be here */
+    // must always be here
     wxPaintDC dc(this);
 
-#ifndef __WXMOTIF__
-    if (!GetContext()) return;
-#endif
+    SetCurrent(*m_glRC);
 
-    SetCurrent();
-    
-    /* initialize OpenGL */
-    if (info.do_init == TRUE) 
+    // Initialize OpenGL
+    if (!m_gldata.initialized)
     {
         InitGL();
-        info.do_init = FALSE;
+        ResetProjectionMode();
+        m_gldata.initialized = true;
     }
-  
-    /* view */
-    glMatrixMode( GL_PROJECTION );
-    glLoadIdentity();
-    gluPerspective( info.zoom, VIEW_ASPECT, 1, 100 );
-    glMatrixMode( GL_MODELVIEW );
 
-    /* clear */
-    glClearColor( .3, .4, .6, 1 );
+    // Clear
+    glClearColor( 0.3f, 0.4f, 0.6f, 1.0f );
     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
 
-    /* transformations */
-    GLfloat m[4][4];
+    // Transformations
     glLoadIdentity();
-    glTranslatef( 0, 0, -30 );
-    build_rotmatrix( m,info.quat );
+    glTranslatef( 0.0f, 0.0f, -20.0f );
+    GLfloat m[4][4];
+    build_rotmatrix( m, m_gldata.quat );
     glMultMatrixf( &m[0][0] );
 
-    /* draw object */
-    lw_object_show( info.lwobject );
-    
-    /* flush */
+    m_renderer.Render();
+
+    // Flush
     glFlush();
 
-    /* swap */
+    // Swap
     SwapBuffers();
 }
 
-void TestGLCanvas::OnSize(wxSizeEvent& event)
+void TestGLCanvas::OnSize(wxSizeEvent& WXUNUSED(event))
 {
-    int width, height;
-    GetClientSize(& width, & height);
-    
-#ifndef __WXMOTIF__
-    if (GetContext())
-#endif
-    {
-        SetCurrent();
-        glViewport(0, 0, width, height);
-    }
+    // Reset the OpenGL view aspect.
+    // This is OK 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.
+    ResetProjectionMode();
 }
 
-void TestGLCanvas::OnEraseBackground(wxEraseEvent& event)
+void TestGLCanvas::OnEraseBackground(wxEraseEvent& WXUNUSED(event))
 {
-    /* Do nothing, to avoid flashing on MSW */
+    // Do nothing, to avoid flashing on MSW
 }
 
-void TestGLCanvas::LoadLWO(const wxString &filename)
+// Load the DXF file.  If the zlib support is compiled in wxWidgets,
+// supports also the ".dxf.gz" gzip compressed files.
+void TestGLCanvas::LoadDXF(const wxString& filename)
 {
-    /* test if lightwave object */
-    if (!lw_is_lwobject(filename)) return;
-  
-    /* read lightwave object */
-    lwObject *lwobject = lw_object_read(filename);
-    
-    /* scale */
-    lw_object_scale(lwobject, 10.0 / lw_object_radius(lwobject));
-    
-    /* set up mesh info */
-    info.do_init = TRUE;
-    info.lwobject = lwobject;
-    info.beginx = 0;
-    info.beginy = 0;
-    info.zoom   = 45;
-    trackball( info.quat, 0.0, 0.0, 0.0, 0.0 );
+    wxFileInputStream stream(filename);
+    if (stream.Ok())
+#if wxUSE_ZLIB
+    {
+        if (filename.Right(3).Lower() == wxT(".gz"))
+        {
+            wxZlibInputStream zstream(stream);
+            m_renderer.Load(zstream);
+        } else
+        {
+            m_renderer.Load(stream);
+        }
+    }
+#else
+    {
+        m_renderer.Load(stream);
+    }
+#endif
 }
 
-void TestGLCanvas::OnMouse( wxMouseEvent& event )
+void TestGLCanvas::OnMouse(wxMouseEvent& event)
 {
-    wxSize sz(GetClientSize());
     if (event.Dragging())
     {
+        wxSize sz(GetClientSize());
+
         /* drag in progress, simulate trackball */
         float spin_quat[4];
         trackball(spin_quat,
-             (2.0*info.beginx -       sz.x) / sz.x,
-             (     sz.y - 2.0*info.beginy) / sz.y,
-             (     2.0*event.GetX() - sz.x) / sz.x,
-             (    sz.y - 2.0*event.GetY()) / sz.y);
-             
-        add_quats( spin_quat, info.quat, info.quat );
-       
+            (2.0*m_gldata.beginx - sz.x) / sz.x,
+            (sz.y - 2.0*m_gldata.beginy) / sz.y,
+            (2.0*event.GetX() - sz.x)    / sz.x,
+            (sz.y - 2.0*event.GetY())    / sz.y);
+
+        add_quats(spin_quat, m_gldata.quat, m_gldata.quat);
+
         /* orientation has changed, redraw mesh */
-       Refresh(FALSE);
+        Refresh(false);
     }
-    
-    info.beginx = event.GetX();
-    info.beginy = event.GetY();
+
+    m_gldata.beginx = event.GetX();
+    m_gldata.beginy = event.GetY();
 }
 
-void TestGLCanvas::InitGL(void)
+void TestGLCanvas::InitGL()
 {
-    GLfloat light0_pos[4]   = { -50.0, 50.0, 0.0, 0.0 };
-    GLfloat light0_color[4] = { .6, .6, .6, 1.0 }; /* white light */
-    GLfloat light1_pos[4]   = {  50.0, 50.0, 0.0, 0.0 };
-    GLfloat light1_color[4] = { .4, .4, 1, 1.0 };  /* cold blue light */
+    static const GLfloat light0_pos[4]   = { -50.0f, 50.0f, 0.0f, 0.0f };
+
+    // white light
+    static const GLfloat light0_color[4] = { 0.6f, 0.6f, 0.6f, 1.0f };
+
+    static const GLfloat light1_pos[4]   = {  50.0f, 50.0f, 0.0f, 0.0f };
+
+    // cold blue light
+    static const GLfloat light1_color[4] = { 0.4f, 0.4f, 1.0f, 1.0f };
 
     /* remove back faces */
     glDisable(GL_CULL_FACE);
     glEnable(GL_DEPTH_TEST);
-  
+
     /* speedups */
     glEnable(GL_DITHER);
     glShadeModel(GL_SMOOTH);
@@ -226,15 +290,34 @@ void TestGLCanvas::InitGL(void)
 
     /* light */
     glLightfv(GL_LIGHT0, GL_POSITION, light0_pos);
-    glLightfv(GL_LIGHT0, GL_DIFFUSE,  light0_color);  
+    glLightfv(GL_LIGHT0, GL_DIFFUSE,  light0_color);
     glLightfv(GL_LIGHT1, GL_POSITION, light1_pos);
     glLightfv(GL_LIGHT1, GL_DIFFUSE,  light1_color);
     glEnable(GL_LIGHT0);
     glEnable(GL_LIGHT1);
     glEnable(GL_LIGHTING);
-    
-    glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
-    glEnable(GL_COLOR_MATERIAL);  
+
+    glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
+    glEnable(GL_COLOR_MATERIAL);
 }
 
+void TestGLCanvas::ResetProjectionMode()
+{
+    // This is normally only necessary if there is more than one wxGLCanvas
+    // or more than one wxGLContext in the application.
+    SetCurrent(*m_glRC);
+
+    int w, h;
+    GetClientSize(&w, &h);
+
+    // It's up to the application code to update the OpenGL viewport settings.
+    // In order to avoid extensive context switching, consider doing this in
+    // OnPaint() rather than here, though.
+    glViewport(0, 0, (GLint) w, (GLint) h);
 
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    gluPerspective(45.0f, (GLfloat)w/h, 1.0, 100.0);
+    glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity();
+}