home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / samples / opengl / cube / cube.cpp next >
C/C++ Source or Header  |  2002-09-01  |  15KB  |  531 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        cube.cpp
  3. // Purpose:     wxGLCanvas demo program
  4. // Author:      Julian Smart
  5. // Modified by:
  6. // Created:     04/01/98
  7. // RCS-ID:      $Id: cube.cpp,v 1.9 2002/08/31 22:30:50 GD Exp $
  8. // Copyright:   (c) Julian Smart
  9. // Licence:     wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. #if defined(__GNUG__) && !defined(__APPLE__)
  13. #pragma implementation
  14. #pragma interface
  15. #endif
  16.  
  17. // For compilers that support precompilation, includes "wx.h".
  18. #include "wx/wxprec.h"
  19.  
  20. #ifdef __BORLANDC__
  21. #pragma hdrstop
  22. #endif
  23.  
  24. #ifndef WX_PRECOMP
  25. #include "wx/wx.h"
  26. #endif
  27.  
  28. #include "wx/log.h"
  29.  
  30. #if !wxUSE_GLCANVAS
  31. #error Please set wxUSE_GLCANVAS to 1 in setup.h.
  32. #endif
  33.  
  34. #include "cube.h"
  35.  
  36. #ifndef __WXMSW__     // for wxStopWatch, see remark below
  37.   #if defined(__WXMAC__) && !defined(__DARWIN__)
  38.     #include <utime.h>
  39.     #include <unistd.h>
  40.   #else
  41.     #include <sys/time.h>
  42.     #include <sys/unistd.h>
  43.   #endif
  44. #else
  45. #include <sys/timeb.h>
  46. #endif
  47.  
  48. #define ID_NEW_WINDOW 10000
  49. #define ID_DEF_ROTATE_LEFT_KEY 10001
  50. #define ID_DEF_ROTATE_RIGHT_KEY 10002
  51.  
  52. /*----------------------------------------------------------
  53.   Control to get a keycode
  54.   ----------------------------------------------------------*/
  55. class ScanCodeCtrl : public wxTextCtrl
  56. {
  57. public:
  58.   ScanCodeCtrl( wxWindow* parent, wxWindowID id, int code,
  59.                 const wxPoint& pos, const wxSize& size );
  60.   void OnChar( wxKeyEvent& event ) { } /* do nothing */
  61.   void OnKeyDown(wxKeyEvent& event);
  62. private:
  63. // any class wishing to process wxWindows events must use this macro
  64.   DECLARE_EVENT_TABLE()
  65. };
  66. BEGIN_EVENT_TABLE( ScanCodeCtrl, wxTextCtrl )
  67.   EVT_CHAR( ScanCodeCtrl::OnChar )
  68.   EVT_KEY_DOWN( ScanCodeCtrl::OnKeyDown )
  69. END_EVENT_TABLE()
  70.  
  71. ScanCodeCtrl::ScanCodeCtrl( wxWindow* parent, wxWindowID id, int code,
  72.                              const wxPoint& pos, const wxSize& size )
  73.                   : wxTextCtrl( parent, id, "", pos, size )
  74. { wxString buf;
  75.   buf.Printf( "0x%04x", code );
  76.   SetValue( buf );
  77. }
  78.  
  79. void ScanCodeCtrl::OnKeyDown( wxKeyEvent& event )
  80. { wxString buf;
  81.   buf.Printf( "0x%04x", event.KeyCode() );
  82.   SetValue( buf );
  83. }
  84.  
  85. /*------------------------------------------------------------------
  86.  Dialog for defining a keypress
  87. -------------------------------------------------------------------*/
  88.  
  89. class ScanCodeDialog : public wxDialog
  90. {
  91. public:
  92.   ScanCodeDialog( wxWindow* parent, wxWindowID id, const int code,
  93.                   const wxString &descr, const wxString& title );
  94.   int GetValue();
  95. private:
  96.   ScanCodeCtrl       *m_ScanCode;
  97.   wxTextCtrl         *m_Description;
  98. };
  99.  
  100. ScanCodeDialog::ScanCodeDialog( wxWindow* parent, wxWindowID id,
  101.                const int code, const wxString &descr, const wxString& title )
  102.           : wxDialog( parent, id, title, wxPoint(-1, -1), wxSize(96*2,76*2) )
  103. {
  104.   new wxStaticText( this, -1, "Scancode", wxPoint(4*2,3*2),
  105.                     wxSize(31*2,12*2) );
  106.   m_ScanCode = new ScanCodeCtrl( this, -1, code, wxPoint(37*2,6*2),
  107.                                  wxSize(53*2,14*2) );
  108.  
  109.   new wxStaticText( this, -1, "Description", wxPoint(4*2,24*2),
  110.                     wxSize(32*2,12*2) );
  111.   m_Description = new wxTextCtrl( this, -1, descr, wxPoint(37*2,27*2),
  112.                                   wxSize(53*2,14*2) );
  113.  
  114.   new wxButton( this, wxID_OK, "Ok", wxPoint(20*2,50*2), wxSize(20*2,13*2) );
  115.   new wxButton( this, wxID_CANCEL, "Cancel", wxPoint(44*2,50*2),
  116.                 wxSize(25*2,13*2) );
  117. }
  118.  
  119. int ScanCodeDialog::GetValue()
  120. {
  121.   int code;
  122.   wxString buf = m_ScanCode->GetValue();
  123.   sscanf( buf.c_str(), "%i", &code );
  124.   return( code );
  125. }
  126.  
  127. /*----------------------------------------------------------------------
  128.   Utility function to get the elapsed time (in msec) since a given point
  129.   in time (in sec)  (because current version of wxGetElapsedTime doesn┤t
  130.   works right with glibc-2.1 and linux, at least for me)
  131. -----------------------------------------------------------------------*/
  132. unsigned long wxStopWatch( unsigned long *sec_base )
  133. {
  134.   unsigned long secs,msec;
  135.  
  136. #if defined(__WXMSW__)
  137.   struct timeb tb;
  138.   ftime( &tb );
  139.   secs = tb.time;
  140.   msec = tb.millitm;
  141. #elif defined(__WXMAC__) && !defined(__DARWIN__)
  142.   wxLongLong tl = wxGetLocalTimeMillis();
  143.   secs = (unsigned long) (tl.GetValue() / 1000);
  144.   msec = (unsigned long) (tl.GetValue() - secs*1000);
  145. #else
  146.   // think every unice has gettimeofday
  147.   struct timeval tv;
  148.   gettimeofday( &tv, (struct timezone *)NULL );
  149.   secs = tv.tv_sec;
  150.   msec = tv.tv_usec/1000;
  151. #endif
  152.  
  153.   if( *sec_base == 0 )
  154.     *sec_base = secs;
  155.  
  156.   return( (secs-*sec_base)*1000 + msec );
  157. }
  158.  
  159. /*----------------------------------------------------------------
  160.   Implementation of Test-GLCanvas
  161. -----------------------------------------------------------------*/
  162.  
  163. BEGIN_EVENT_TABLE(TestGLCanvas, wxGLCanvas)
  164.   EVT_SIZE(TestGLCanvas::OnSize)
  165.   EVT_PAINT(TestGLCanvas::OnPaint)
  166.   EVT_ERASE_BACKGROUND(TestGLCanvas::OnEraseBackground)
  167.   EVT_KEY_DOWN( TestGLCanvas::OnKeyDown )
  168.   EVT_KEY_UP( TestGLCanvas::OnKeyUp )
  169.   EVT_ENTER_WINDOW( TestGLCanvas::OnEnterWindow )
  170. END_EVENT_TABLE()
  171.  
  172. unsigned long  TestGLCanvas::m_secbase = 0;
  173. int            TestGLCanvas::m_TimeInitialized = 0;
  174. unsigned long  TestGLCanvas::m_xsynct;
  175. unsigned long  TestGLCanvas::m_gsynct;
  176.  
  177. TestGLCanvas::TestGLCanvas(wxWindow *parent, wxWindowID id,
  178.     const wxPoint& pos, const wxSize& size, long style, const wxString& name):
  179.   wxGLCanvas(parent, (wxGLCanvas*) NULL, id, pos, size, style, name )
  180. {
  181.     m_init = FALSE;
  182.     m_gllist = 0;
  183.     m_rleft = WXK_LEFT;
  184.     m_rright = WXK_RIGHT;
  185. }
  186.  
  187. TestGLCanvas::TestGLCanvas(wxWindow *parent, const TestGLCanvas &other,
  188.     wxWindowID id, const wxPoint& pos, const wxSize& size, long style,
  189.     const wxString& name ) :
  190.       wxGLCanvas(parent, other.GetContext(), id, pos, size, style, name  )
  191. {
  192.     m_init = FALSE;
  193.     m_gllist = other.m_gllist;    /* share display list */
  194.     m_rleft = WXK_LEFT;
  195.     m_rright = WXK_RIGHT;
  196. }
  197.  
  198. TestGLCanvas::~TestGLCanvas()
  199. {
  200. }
  201.  
  202. void TestGLCanvas::Render()
  203. {
  204.     wxPaintDC dc(this);
  205.  
  206. #ifndef __WXMOTIF__
  207.     if (!GetContext()) return;
  208. #endif
  209.  
  210.     SetCurrent();
  211.     /* init OpenGL once, but after SetCurrent */
  212.     if (!m_init)
  213.     {
  214.         InitGL();
  215.         m_init = TRUE;
  216.     }
  217.  
  218.     glMatrixMode(GL_PROJECTION);
  219.     glLoadIdentity();
  220.     glFrustum(-0.5F, 0.5F, -0.5F, 0.5F, 1.0F, 3.0F);
  221.     glMatrixMode(GL_MODELVIEW);
  222.  
  223.     /* clear color and depth buffers */
  224.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  225.  
  226.   if( m_gllist == 0 )
  227.   {
  228.     m_gllist = glGenLists( 1 );
  229.     glNewList( m_gllist, GL_COMPILE_AND_EXECUTE );
  230.     /* draw six faces of a cube */
  231.     glBegin(GL_QUADS);
  232.     glNormal3f( 0.0F, 0.0F, 1.0F);
  233.     glVertex3f( 0.5F, 0.5F, 0.5F); glVertex3f(-0.5F, 0.5F, 0.5F);
  234.     glVertex3f(-0.5F,-0.5F, 0.5F); glVertex3f( 0.5F,-0.5F, 0.5F);
  235.  
  236.     glNormal3f( 0.0F, 0.0F,-1.0F);
  237.     glVertex3f(-0.5F,-0.5F,-0.5F); glVertex3f(-0.5F, 0.5F,-0.5F);
  238.     glVertex3f( 0.5F, 0.5F,-0.5F); glVertex3f( 0.5F,-0.5F,-0.5F);
  239.  
  240.     glNormal3f( 0.0F, 1.0F, 0.0F);
  241.     glVertex3f( 0.5F, 0.5F, 0.5F); glVertex3f( 0.5F, 0.5F,-0.5F);
  242.     glVertex3f(-0.5F, 0.5F,-0.5F); glVertex3f(-0.5F, 0.5F, 0.5F);
  243.  
  244.     glNormal3f( 0.0F,-1.0F, 0.0F);
  245.     glVertex3f(-0.5F,-0.5F,-0.5F); glVertex3f( 0.5F,-0.5F,-0.5F);
  246.     glVertex3f( 0.5F,-0.5F, 0.5F); glVertex3f(-0.5F,-0.5F, 0.5F);
  247.  
  248.     glNormal3f( 1.0F, 0.0F, 0.0F);
  249.     glVertex3f( 0.5F, 0.5F, 0.5F); glVertex3f( 0.5F,-0.5F, 0.5F);
  250.     glVertex3f( 0.5F,-0.5F,-0.5F); glVertex3f( 0.5F, 0.5F,-0.5F);
  251.  
  252.     glNormal3f(-1.0F, 0.0F, 0.0F);
  253.     glVertex3f(-0.5F,-0.5F,-0.5F); glVertex3f(-0.5F,-0.5F, 0.5F);
  254.     glVertex3f(-0.5F, 0.5F, 0.5F); glVertex3f(-0.5F, 0.5F,-0.5F);
  255.     glEnd();
  256.  
  257.     glEndList();
  258.   }
  259.   else
  260.     glCallList( m_gllist );
  261.  
  262.   glFlush();
  263.   SwapBuffers();
  264. }
  265.  
  266. void TestGLCanvas::OnEnterWindow( wxMouseEvent& event )
  267. {
  268.     SetFocus();
  269. }
  270.  
  271. void TestGLCanvas::OnPaint( wxPaintEvent& event )
  272. {
  273.     Render();
  274. }
  275.  
  276. void TestGLCanvas::OnSize(wxSizeEvent& event)
  277. {
  278.     // this is also necessary to update the context on some platforms
  279.     wxGLCanvas::OnSize(event);
  280.  
  281.     // set GL viewport (not called by wxGLCanvas::OnSize on all platforms...)
  282.     int w, h;
  283.     GetClientSize(&w, &h);
  284. #ifndef __WXMOTIF__
  285.     if (GetContext())
  286. #endif
  287.     {
  288.         SetCurrent();
  289.         glViewport(0, 0, (GLint) w, (GLint) h);
  290.     }
  291. }
  292.  
  293. void TestGLCanvas::OnEraseBackground(wxEraseEvent& event)
  294. {
  295.   // Do nothing, to avoid flashing.
  296. }
  297.  
  298. void TestGLCanvas::InitGL()
  299. {
  300.     SetCurrent();
  301.  
  302.     /* set viewing projection */
  303.     glMatrixMode(GL_PROJECTION);
  304.     glFrustum(-0.5F, 0.5F, -0.5F, 0.5F, 1.0F, 3.0F);
  305.  
  306.     /* position viewer */
  307.     glMatrixMode(GL_MODELVIEW);
  308.     glTranslatef(0.0F, 0.0F, -2.0F);
  309.  
  310.     /* position object */
  311.     glRotatef(30.0F, 1.0F, 0.0F, 0.0F);
  312.     glRotatef(30.0F, 0.0F, 1.0F, 0.0F);
  313.  
  314.     glEnable(GL_DEPTH_TEST);
  315.     glEnable(GL_LIGHTING);
  316.     glEnable(GL_LIGHT0);
  317. }
  318.  
  319. GLfloat TestGLCanvas::CalcRotateSpeed( unsigned long acceltime )
  320. {
  321.   GLfloat t,v;
  322.  
  323.   t = ((GLfloat)acceltime) / 1000.0f;
  324.  
  325.   if( t < 0.5f )
  326.     v = t;
  327.   else if( t < 1.0f )
  328.     v = t * (2.0f - t);
  329.   else
  330.     v = 0.75f;
  331.  
  332.   return(v);
  333. }
  334.  
  335. GLfloat TestGLCanvas::CalcRotateAngle( unsigned long lasttime,
  336.                                   unsigned long acceltime )
  337. {
  338.     GLfloat t,s1,s2;
  339.  
  340.     t = ((GLfloat)(acceltime - lasttime)) / 1000.0f;
  341.     s1 = CalcRotateSpeed( lasttime );
  342.     s2 = CalcRotateSpeed( acceltime );
  343.  
  344.     return( t * (s1 + s2) * 135.0f );
  345. }
  346.  
  347. void TestGLCanvas::Action( long code, unsigned long lasttime,
  348.                            unsigned long acceltime )
  349. {
  350.     GLfloat angle = CalcRotateAngle( lasttime, acceltime );
  351.  
  352.     if (code == m_rleft)
  353.         Rotate( angle );
  354.     else if (code == m_rright)
  355.             Rotate( -angle );
  356. }
  357.  
  358. void TestGLCanvas::OnKeyDown( wxKeyEvent& event )
  359. {
  360.     long evkey = event.KeyCode();
  361.     if (evkey == 0) return;
  362.  
  363.     if (!m_TimeInitialized)
  364.     {
  365.         m_TimeInitialized = 1;
  366.         m_xsynct = event.m_timeStamp;
  367.         m_gsynct = wxStopWatch(&m_secbase);
  368.  
  369.         m_Key = evkey;
  370.         m_StartTime = 0;
  371.         m_LastTime = 0;
  372.         m_LastRedraw = 0;
  373.     }
  374.  
  375.     unsigned long currTime = event.m_timeStamp - m_xsynct;
  376.  
  377.     if (evkey != m_Key)
  378.     {
  379.         m_Key = evkey;
  380.         m_LastRedraw = m_StartTime = m_LastTime = currTime;
  381.     }
  382.  
  383.     if (currTime >= m_LastRedraw)      // Redraw:
  384.     {
  385.         Action( m_Key, m_LastTime-m_StartTime, currTime-m_StartTime );
  386.  
  387. #if defined(__WXMAC__) && !defined(__DARWIN__)
  388.         m_LastRedraw = currTime;    // wxStopWatch() doesn't work on Mac...
  389. #else
  390.         m_LastRedraw = wxStopWatch(&m_secbase) - m_gsynct;
  391. #endif
  392.         m_LastTime = currTime;
  393.     }
  394.  
  395.     event.Skip();
  396. }
  397.  
  398. void TestGLCanvas::OnKeyUp( wxKeyEvent& event )
  399. {
  400.     m_Key = 0;
  401.     m_StartTime = 0;
  402.     m_LastTime = 0;
  403.     m_LastRedraw = 0;
  404.  
  405.     event.Skip();
  406. }
  407.  
  408. void TestGLCanvas::Rotate( GLfloat deg )
  409. {
  410.     SetCurrent();
  411.  
  412.     glMatrixMode(GL_MODELVIEW);
  413.     glRotatef((GLfloat)deg, 0.0F, 0.0F, 1.0F);
  414.     Refresh(FALSE);
  415. }
  416.  
  417.  
  418. /* -----------------------------------------------------------------------
  419.   Main Window
  420. -------------------------------------------------------------------------*/
  421.  
  422. BEGIN_EVENT_TABLE(MyFrame, wxFrame)
  423.     EVT_MENU(wxID_EXIT, MyFrame::OnExit)
  424.     EVT_MENU( ID_NEW_WINDOW, MyFrame::OnNewWindow)
  425.     EVT_MENU( ID_DEF_ROTATE_LEFT_KEY, MyFrame::OnDefRotateLeftKey)
  426.     EVT_MENU( ID_DEF_ROTATE_RIGHT_KEY, MyFrame::OnDefRotateRightKey)
  427. END_EVENT_TABLE()
  428.  
  429. // My frame constructor
  430. MyFrame::MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos,
  431.                  const wxSize& size, long style)
  432.          : wxFrame(frame, -1, title, pos, size, style)
  433. {
  434.     m_canvas = NULL;
  435. }
  436.  
  437. // Intercept menu commands
  438. void MyFrame::OnExit(wxCommandEvent& event)
  439. {
  440.     Destroy();
  441. }
  442.  
  443. void MyFrame::OnNewWindow(wxCommandEvent& event)
  444. {
  445.   MyFrame *frame = new MyFrame(NULL, "Cube OpenGL Demo Clone",
  446.                                wxPoint(50, 50), wxSize(400, 300));
  447.   // Give it an icon
  448. #ifdef __WXMSW__
  449.   frame->SetIcon(wxIcon("mondrian"));
  450. #endif
  451.  
  452.   // Make a menubar
  453.   wxMenu *winMenu = new wxMenu;
  454.  
  455.   winMenu->Append(wxID_EXIT, "&Close");
  456.   winMenu->Append(ID_NEW_WINDOW, "&New" );
  457.   wxMenuBar *menuBar = new wxMenuBar;
  458.   menuBar->Append(winMenu, "&Window");
  459.  
  460.   winMenu = new wxMenu;
  461.   winMenu->Append(ID_DEF_ROTATE_LEFT_KEY, "Rotate &left");
  462.   winMenu->Append(ID_DEF_ROTATE_RIGHT_KEY, "Rotate &right");
  463.   menuBar->Append(winMenu, "&Key");
  464.  
  465.   frame->SetMenuBar(menuBar);
  466.  
  467.   frame->m_canvas = new TestGLCanvas( frame, *m_canvas, -1,
  468.                wxDefaultPosition, wxDefaultSize );
  469.  
  470.   // Show the frame
  471.   frame->Show(TRUE);
  472. }
  473.  
  474. void MyFrame::OnDefRotateLeftKey(wxCommandEvent& event)
  475. {
  476.   ScanCodeDialog dial( this, -1, m_canvas->m_rleft,
  477.                        wxString("Left"), "Define key" );
  478.   int result = dial.ShowModal();
  479.   if( result == wxID_OK )
  480.     m_canvas->m_rleft = dial.GetValue();
  481. }
  482. void MyFrame::OnDefRotateRightKey(wxCommandEvent& event)
  483. {
  484.   ScanCodeDialog dial( this, -1, m_canvas->m_rright,
  485.                        wxString("Right"), "Define key" );
  486.   int result = dial.ShowModal();
  487.   if( result == wxID_OK )
  488.     m_canvas->m_rright = dial.GetValue();
  489. }
  490.  
  491. /*------------------------------------------------------------------
  492.   Application object ( equivalent to main() )
  493. ------------------------------------------------------------------ */
  494.  
  495. IMPLEMENT_APP(MyApp)
  496.  
  497. bool MyApp::OnInit(void)
  498. {
  499.   wxLog::SetTraceMask(wxTraceMessages);
  500.  
  501.   // Create the main frame window
  502.   MyFrame *frame = new MyFrame(NULL, "Cube OpenGL Demo", wxPoint(50, 50),
  503.                                wxSize(400, 300));
  504.   // Give it an icon
  505. #ifdef wx_msw
  506.   frame->SetIcon(wxIcon("mondrian"));
  507. #endif
  508.  
  509.   // Make a menubar
  510.   wxMenu *winMenu = new wxMenu;
  511.  
  512.   winMenu->Append(wxID_EXIT, "&Close");
  513.   winMenu->Append(ID_NEW_WINDOW, "&New" );
  514.   wxMenuBar *menuBar = new wxMenuBar;
  515.   menuBar->Append(winMenu, "&Window");
  516.  
  517.   winMenu = new wxMenu;
  518.   winMenu->Append(ID_DEF_ROTATE_LEFT_KEY, "Rotate &left");
  519.   winMenu->Append(ID_DEF_ROTATE_RIGHT_KEY, "Rotate &right");
  520.   menuBar->Append(winMenu, "&Key");
  521.  
  522.   frame->SetMenuBar(menuBar);
  523.  
  524.   frame->m_canvas = new TestGLCanvas(frame, -1, wxDefaultPosition, wxDefaultSize);
  525.  
  526.   // Show the frame
  527.   frame->Show(TRUE);
  528.  
  529.   return TRUE;
  530. }
  531.