]>
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 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
24 #error "OpenGL required: set wxUSE_GLCANVAS to 1 and rebuild the library"
28 #include "../../sample.xpm"
30 #ifndef __WXMSW__ // for StopWatch, see remark below
31 #if defined(__WXMAC__) && !defined(__DARWIN__)
36 #include <sys/unistd.h>
39 #include <sys/timeb.h>
42 #define ID_NEW_WINDOW 10000
43 #define ID_DEF_ROTATE_LEFT_KEY 10001
44 #define ID_DEF_ROTATE_RIGHT_KEY 10002
46 /*----------------------------------------------------------
47 Control to get a keycode
48 ----------------------------------------------------------*/
49 class ScanCodeCtrl
: public wxTextCtrl
52 ScanCodeCtrl( wxWindow
* parent
, wxWindowID id
, int code
,
53 const wxPoint
& pos
, const wxSize
& size
);
55 void OnChar( wxKeyEvent
& WXUNUSED(event
) )
60 void OnKeyDown(wxKeyEvent
& event
);
64 // Any class wishing to process wxWidgets events must use this macro
68 BEGIN_EVENT_TABLE( ScanCodeCtrl
, wxTextCtrl
)
69 EVT_CHAR( ScanCodeCtrl::OnChar
)
70 EVT_KEY_DOWN( ScanCodeCtrl::OnKeyDown
)
73 ScanCodeCtrl::ScanCodeCtrl( wxWindow
* parent
, wxWindowID id
, int code
,
74 const wxPoint
& pos
, const wxSize
& size
)
75 : wxTextCtrl( parent
, id
, wxEmptyString
, pos
, size
)
77 SetValue( wxString::Format(wxT("0x%04x"), code
) );
80 void ScanCodeCtrl::OnKeyDown( wxKeyEvent
& event
)
82 SetValue( wxString::Format(wxT("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
);
98 ScanCodeCtrl
*m_ScanCode
;
99 wxTextCtrl
*m_Description
;
102 ScanCodeDialog::ScanCodeDialog( wxWindow
* parent
, wxWindowID id
,
103 const int code
, const wxString
&descr
, const wxString
& title
)
104 : wxDialog( parent
, id
, title
, wxDefaultPosition
, wxSize(96*2,76*2) )
106 new wxStaticText( this, wxID_ANY
, _T("Scancode"), wxPoint(4*2,3*2),
108 m_ScanCode
= new ScanCodeCtrl( this, wxID_ANY
, code
, wxPoint(37*2,6*2),
111 new wxStaticText( this, wxID_ANY
, _T("Description"), wxPoint(4*2,24*2),
113 m_Description
= new wxTextCtrl( this, wxID_ANY
, descr
, wxPoint(37*2,27*2),
116 new wxButton( this, wxID_OK
, _T("Ok"), wxPoint(20*2,50*2), wxSize(20*2,13*2) );
117 new wxButton( this, wxID_CANCEL
, _T("Cancel"), wxPoint(44*2,50*2),
121 int ScanCodeDialog::GetValue()
124 wxString buf
= m_ScanCode
->GetValue();
125 wxSscanf( buf
.c_str(), _T("%i"), &code
);
129 /*----------------------------------------------------------------------
130 Utility function to get the elapsed time (in msec) since a given point
131 in time (in sec) (because current version of wxGetElapsedTime doesn´t
132 works right with glibc-2.1 and linux, at least for me)
133 -----------------------------------------------------------------------*/
134 unsigned long StopWatch( unsigned long *sec_base
)
136 unsigned long secs
,msec
;
138 #if defined(__WXMSW__)
143 #elif defined(__WXMAC__) && !defined(__DARWIN__)
144 wxLongLong tl
= wxGetLocalTimeMillis();
145 secs
= (unsigned long) (tl
.GetValue() / 1000);
146 msec
= (unsigned long) (tl
.GetValue() - secs
*1000);
148 // think every unice has gettimeofday
150 gettimeofday( &tv
, (struct timezone
*)NULL
);
152 msec
= tv
.tv_usec
/1000;
158 return( (secs
-*sec_base
)*1000 + msec
);
161 /*----------------------------------------------------------------
162 Implementation of Test-GLCanvas
163 -----------------------------------------------------------------*/
165 BEGIN_EVENT_TABLE(TestGLCanvas
, wxGLCanvas
)
166 EVT_SIZE(TestGLCanvas::OnSize
)
167 EVT_PAINT(TestGLCanvas::OnPaint
)
168 EVT_ERASE_BACKGROUND(TestGLCanvas::OnEraseBackground
)
169 EVT_KEY_DOWN( TestGLCanvas::OnKeyDown
)
170 EVT_KEY_UP( TestGLCanvas::OnKeyUp
)
171 EVT_ENTER_WINDOW( TestGLCanvas::OnEnterWindow
)
174 unsigned long TestGLCanvas::m_secbase
= 0;
175 int TestGLCanvas::m_TimeInitialized
= 0;
176 unsigned long TestGLCanvas::m_xsynct
;
177 unsigned long TestGLCanvas::m_gsynct
;
179 TestGLCanvas::TestGLCanvas(wxWindow
*parent
, wxWindowID id
,
180 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
)
181 : wxGLCanvas(parent
, (wxGLCanvas
*) NULL
, id
, pos
, size
, style
|wxFULL_REPAINT_ON_RESIZE
, name
)
186 m_rright
= WXK_RIGHT
;
189 TestGLCanvas::TestGLCanvas(wxWindow
*parent
, const TestGLCanvas
*other
,
190 wxWindowID id
, const wxPoint
& pos
, const wxSize
& size
, long style
,
191 const wxString
& name
)
192 : wxGLCanvas(parent
, other
->GetContext(), id
, pos
, size
, style
|wxFULL_REPAINT_ON_RESIZE
, name
)
195 m_gllist
= other
->m_gllist
; // share display list
197 m_rright
= WXK_RIGHT
;
200 TestGLCanvas::~TestGLCanvas()
204 void TestGLCanvas::Render()
209 if (!GetContext()) return;
213 // Init OpenGL once, but after SetCurrent
220 glMatrixMode(GL_PROJECTION
);
222 glFrustum(-0.5f
, 0.5f
, -0.5f
, 0.5f
, 1.0f
, 3.0f
);
223 glMatrixMode(GL_MODELVIEW
);
225 /* clear color and depth buffers */
226 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
230 m_gllist
= glGenLists( 1 );
231 glNewList( m_gllist
, GL_COMPILE_AND_EXECUTE
);
232 /* draw six faces of a cube */
234 glNormal3f( 0.0f
, 0.0f
, 1.0f
);
235 glVertex3f( 0.5f
, 0.5f
, 0.5f
); glVertex3f(-0.5f
, 0.5f
, 0.5f
);
236 glVertex3f(-0.5f
,-0.5f
, 0.5f
); glVertex3f( 0.5f
,-0.5f
, 0.5f
);
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
, 1.0f
, 0.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( 1.0f
, 0.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
);
263 glCallList(m_gllist
);
270 void TestGLCanvas::OnEnterWindow( wxMouseEvent
& WXUNUSED(event
) )
275 void TestGLCanvas::OnPaint( wxPaintEvent
& WXUNUSED(event
) )
280 void TestGLCanvas::OnSize(wxSizeEvent
& event
)
282 // this is also necessary to update the context on some platforms
283 wxGLCanvas::OnSize(event
);
285 // set GL viewport (not called by wxGLCanvas::OnSize on all platforms...)
287 GetClientSize(&w
, &h
);
293 glViewport(0, 0, (GLint
) w
, (GLint
) h
);
297 void TestGLCanvas::OnEraseBackground(wxEraseEvent
& WXUNUSED(event
))
299 // Do nothing, to avoid flashing.
302 void TestGLCanvas::InitGL()
306 /* set viewing projection */
307 glMatrixMode(GL_PROJECTION
);
308 glFrustum(-0.5f
, 0.5f
, -0.5f
, 0.5f
, 1.0f
, 3.0f
);
310 /* position viewer */
311 glMatrixMode(GL_MODELVIEW
);
312 glTranslatef(0.0f
, 0.0f
, -2.0f
);
314 /* position object */
315 glRotatef(30.0f
, 1.0f
, 0.0f
, 0.0f
);
316 glRotatef(30.0f
, 0.0f
, 1.0f
, 0.0f
);
318 glEnable(GL_DEPTH_TEST
);
319 glEnable(GL_LIGHTING
);
323 GLfloat
TestGLCanvas::CalcRotateSpeed( unsigned long acceltime
)
327 t
= ((GLfloat
)acceltime
) / 1000.0f
;
339 GLfloat
TestGLCanvas::CalcRotateAngle( unsigned long lasttime
,
340 unsigned long acceltime
)
344 t
= ((GLfloat
)(acceltime
- lasttime
)) / 1000.0f
;
345 s1
= CalcRotateSpeed( lasttime
);
346 s2
= CalcRotateSpeed( acceltime
);
348 return( t
* (s1
+ s2
) * 135.0f
);
351 void TestGLCanvas::Action( long code
, unsigned long lasttime
,
352 unsigned long acceltime
)
354 GLfloat angle
= CalcRotateAngle( lasttime
, acceltime
);
358 else if (code
== m_rright
)
362 void TestGLCanvas::OnKeyDown( wxKeyEvent
& event
)
364 long evkey
= event
.GetKeyCode();
365 if (evkey
== 0) return;
367 if (!m_TimeInitialized
)
369 m_TimeInitialized
= 1;
370 m_xsynct
= event
.GetTimestamp();
371 m_gsynct
= StopWatch(&m_secbase
);
379 unsigned long currTime
= event
.GetTimestamp() - m_xsynct
;
384 m_LastRedraw
= m_StartTime
= m_LastTime
= currTime
;
387 if (currTime
>= m_LastRedraw
) // Redraw:
389 Action( m_Key
, m_LastTime
-m_StartTime
, currTime
-m_StartTime
);
391 #if defined(__WXMAC__) && !defined(__DARWIN__)
392 m_LastRedraw
= currTime
; // StopWatch() doesn't work on Mac...
394 m_LastRedraw
= StopWatch(&m_secbase
) - m_gsynct
;
396 m_LastTime
= currTime
;
402 void TestGLCanvas::OnKeyUp( wxKeyEvent
& event
)
412 void TestGLCanvas::Rotate( GLfloat deg
)
416 glMatrixMode(GL_MODELVIEW
);
417 glRotatef((GLfloat
)deg
, 0.0f
, 0.0f
, 1.0f
);
422 /* -----------------------------------------------------------------------
424 -------------------------------------------------------------------------*/
426 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
427 EVT_MENU(wxID_EXIT
, MyFrame::OnExit
)
428 EVT_MENU( ID_NEW_WINDOW
, MyFrame::OnNewWindow
)
429 EVT_MENU( ID_DEF_ROTATE_LEFT_KEY
, MyFrame::OnDefRotateLeftKey
)
430 EVT_MENU( ID_DEF_ROTATE_RIGHT_KEY
, MyFrame::OnDefRotateRightKey
)
433 // My frame constructor
434 MyFrame::MyFrame(wxWindow
*parent
, const wxString
& title
, const wxPoint
& pos
,
435 const wxSize
& size
, long style
)
436 : wxFrame(parent
, wxID_ANY
, title
, pos
, size
, style
)
439 SetIcon(wxIcon(sample_xpm
));
442 // Intercept menu commands
443 void MyFrame::OnExit( wxCommandEvent
& WXUNUSED(event
) )
445 // true is to force the frame to close
449 /*static*/ MyFrame
*MyFrame::Create(MyFrame
*parentFrame
, bool isCloneWindow
)
451 wxString str
= wxT("wxWidgets OpenGL Cube Sample");
452 if (isCloneWindow
) str
+= wxT(" - Clone");
454 MyFrame
*frame
= new MyFrame(NULL
, str
, wxDefaultPosition
,
458 wxMenu
*winMenu
= new wxMenu
;
460 winMenu
->Append(wxID_EXIT
, _T("&Close"));
461 winMenu
->Append(ID_NEW_WINDOW
, _T("&New") );
462 wxMenuBar
*menuBar
= new wxMenuBar
;
463 menuBar
->Append(winMenu
, _T("&Window"));
465 winMenu
= new wxMenu
;
466 winMenu
->Append(ID_DEF_ROTATE_LEFT_KEY
, _T("Rotate &left"));
467 winMenu
->Append(ID_DEF_ROTATE_RIGHT_KEY
, _T("Rotate &right"));
468 menuBar
->Append(winMenu
, _T("&Key"));
470 frame
->SetMenuBar(menuBar
);
474 frame
->m_canvas
= new TestGLCanvas( frame
, parentFrame
->m_canvas
,
475 wxID_ANY
, wxDefaultPosition
, wxDefaultSize
);
479 frame
->m_canvas
= new TestGLCanvas(frame
, wxID_ANY
,
480 wxDefaultPosition
, wxDefaultSize
);
489 void MyFrame::OnNewWindow( wxCommandEvent
& WXUNUSED(event
) )
491 (void) Create(this, true);
494 void MyFrame::OnDefRotateLeftKey( wxCommandEvent
& WXUNUSED(event
) )
496 ScanCodeDialog
dial( this, wxID_ANY
, m_canvas
->m_rleft
,
497 wxString(_T("Left")), _T("Define key") );
499 int result
= dial
.ShowModal();
501 if( result
== wxID_OK
)
502 m_canvas
->m_rleft
= dial
.GetValue();
505 void MyFrame::OnDefRotateRightKey( wxCommandEvent
& WXUNUSED(event
) )
507 ScanCodeDialog
dial( this, wxID_ANY
, m_canvas
->m_rright
,
508 wxString(_T("Right")), _T("Define key") );
510 int result
= dial
.ShowModal();
512 if( result
== wxID_OK
)
513 m_canvas
->m_rright
= dial
.GetValue();
516 /*------------------------------------------------------------------
517 Application object ( equivalent to main() )
518 ------------------------------------------------------------------ */
524 // Create the main frame window
525 (void) MyFrame::Create(NULL
);