]>
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"
31 #error Please set wxUSE_GLCANVAS to 1 in setup.h.
36 #ifndef __WXMSW__ // for wxStopWatch, see remark below
37 #if defined(__WXMAC__) && !defined(__DARWIN__)
42 #include <sys/unistd.h>
45 #include <sys/timeb.h>
48 #define ID_NEW_WINDOW 10000
49 #define ID_DEF_ROTATE_LEFT_KEY 10001
50 #define ID_DEF_ROTATE_RIGHT_KEY 10002
52 /*----------------------------------------------------------
53 Control to get a keycode
54 ----------------------------------------------------------*/
55 class ScanCodeCtrl
: public wxTextCtrl
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
);
63 // any class wishing to process wxWindows events must use this macro
66 BEGIN_EVENT_TABLE( ScanCodeCtrl
, wxTextCtrl
)
67 EVT_CHAR( ScanCodeCtrl::OnChar
)
68 EVT_KEY_DOWN( ScanCodeCtrl::OnKeyDown
)
71 ScanCodeCtrl::ScanCodeCtrl( wxWindow
* parent
, wxWindowID id
, int code
,
72 const wxPoint
& pos
, const wxSize
& size
)
73 : wxTextCtrl( parent
, id
, "", pos
, size
)
75 buf
.Printf( "0x%04x", code
);
79 void ScanCodeCtrl::OnKeyDown( wxKeyEvent
& event
)
81 buf
.Printf( "0x%04x", event
.GetKeyCode() );
85 /*------------------------------------------------------------------
86 Dialog for defining a keypress
87 -------------------------------------------------------------------*/
89 class ScanCodeDialog
: public wxDialog
92 ScanCodeDialog( wxWindow
* parent
, wxWindowID id
, const int code
,
93 const wxString
&descr
, const wxString
& title
);
96 ScanCodeCtrl
*m_ScanCode
;
97 wxTextCtrl
*m_Description
;
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) )
104 new wxStaticText( this, -1, "Scancode", wxPoint(4*2,3*2),
106 m_ScanCode
= new ScanCodeCtrl( this, -1, code
, wxPoint(37*2,6*2),
109 new wxStaticText( this, -1, "Description", wxPoint(4*2,24*2),
111 m_Description
= new wxTextCtrl( this, -1, descr
, wxPoint(37*2,27*2),
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),
119 int ScanCodeDialog::GetValue()
122 wxString buf
= m_ScanCode
->GetValue();
123 sscanf( buf
.c_str(), "%i", &code
);
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
)
134 unsigned long secs
,msec
;
136 #if defined(__WXMSW__)
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);
146 // think every unice has gettimeofday
148 gettimeofday( &tv
, (struct timezone
*)NULL
);
150 msec
= tv
.tv_usec
/1000;
156 return( (secs
-*sec_base
)*1000 + msec
);
159 /*----------------------------------------------------------------
160 Implementation of Test-GLCanvas
161 -----------------------------------------------------------------*/
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
)
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
;
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
)
184 m_rright
= WXK_RIGHT
;
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
)
193 m_gllist
= other
.m_gllist
; /* share display list */
195 m_rright
= WXK_RIGHT
;
198 TestGLCanvas::~TestGLCanvas()
202 void TestGLCanvas::Render()
207 if (!GetContext()) return;
211 /* init OpenGL once, but after SetCurrent */
218 glMatrixMode(GL_PROJECTION
);
220 glFrustum(-0.5F
, 0.5F
, -0.5F
, 0.5F
, 1.0F
, 3.0F
);
221 glMatrixMode(GL_MODELVIEW
);
223 /* clear color and depth buffers */
224 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
228 m_gllist
= glGenLists( 1 );
229 glNewList( m_gllist
, GL_COMPILE_AND_EXECUTE
);
230 /* draw six faces of a cube */
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
);
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
);
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
);
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
);
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
);
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
);
260 glCallList( m_gllist
);
266 void TestGLCanvas::OnEnterWindow( wxMouseEvent
& event
)
271 void TestGLCanvas::OnPaint( wxPaintEvent
& event
)
276 void TestGLCanvas::OnSize(wxSizeEvent
& event
)
278 // this is also necessary to update the context on some platforms
279 wxGLCanvas::OnSize(event
);
281 // set GL viewport (not called by wxGLCanvas::OnSize on all platforms...)
283 GetClientSize(&w
, &h
);
289 glViewport(0, 0, (GLint
) w
, (GLint
) h
);
293 void TestGLCanvas::OnEraseBackground(wxEraseEvent
& event
)
295 // Do nothing, to avoid flashing.
298 void TestGLCanvas::InitGL()
302 /* set viewing projection */
303 glMatrixMode(GL_PROJECTION
);
304 glFrustum(-0.5F
, 0.5F
, -0.5F
, 0.5F
, 1.0F
, 3.0F
);
306 /* position viewer */
307 glMatrixMode(GL_MODELVIEW
);
308 glTranslatef(0.0F
, 0.0F
, -2.0F
);
310 /* position object */
311 glRotatef(30.0F
, 1.0F
, 0.0F
, 0.0F
);
312 glRotatef(30.0F
, 0.0F
, 1.0F
, 0.0F
);
314 glEnable(GL_DEPTH_TEST
);
315 glEnable(GL_LIGHTING
);
319 GLfloat
TestGLCanvas::CalcRotateSpeed( unsigned long acceltime
)
323 t
= ((GLfloat
)acceltime
) / 1000.0f
;
335 GLfloat
TestGLCanvas::CalcRotateAngle( unsigned long lasttime
,
336 unsigned long acceltime
)
340 t
= ((GLfloat
)(acceltime
- lasttime
)) / 1000.0f
;
341 s1
= CalcRotateSpeed( lasttime
);
342 s2
= CalcRotateSpeed( acceltime
);
344 return( t
* (s1
+ s2
) * 135.0f
);
347 void TestGLCanvas::Action( long code
, unsigned long lasttime
,
348 unsigned long acceltime
)
350 GLfloat angle
= CalcRotateAngle( lasttime
, acceltime
);
354 else if (code
== m_rright
)
358 void TestGLCanvas::OnKeyDown( wxKeyEvent
& event
)
360 long evkey
= event
.GetKeyCode();
361 if (evkey
== 0) return;
363 if (!m_TimeInitialized
)
365 m_TimeInitialized
= 1;
366 m_xsynct
= event
.m_timeStamp
;
367 m_gsynct
= wxStopWatch(&m_secbase
);
375 unsigned long currTime
= event
.m_timeStamp
- m_xsynct
;
380 m_LastRedraw
= m_StartTime
= m_LastTime
= currTime
;
383 if (currTime
>= m_LastRedraw
) // Redraw:
385 Action( m_Key
, m_LastTime
-m_StartTime
, currTime
-m_StartTime
);
387 #if defined(__WXMAC__) && !defined(__DARWIN__)
388 m_LastRedraw
= currTime
; // wxStopWatch() doesn't work on Mac...
390 m_LastRedraw
= wxStopWatch(&m_secbase
) - m_gsynct
;
392 m_LastTime
= currTime
;
398 void TestGLCanvas::OnKeyUp( wxKeyEvent
& event
)
408 void TestGLCanvas::Rotate( GLfloat deg
)
412 glMatrixMode(GL_MODELVIEW
);
413 glRotatef((GLfloat
)deg
, 0.0F
, 0.0F
, 1.0F
);
418 /* -----------------------------------------------------------------------
420 -------------------------------------------------------------------------*/
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
)
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
)
437 // Intercept menu commands
438 void MyFrame::OnExit(wxCommandEvent
& event
)
443 void MyFrame::OnNewWindow(wxCommandEvent
& event
)
445 MyFrame
*frame
= new MyFrame(NULL
, "Cube OpenGL Demo Clone",
446 wxPoint(50, 50), wxSize(400, 300));
449 frame
->SetIcon(wxIcon("mondrian"));
453 wxMenu
*winMenu
= new wxMenu
;
455 winMenu
->Append(wxID_EXIT
, "&Close");
456 winMenu
->Append(ID_NEW_WINDOW
, "&New" );
457 wxMenuBar
*menuBar
= new wxMenuBar
;
458 menuBar
->Append(winMenu
, "&Window");
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");
465 frame
->SetMenuBar(menuBar
);
467 frame
->m_canvas
= new TestGLCanvas( frame
, *m_canvas
, -1,
468 wxDefaultPosition
, wxDefaultSize
);
474 void MyFrame::OnDefRotateLeftKey(wxCommandEvent
& event
)
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();
482 void MyFrame::OnDefRotateRightKey(wxCommandEvent
& event
)
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();
491 /*------------------------------------------------------------------
492 Application object ( equivalent to main() )
493 ------------------------------------------------------------------ */
497 bool MyApp::OnInit(void)
499 wxLog::SetTraceMask(wxTraceMessages
);
501 // Create the main frame window
502 MyFrame
*frame
= new MyFrame(NULL
, "Cube OpenGL Demo", wxPoint(50, 50),
506 frame
->SetIcon(wxIcon("mondrian"));
510 wxMenu
*winMenu
= new wxMenu
;
512 winMenu
->Append(wxID_EXIT
, "&Close");
513 winMenu
->Append(ID_NEW_WINDOW
, "&New" );
514 wxMenuBar
*menuBar
= new wxMenuBar
;
515 menuBar
->Append(winMenu
, "&Window");
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");
522 frame
->SetMenuBar(menuBar
);
524 frame
->m_canvas
= new TestGLCanvas(frame
, -1, wxDefaultPosition
, wxDefaultSize
);