]>
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"
30 #ifndef __WXMSW__ // for wxStopWatch, 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 wxWindows 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 wxStopWatch( 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 -----------------------------------------------------------------*/
167 BEGIN_EVENT_TABLE(TestGLCanvas
, wxGLCanvas
)
168 EVT_SIZE(TestGLCanvas::OnSize
)
169 EVT_PAINT(TestGLCanvas::OnPaint
)
170 EVT_ERASE_BACKGROUND(TestGLCanvas::OnEraseBackground
)
171 EVT_KEY_DOWN( TestGLCanvas::OnKeyDown
)
172 EVT_KEY_UP( TestGLCanvas::OnKeyUp
)
173 EVT_ENTER_WINDOW( TestGLCanvas::OnEnterWindow
)
176 unsigned long TestGLCanvas::m_secbase
= 0;
177 int TestGLCanvas::m_TimeInitialized
= 0;
178 unsigned long TestGLCanvas::m_xsynct
;
179 unsigned long TestGLCanvas::m_gsynct
;
181 TestGLCanvas::TestGLCanvas(wxWindow
*parent
, wxWindowID id
,
182 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
)
183 : wxGLCanvas(parent
, (wxGLCanvas
*) NULL
, id
, pos
, size
, style
, name
)
188 m_rright
= WXK_RIGHT
;
191 TestGLCanvas::TestGLCanvas(wxWindow
*parent
, const TestGLCanvas
&other
,
192 wxWindowID id
, const wxPoint
& pos
, const wxSize
& size
, long style
,
193 const wxString
& name
)
194 : wxGLCanvas(parent
, other
.GetContext(), id
, pos
, size
, style
, name
)
197 m_gllist
= other
.m_gllist
; // share display list
199 m_rright
= WXK_RIGHT
;
202 TestGLCanvas::~TestGLCanvas()
206 void TestGLCanvas::Render()
211 if (!GetContext()) return;
215 // Init OpenGL once, but after SetCurrent
222 glMatrixMode(GL_PROJECTION
);
224 glFrustum(-0.5f
, 0.5f
, -0.5f
, 0.5f
, 1.0f
, 3.0f
);
225 glMatrixMode(GL_MODELVIEW
);
227 /* clear color and depth buffers */
228 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
232 m_gllist
= glGenLists( 1 );
233 glNewList( m_gllist
, GL_COMPILE_AND_EXECUTE
);
234 /* draw six faces of a cube */
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
, 0.0f
,-1.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( 0.0f
,-1.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
);
256 glNormal3f(-1.0f
, 0.0f
, 0.0f
);
257 glVertex3f(-0.5f
,-0.5f
,-0.5f
); glVertex3f(-0.5f
,-0.5f
, 0.5f
);
258 glVertex3f(-0.5f
, 0.5f
, 0.5f
); glVertex3f(-0.5f
, 0.5f
,-0.5f
);
265 glCallList(m_gllist
);
272 void TestGLCanvas::OnEnterWindow( wxMouseEvent
& WXUNUSED(event
) )
277 void TestGLCanvas::OnPaint( wxPaintEvent
& WXUNUSED(event
) )
282 void TestGLCanvas::OnSize(wxSizeEvent
& event
)
284 // this is also necessary to update the context on some platforms
285 wxGLCanvas::OnSize(event
);
287 // set GL viewport (not called by wxGLCanvas::OnSize on all platforms...)
289 GetClientSize(&w
, &h
);
295 glViewport(0, 0, (GLint
) w
, (GLint
) h
);
299 void TestGLCanvas::OnEraseBackground(wxEraseEvent
& WXUNUSED(event
))
301 // Do nothing, to avoid flashing.
304 void TestGLCanvas::InitGL()
308 /* set viewing projection */
309 glMatrixMode(GL_PROJECTION
);
310 glFrustum(-0.5f
, 0.5f
, -0.5f
, 0.5f
, 1.0f
, 3.0f
);
312 /* position viewer */
313 glMatrixMode(GL_MODELVIEW
);
314 glTranslatef(0.0f
, 0.0f
, -2.0f
);
316 /* position object */
317 glRotatef(30.0f
, 1.0f
, 0.0f
, 0.0f
);
318 glRotatef(30.0f
, 0.0f
, 1.0f
, 0.0f
);
320 glEnable(GL_DEPTH_TEST
);
321 glEnable(GL_LIGHTING
);
325 GLfloat
TestGLCanvas::CalcRotateSpeed( unsigned long acceltime
)
329 t
= ((GLfloat
)acceltime
) / 1000.0f
;
341 GLfloat
TestGLCanvas::CalcRotateAngle( unsigned long lasttime
,
342 unsigned long acceltime
)
346 t
= ((GLfloat
)(acceltime
- lasttime
)) / 1000.0f
;
347 s1
= CalcRotateSpeed( lasttime
);
348 s2
= CalcRotateSpeed( acceltime
);
350 return( t
* (s1
+ s2
) * 135.0f
);
353 void TestGLCanvas::Action( long code
, unsigned long lasttime
,
354 unsigned long acceltime
)
356 GLfloat angle
= CalcRotateAngle( lasttime
, acceltime
);
360 else if (code
== m_rright
)
364 void TestGLCanvas::OnKeyDown( wxKeyEvent
& event
)
366 long evkey
= event
.GetKeyCode();
367 if (evkey
== 0) return;
369 if (!m_TimeInitialized
)
371 m_TimeInitialized
= 1;
372 m_xsynct
= event
.m_timeStamp
;
373 m_gsynct
= wxStopWatch(&m_secbase
);
381 unsigned long currTime
= event
.m_timeStamp
- m_xsynct
;
386 m_LastRedraw
= m_StartTime
= m_LastTime
= currTime
;
389 if (currTime
>= m_LastRedraw
) // Redraw:
391 Action( m_Key
, m_LastTime
-m_StartTime
, currTime
-m_StartTime
);
393 #if defined(__WXMAC__) && !defined(__DARWIN__)
394 m_LastRedraw
= currTime
; // wxStopWatch() doesn't work on Mac...
396 m_LastRedraw
= wxStopWatch(&m_secbase
) - m_gsynct
;
398 m_LastTime
= currTime
;
404 void TestGLCanvas::OnKeyUp( wxKeyEvent
& event
)
414 void TestGLCanvas::Rotate( GLfloat deg
)
418 glMatrixMode(GL_MODELVIEW
);
419 glRotatef((GLfloat
)deg
, 0.0f
, 0.0f
, 1.0f
);
424 #endif // wxUSE_GLCANVAS
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("wxWindows 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
);
483 frame
->m_canvas
= new TestGLCanvas( frame
, parentFrame
->m_canvas
,
484 wxID_ANY
, wxDefaultPosition
, wxDefaultSize
);
488 frame
->m_canvas
= new TestGLCanvas(frame
, wxID_ANY
,
489 wxDefaultPosition
, wxDefaultSize
);
499 void MyFrame::OnNewWindow( wxCommandEvent
& WXUNUSED(event
) )
501 (void) Create(this, true);
504 void MyFrame::OnDefRotateLeftKey( wxCommandEvent
& WXUNUSED(event
) )
507 ScanCodeDialog
dial( this, wxID_ANY
, m_canvas
->m_rleft
,
508 wxString(_T("Left")), _T("Define key") );
510 int result
= dial
.ShowModal();
512 if( result
== wxID_OK
)
513 m_canvas
->m_rleft
= dial
.GetValue();
517 void MyFrame::OnDefRotateRightKey( wxCommandEvent
& WXUNUSED(event
) )
520 ScanCodeDialog
dial( this, wxID_ANY
, m_canvas
->m_rright
,
521 wxString(_T("Right")), _T("Define key") );
523 int result
= dial
.ShowModal();
525 if( result
== wxID_OK
)
526 m_canvas
->m_rright
= dial
.GetValue();
530 /*------------------------------------------------------------------
531 Application object ( equivalent to main() )
532 ------------------------------------------------------------------ */
539 wxLog::SetTraceMask(wxTraceMessages
);
542 // Create the main frame window
543 (void) MyFrame::Create(NULL
);
551 wxMessageBox( _T("This sample has to be compiled with wxUSE_GLCANVAS"),
552 _T("Building error"), wxOK
);