]>
git.saurik.com Git - wxWidgets.git/blob - samples/opengl/cube/cube.cpp
1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxGLCanvas demo program
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #if defined(__GNUG__) && !defined(__APPLE__)
13 #pragma implementation
17 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
29 #error "OpenGL required: set wxUSE_GLCANVAS to 1 and rebuild the library"
34 #ifndef __WXMSW__ // for wxStopWatch, see remark below
35 #if defined(__WXMAC__) && !defined(__DARWIN__)
40 #include <sys/unistd.h>
43 #include <sys/timeb.h>
46 #define ID_NEW_WINDOW 10000
47 #define ID_DEF_ROTATE_LEFT_KEY 10001
48 #define ID_DEF_ROTATE_RIGHT_KEY 10002
50 /*----------------------------------------------------------
51 Control to get a keycode
52 ----------------------------------------------------------*/
53 class ScanCodeCtrl
: public wxTextCtrl
56 ScanCodeCtrl( wxWindow
* parent
, wxWindowID id
, int code
,
57 const wxPoint
& pos
, const wxSize
& size
);
59 void OnChar( wxKeyEvent
& WXUNUSED(event
) )
64 void OnKeyDown(wxKeyEvent
& event
);
68 // Any class wishing to process wxWidgets events must use this macro
72 BEGIN_EVENT_TABLE( ScanCodeCtrl
, wxTextCtrl
)
73 EVT_CHAR( ScanCodeCtrl::OnChar
)
74 EVT_KEY_DOWN( ScanCodeCtrl::OnKeyDown
)
77 ScanCodeCtrl::ScanCodeCtrl( wxWindow
* parent
, wxWindowID id
, int code
,
78 const wxPoint
& pos
, const wxSize
& size
)
79 : wxTextCtrl( parent
, id
, wxEmptyString
, pos
, size
)
81 SetValue( wxString::Format(wxT("0x%04x"), code
) );
84 void ScanCodeCtrl::OnKeyDown( wxKeyEvent
& event
)
86 SetValue( wxString::Format(wxT("0x%04x"), event
.GetKeyCode()) );
89 /*------------------------------------------------------------------
90 Dialog for defining a keypress
91 -------------------------------------------------------------------*/
93 class ScanCodeDialog
: public wxDialog
96 ScanCodeDialog( wxWindow
* parent
, wxWindowID id
, const int code
,
97 const wxString
&descr
, const wxString
& title
);
102 ScanCodeCtrl
*m_ScanCode
;
103 wxTextCtrl
*m_Description
;
106 ScanCodeDialog::ScanCodeDialog( wxWindow
* parent
, wxWindowID id
,
107 const int code
, const wxString
&descr
, const wxString
& title
)
108 : wxDialog( parent
, id
, title
, wxDefaultPosition
, wxSize(96*2,76*2) )
110 new wxStaticText( this, wxID_ANY
, _T("Scancode"), wxPoint(4*2,3*2),
112 m_ScanCode
= new ScanCodeCtrl( this, wxID_ANY
, code
, wxPoint(37*2,6*2),
115 new wxStaticText( this, wxID_ANY
, _T("Description"), wxPoint(4*2,24*2),
117 m_Description
= new wxTextCtrl( this, wxID_ANY
, descr
, wxPoint(37*2,27*2),
120 new wxButton( this, wxID_OK
, _T("Ok"), wxPoint(20*2,50*2), wxSize(20*2,13*2) );
121 new wxButton( this, wxID_CANCEL
, _T("Cancel"), wxPoint(44*2,50*2),
125 int ScanCodeDialog::GetValue()
128 wxString buf
= m_ScanCode
->GetValue();
129 wxSscanf( buf
.c_str(), _T("%i"), &code
);
133 /*----------------------------------------------------------------------
134 Utility function to get the elapsed time (in msec) since a given point
135 in time (in sec) (because current version of wxGetElapsedTime doesn´t
136 works right with glibc-2.1 and linux, at least for me)
137 -----------------------------------------------------------------------*/
138 unsigned long wxStopWatch( unsigned long *sec_base
)
140 unsigned long secs
,msec
;
142 #if defined(__WXMSW__)
147 #elif defined(__WXMAC__) && !defined(__DARWIN__)
148 wxLongLong tl
= wxGetLocalTimeMillis();
149 secs
= (unsigned long) (tl
.GetValue() / 1000);
150 msec
= (unsigned long) (tl
.GetValue() - secs
*1000);
152 // think every unice has gettimeofday
154 gettimeofday( &tv
, (struct timezone
*)NULL
);
156 msec
= tv
.tv_usec
/1000;
162 return( (secs
-*sec_base
)*1000 + msec
);
165 /*----------------------------------------------------------------
166 Implementation of Test-GLCanvas
167 -----------------------------------------------------------------*/
169 BEGIN_EVENT_TABLE(TestGLCanvas
, wxGLCanvas
)
170 EVT_SIZE(TestGLCanvas::OnSize
)
171 EVT_PAINT(TestGLCanvas::OnPaint
)
172 EVT_ERASE_BACKGROUND(TestGLCanvas::OnEraseBackground
)
173 EVT_KEY_DOWN( TestGLCanvas::OnKeyDown
)
174 EVT_KEY_UP( TestGLCanvas::OnKeyUp
)
175 EVT_ENTER_WINDOW( TestGLCanvas::OnEnterWindow
)
178 unsigned long TestGLCanvas::m_secbase
= 0;
179 int TestGLCanvas::m_TimeInitialized
= 0;
180 unsigned long TestGLCanvas::m_xsynct
;
181 unsigned long TestGLCanvas::m_gsynct
;
183 TestGLCanvas::TestGLCanvas(wxWindow
*parent
, wxWindowID id
,
184 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
)
185 : wxGLCanvas(parent
, (wxGLCanvas
*) NULL
, id
, pos
, size
, style
, name
)
190 m_rright
= WXK_RIGHT
;
193 TestGLCanvas::TestGLCanvas(wxWindow
*parent
, const TestGLCanvas
&other
,
194 wxWindowID id
, const wxPoint
& pos
, const wxSize
& size
, long style
,
195 const wxString
& name
)
196 : wxGLCanvas(parent
, other
.GetContext(), id
, pos
, size
, style
, name
)
199 m_gllist
= other
.m_gllist
; // share display list
201 m_rright
= WXK_RIGHT
;
204 TestGLCanvas::~TestGLCanvas()
208 void TestGLCanvas::Render()
213 if (!GetContext()) return;
217 // Init OpenGL once, but after SetCurrent
224 glMatrixMode(GL_PROJECTION
);
226 glFrustum(-0.5f
, 0.5f
, -0.5f
, 0.5f
, 1.0f
, 3.0f
);
227 glMatrixMode(GL_MODELVIEW
);
229 /* clear color and depth buffers */
230 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
234 m_gllist
= glGenLists( 1 );
235 glNewList( m_gllist
, GL_COMPILE_AND_EXECUTE
);
236 /* draw six faces of a cube */
238 glNormal3f( 0.0f
, 0.0f
, 1.0f
);
239 glVertex3f( 0.5f
, 0.5f
, 0.5f
); glVertex3f(-0.5f
, 0.5f
, 0.5f
);
240 glVertex3f(-0.5f
,-0.5f
, 0.5f
); glVertex3f( 0.5f
,-0.5f
, 0.5f
);
242 glNormal3f( 0.0f
, 0.0f
,-1.0f
);
243 glVertex3f(-0.5f
,-0.5f
,-0.5f
); glVertex3f(-0.5f
, 0.5f
,-0.5f
);
244 glVertex3f( 0.5f
, 0.5f
,-0.5f
); glVertex3f( 0.5f
,-0.5f
,-0.5f
);
246 glNormal3f( 0.0f
, 1.0f
, 0.0f
);
247 glVertex3f( 0.5f
, 0.5f
, 0.5f
); glVertex3f( 0.5f
, 0.5f
,-0.5f
);
248 glVertex3f(-0.5f
, 0.5f
,-0.5f
); glVertex3f(-0.5f
, 0.5f
, 0.5f
);
250 glNormal3f( 0.0f
,-1.0f
, 0.0f
);
251 glVertex3f(-0.5f
,-0.5f
,-0.5f
); glVertex3f( 0.5f
,-0.5f
,-0.5f
);
252 glVertex3f( 0.5f
,-0.5f
, 0.5f
); glVertex3f(-0.5f
,-0.5f
, 0.5f
);
254 glNormal3f( 1.0f
, 0.0f
, 0.0f
);
255 glVertex3f( 0.5f
, 0.5f
, 0.5f
); glVertex3f( 0.5f
,-0.5f
, 0.5f
);
256 glVertex3f( 0.5f
,-0.5f
,-0.5f
); glVertex3f( 0.5f
, 0.5f
,-0.5f
);
258 glNormal3f(-1.0f
, 0.0f
, 0.0f
);
259 glVertex3f(-0.5f
,-0.5f
,-0.5f
); glVertex3f(-0.5f
,-0.5f
, 0.5f
);
260 glVertex3f(-0.5f
, 0.5f
, 0.5f
); glVertex3f(-0.5f
, 0.5f
,-0.5f
);
267 glCallList(m_gllist
);
274 void TestGLCanvas::OnEnterWindow( wxMouseEvent
& WXUNUSED(event
) )
279 void TestGLCanvas::OnPaint( wxPaintEvent
& WXUNUSED(event
) )
284 void TestGLCanvas::OnSize(wxSizeEvent
& event
)
286 // this is also necessary to update the context on some platforms
287 wxGLCanvas::OnSize(event
);
289 // set GL viewport (not called by wxGLCanvas::OnSize on all platforms...)
291 GetClientSize(&w
, &h
);
297 glViewport(0, 0, (GLint
) w
, (GLint
) h
);
301 void TestGLCanvas::OnEraseBackground(wxEraseEvent
& WXUNUSED(event
))
303 // Do nothing, to avoid flashing.
306 void TestGLCanvas::InitGL()
310 /* set viewing projection */
311 glMatrixMode(GL_PROJECTION
);
312 glFrustum(-0.5f
, 0.5f
, -0.5f
, 0.5f
, 1.0f
, 3.0f
);
314 /* position viewer */
315 glMatrixMode(GL_MODELVIEW
);
316 glTranslatef(0.0f
, 0.0f
, -2.0f
);
318 /* position object */
319 glRotatef(30.0f
, 1.0f
, 0.0f
, 0.0f
);
320 glRotatef(30.0f
, 0.0f
, 1.0f
, 0.0f
);
322 glEnable(GL_DEPTH_TEST
);
323 glEnable(GL_LIGHTING
);
327 GLfloat
TestGLCanvas::CalcRotateSpeed( unsigned long acceltime
)
331 t
= ((GLfloat
)acceltime
) / 1000.0f
;
343 GLfloat
TestGLCanvas::CalcRotateAngle( unsigned long lasttime
,
344 unsigned long acceltime
)
348 t
= ((GLfloat
)(acceltime
- lasttime
)) / 1000.0f
;
349 s1
= CalcRotateSpeed( lasttime
);
350 s2
= CalcRotateSpeed( acceltime
);
352 return( t
* (s1
+ s2
) * 135.0f
);
355 void TestGLCanvas::Action( long code
, unsigned long lasttime
,
356 unsigned long acceltime
)
358 GLfloat angle
= CalcRotateAngle( lasttime
, acceltime
);
362 else if (code
== m_rright
)
366 void TestGLCanvas::OnKeyDown( wxKeyEvent
& event
)
368 long evkey
= event
.GetKeyCode();
369 if (evkey
== 0) return;
371 if (!m_TimeInitialized
)
373 m_TimeInitialized
= 1;
374 m_xsynct
= event
.m_timeStamp
;
375 m_gsynct
= wxStopWatch(&m_secbase
);
383 unsigned long currTime
= event
.m_timeStamp
- m_xsynct
;
388 m_LastRedraw
= m_StartTime
= m_LastTime
= currTime
;
391 if (currTime
>= m_LastRedraw
) // Redraw:
393 Action( m_Key
, m_LastTime
-m_StartTime
, currTime
-m_StartTime
);
395 #if defined(__WXMAC__) && !defined(__DARWIN__)
396 m_LastRedraw
= currTime
; // wxStopWatch() doesn't work on Mac...
398 m_LastRedraw
= wxStopWatch(&m_secbase
) - m_gsynct
;
400 m_LastTime
= currTime
;
406 void TestGLCanvas::OnKeyUp( wxKeyEvent
& event
)
416 void TestGLCanvas::Rotate( GLfloat deg
)
420 glMatrixMode(GL_MODELVIEW
);
421 glRotatef((GLfloat
)deg
, 0.0f
, 0.0f
, 1.0f
);
426 /* -----------------------------------------------------------------------
428 -------------------------------------------------------------------------*/
430 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
431 EVT_MENU(wxID_EXIT
, MyFrame::OnExit
)
432 EVT_MENU( ID_NEW_WINDOW
, MyFrame::OnNewWindow
)
433 EVT_MENU( ID_DEF_ROTATE_LEFT_KEY
, MyFrame::OnDefRotateLeftKey
)
434 EVT_MENU( ID_DEF_ROTATE_RIGHT_KEY
, MyFrame::OnDefRotateRightKey
)
437 // My frame constructor
438 MyFrame::MyFrame(wxWindow
*parent
, const wxString
& title
, const wxPoint
& pos
,
439 const wxSize
& size
, long style
)
440 : wxFrame(parent
, wxID_ANY
, title
, pos
, size
, style
)
445 // Intercept menu commands
446 void MyFrame::OnExit( wxCommandEvent
& WXUNUSED(event
) )
448 // true is to force the frame to close
452 /*static*/ MyFrame
*MyFrame::Create(MyFrame
*parentFrame
, bool isCloneWindow
)
454 wxString str
= wxT("wxWidgets OpenGL Cube Sample");
455 if (isCloneWindow
) str
+= wxT(" - Clone");
457 MyFrame
*frame
= new MyFrame(NULL
, str
, wxDefaultPosition
,
462 frame
->SetIcon(wxIcon(_T("mondrian")));
466 wxMenu
*winMenu
= new wxMenu
;
468 winMenu
->Append(wxID_EXIT
, _T("&Close"));
469 winMenu
->Append(ID_NEW_WINDOW
, _T("&New") );
470 wxMenuBar
*menuBar
= new wxMenuBar
;
471 menuBar
->Append(winMenu
, _T("&Window"));
473 winMenu
= new wxMenu
;
474 winMenu
->Append(ID_DEF_ROTATE_LEFT_KEY
, _T("Rotate &left"));
475 winMenu
->Append(ID_DEF_ROTATE_RIGHT_KEY
, _T("Rotate &right"));
476 menuBar
->Append(winMenu
, _T("&Key"));
478 frame
->SetMenuBar(menuBar
);
482 frame
->m_canvas
= new TestGLCanvas( frame
, parentFrame
->m_canvas
,
483 wxID_ANY
, wxDefaultPosition
, wxDefaultSize
);
487 frame
->m_canvas
= new TestGLCanvas(frame
, wxID_ANY
,
488 wxDefaultPosition
, wxDefaultSize
);
497 void MyFrame::OnNewWindow( wxCommandEvent
& WXUNUSED(event
) )
499 (void) Create(this, true);
502 void MyFrame::OnDefRotateLeftKey( wxCommandEvent
& WXUNUSED(event
) )
504 ScanCodeDialog
dial( this, wxID_ANY
, m_canvas
->m_rleft
,
505 wxString(_T("Left")), _T("Define key") );
507 int result
= dial
.ShowModal();
509 if( result
== wxID_OK
)
510 m_canvas
->m_rleft
= dial
.GetValue();
513 void MyFrame::OnDefRotateRightKey( wxCommandEvent
& WXUNUSED(event
) )
515 ScanCodeDialog
dial( this, wxID_ANY
, m_canvas
->m_rright
,
516 wxString(_T("Right")), _T("Define key") );
518 int result
= dial
.ShowModal();
520 if( result
== wxID_OK
)
521 m_canvas
->m_rright
= dial
.GetValue();
524 /*------------------------------------------------------------------
525 Application object ( equivalent to main() )
526 ------------------------------------------------------------------ */
532 // Create the main frame window
533 (void) MyFrame::Create(NULL
);