]>
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"
33 #include "../../sample.xpm"
35 #ifndef __WXMSW__ // for StopWatch, see remark below
36 #if defined(__WXMAC__) && !defined(__DARWIN__)
41 #include <sys/unistd.h>
44 #include <sys/timeb.h>
47 #define ID_NEW_WINDOW 10000
48 #define ID_DEF_ROTATE_LEFT_KEY 10001
49 #define ID_DEF_ROTATE_RIGHT_KEY 10002
51 /*----------------------------------------------------------
52 Control to get a keycode
53 ----------------------------------------------------------*/
54 class ScanCodeCtrl
: public wxTextCtrl
57 ScanCodeCtrl( wxWindow
* parent
, wxWindowID id
, int code
,
58 const wxPoint
& pos
, const wxSize
& size
);
60 void OnChar( wxKeyEvent
& WXUNUSED(event
) )
65 void OnKeyDown(wxKeyEvent
& event
);
69 // Any class wishing to process wxWidgets events must use this macro
73 BEGIN_EVENT_TABLE( ScanCodeCtrl
, wxTextCtrl
)
74 EVT_CHAR( ScanCodeCtrl::OnChar
)
75 EVT_KEY_DOWN( ScanCodeCtrl::OnKeyDown
)
78 ScanCodeCtrl::ScanCodeCtrl( wxWindow
* parent
, wxWindowID id
, int code
,
79 const wxPoint
& pos
, const wxSize
& size
)
80 : wxTextCtrl( parent
, id
, wxEmptyString
, pos
, size
)
82 SetValue( wxString::Format(wxT("0x%04x"), code
) );
85 void ScanCodeCtrl::OnKeyDown( wxKeyEvent
& event
)
87 SetValue( wxString::Format(wxT("0x%04x"), event
.GetKeyCode()) );
90 /*------------------------------------------------------------------
91 Dialog for defining a keypress
92 -------------------------------------------------------------------*/
94 class ScanCodeDialog
: public wxDialog
97 ScanCodeDialog( wxWindow
* parent
, wxWindowID id
, const int code
,
98 const wxString
&descr
, const wxString
& title
);
103 ScanCodeCtrl
*m_ScanCode
;
104 wxTextCtrl
*m_Description
;
107 ScanCodeDialog::ScanCodeDialog( wxWindow
* parent
, wxWindowID id
,
108 const int code
, const wxString
&descr
, const wxString
& title
)
109 : wxDialog( parent
, id
, title
, wxDefaultPosition
, wxSize(96*2,76*2) )
111 new wxStaticText( this, wxID_ANY
, _T("Scancode"), wxPoint(4*2,3*2),
113 m_ScanCode
= new ScanCodeCtrl( this, wxID_ANY
, code
, wxPoint(37*2,6*2),
116 new wxStaticText( this, wxID_ANY
, _T("Description"), wxPoint(4*2,24*2),
118 m_Description
= new wxTextCtrl( this, wxID_ANY
, descr
, wxPoint(37*2,27*2),
121 new wxButton( this, wxID_OK
, _T("Ok"), wxPoint(20*2,50*2), wxSize(20*2,13*2) );
122 new wxButton( this, wxID_CANCEL
, _T("Cancel"), wxPoint(44*2,50*2),
126 int ScanCodeDialog::GetValue()
129 wxString buf
= m_ScanCode
->GetValue();
130 wxSscanf( buf
.c_str(), _T("%i"), &code
);
134 /*----------------------------------------------------------------------
135 Utility function to get the elapsed time (in msec) since a given point
136 in time (in sec) (because current version of wxGetElapsedTime doesn´t
137 works right with glibc-2.1 and linux, at least for me)
138 -----------------------------------------------------------------------*/
139 unsigned long StopWatch( unsigned long *sec_base
)
141 unsigned long secs
,msec
;
143 #if defined(__WXMSW__)
148 #elif defined(__WXMAC__) && !defined(__DARWIN__)
149 wxLongLong tl
= wxGetLocalTimeMillis();
150 secs
= (unsigned long) (tl
.GetValue() / 1000);
151 msec
= (unsigned long) (tl
.GetValue() - secs
*1000);
153 // think every unice has gettimeofday
155 gettimeofday( &tv
, (struct timezone
*)NULL
);
157 msec
= tv
.tv_usec
/1000;
163 return( (secs
-*sec_base
)*1000 + msec
);
166 /*----------------------------------------------------------------
167 Implementation of Test-GLCanvas
168 -----------------------------------------------------------------*/
170 BEGIN_EVENT_TABLE(TestGLCanvas
, wxGLCanvas
)
171 EVT_SIZE(TestGLCanvas::OnSize
)
172 EVT_PAINT(TestGLCanvas::OnPaint
)
173 EVT_ERASE_BACKGROUND(TestGLCanvas::OnEraseBackground
)
174 EVT_KEY_DOWN( TestGLCanvas::OnKeyDown
)
175 EVT_KEY_UP( TestGLCanvas::OnKeyUp
)
176 EVT_ENTER_WINDOW( TestGLCanvas::OnEnterWindow
)
179 unsigned long TestGLCanvas::m_secbase
= 0;
180 int TestGLCanvas::m_TimeInitialized
= 0;
181 unsigned long TestGLCanvas::m_xsynct
;
182 unsigned long TestGLCanvas::m_gsynct
;
184 TestGLCanvas::TestGLCanvas(wxWindow
*parent
, wxWindowID id
,
185 const wxPoint
& pos
, const wxSize
& size
, long style
, const wxString
& name
)
186 : wxGLCanvas(parent
, (wxGLCanvas
*) NULL
, id
, pos
, size
, style
|wxFULL_REPAINT_ON_RESIZE
, name
)
191 m_rright
= WXK_RIGHT
;
194 TestGLCanvas::TestGLCanvas(wxWindow
*parent
, const TestGLCanvas
*other
,
195 wxWindowID id
, const wxPoint
& pos
, const wxSize
& size
, long style
,
196 const wxString
& name
)
197 : wxGLCanvas(parent
, other
->GetContext(), id
, pos
, size
, style
|wxFULL_REPAINT_ON_RESIZE
, name
)
200 m_gllist
= other
->m_gllist
; // share display list
202 m_rright
= WXK_RIGHT
;
205 TestGLCanvas::~TestGLCanvas()
209 void TestGLCanvas::Render()
214 if (!GetContext()) return;
218 // Init OpenGL once, but after SetCurrent
225 glMatrixMode(GL_PROJECTION
);
227 glFrustum(-0.5f
, 0.5f
, -0.5f
, 0.5f
, 1.0f
, 3.0f
);
228 glMatrixMode(GL_MODELVIEW
);
230 /* clear color and depth buffers */
231 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
235 m_gllist
= glGenLists( 1 );
236 glNewList( m_gllist
, GL_COMPILE_AND_EXECUTE
);
237 /* draw six faces of a cube */
239 glNormal3f( 0.0f
, 0.0f
, 1.0f
);
240 glVertex3f( 0.5f
, 0.5f
, 0.5f
); glVertex3f(-0.5f
, 0.5f
, 0.5f
);
241 glVertex3f(-0.5f
,-0.5f
, 0.5f
); glVertex3f( 0.5f
,-0.5f
, 0.5f
);
243 glNormal3f( 0.0f
, 0.0f
,-1.0f
);
244 glVertex3f(-0.5f
,-0.5f
,-0.5f
); glVertex3f(-0.5f
, 0.5f
,-0.5f
);
245 glVertex3f( 0.5f
, 0.5f
,-0.5f
); glVertex3f( 0.5f
,-0.5f
,-0.5f
);
247 glNormal3f( 0.0f
, 1.0f
, 0.0f
);
248 glVertex3f( 0.5f
, 0.5f
, 0.5f
); glVertex3f( 0.5f
, 0.5f
,-0.5f
);
249 glVertex3f(-0.5f
, 0.5f
,-0.5f
); glVertex3f(-0.5f
, 0.5f
, 0.5f
);
251 glNormal3f( 0.0f
,-1.0f
, 0.0f
);
252 glVertex3f(-0.5f
,-0.5f
,-0.5f
); glVertex3f( 0.5f
,-0.5f
,-0.5f
);
253 glVertex3f( 0.5f
,-0.5f
, 0.5f
); glVertex3f(-0.5f
,-0.5f
, 0.5f
);
255 glNormal3f( 1.0f
, 0.0f
, 0.0f
);
256 glVertex3f( 0.5f
, 0.5f
, 0.5f
); glVertex3f( 0.5f
,-0.5f
, 0.5f
);
257 glVertex3f( 0.5f
,-0.5f
,-0.5f
); glVertex3f( 0.5f
, 0.5f
,-0.5f
);
259 glNormal3f(-1.0f
, 0.0f
, 0.0f
);
260 glVertex3f(-0.5f
,-0.5f
,-0.5f
); glVertex3f(-0.5f
,-0.5f
, 0.5f
);
261 glVertex3f(-0.5f
, 0.5f
, 0.5f
); glVertex3f(-0.5f
, 0.5f
,-0.5f
);
268 glCallList(m_gllist
);
275 void TestGLCanvas::OnEnterWindow( wxMouseEvent
& WXUNUSED(event
) )
280 void TestGLCanvas::OnPaint( wxPaintEvent
& WXUNUSED(event
) )
285 void TestGLCanvas::OnSize(wxSizeEvent
& event
)
287 // this is also necessary to update the context on some platforms
288 wxGLCanvas::OnSize(event
);
290 // set GL viewport (not called by wxGLCanvas::OnSize on all platforms...)
292 GetClientSize(&w
, &h
);
298 glViewport(0, 0, (GLint
) w
, (GLint
) h
);
302 void TestGLCanvas::OnEraseBackground(wxEraseEvent
& WXUNUSED(event
))
304 // Do nothing, to avoid flashing.
307 void TestGLCanvas::InitGL()
311 /* set viewing projection */
312 glMatrixMode(GL_PROJECTION
);
313 glFrustum(-0.5f
, 0.5f
, -0.5f
, 0.5f
, 1.0f
, 3.0f
);
315 /* position viewer */
316 glMatrixMode(GL_MODELVIEW
);
317 glTranslatef(0.0f
, 0.0f
, -2.0f
);
319 /* position object */
320 glRotatef(30.0f
, 1.0f
, 0.0f
, 0.0f
);
321 glRotatef(30.0f
, 0.0f
, 1.0f
, 0.0f
);
323 glEnable(GL_DEPTH_TEST
);
324 glEnable(GL_LIGHTING
);
328 GLfloat
TestGLCanvas::CalcRotateSpeed( unsigned long acceltime
)
332 t
= ((GLfloat
)acceltime
) / 1000.0f
;
344 GLfloat
TestGLCanvas::CalcRotateAngle( unsigned long lasttime
,
345 unsigned long acceltime
)
349 t
= ((GLfloat
)(acceltime
- lasttime
)) / 1000.0f
;
350 s1
= CalcRotateSpeed( lasttime
);
351 s2
= CalcRotateSpeed( acceltime
);
353 return( t
* (s1
+ s2
) * 135.0f
);
356 void TestGLCanvas::Action( long code
, unsigned long lasttime
,
357 unsigned long acceltime
)
359 GLfloat angle
= CalcRotateAngle( lasttime
, acceltime
);
363 else if (code
== m_rright
)
367 void TestGLCanvas::OnKeyDown( wxKeyEvent
& event
)
369 long evkey
= event
.GetKeyCode();
370 if (evkey
== 0) return;
372 if (!m_TimeInitialized
)
374 m_TimeInitialized
= 1;
375 m_xsynct
= event
.GetTimestamp();
376 m_gsynct
= StopWatch(&m_secbase
);
384 unsigned long currTime
= event
.GetTimestamp() - m_xsynct
;
389 m_LastRedraw
= m_StartTime
= m_LastTime
= currTime
;
392 if (currTime
>= m_LastRedraw
) // Redraw:
394 Action( m_Key
, m_LastTime
-m_StartTime
, currTime
-m_StartTime
);
396 #if defined(__WXMAC__) && !defined(__DARWIN__)
397 m_LastRedraw
= currTime
; // StopWatch() doesn't work on Mac...
399 m_LastRedraw
= StopWatch(&m_secbase
) - m_gsynct
;
401 m_LastTime
= currTime
;
407 void TestGLCanvas::OnKeyUp( wxKeyEvent
& event
)
417 void TestGLCanvas::Rotate( GLfloat deg
)
421 glMatrixMode(GL_MODELVIEW
);
422 glRotatef((GLfloat
)deg
, 0.0f
, 0.0f
, 1.0f
);
427 /* -----------------------------------------------------------------------
429 -------------------------------------------------------------------------*/
431 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
432 EVT_MENU(wxID_EXIT
, MyFrame::OnExit
)
433 EVT_MENU( ID_NEW_WINDOW
, MyFrame::OnNewWindow
)
434 EVT_MENU( ID_DEF_ROTATE_LEFT_KEY
, MyFrame::OnDefRotateLeftKey
)
435 EVT_MENU( ID_DEF_ROTATE_RIGHT_KEY
, MyFrame::OnDefRotateRightKey
)
438 // My frame constructor
439 MyFrame::MyFrame(wxWindow
*parent
, const wxString
& title
, const wxPoint
& pos
,
440 const wxSize
& size
, long style
)
441 : wxFrame(parent
, wxID_ANY
, title
, pos
, size
, style
)
444 SetIcon(wxIcon(sample_xpm
));
447 // Intercept menu commands
448 void MyFrame::OnExit( wxCommandEvent
& WXUNUSED(event
) )
450 // true is to force the frame to close
454 /*static*/ MyFrame
*MyFrame::Create(MyFrame
*parentFrame
, bool isCloneWindow
)
456 wxString str
= wxT("wxWidgets OpenGL Cube Sample");
457 if (isCloneWindow
) str
+= wxT(" - Clone");
459 MyFrame
*frame
= new MyFrame(NULL
, str
, wxDefaultPosition
,
463 wxMenu
*winMenu
= new wxMenu
;
465 winMenu
->Append(wxID_EXIT
, _T("&Close"));
466 winMenu
->Append(ID_NEW_WINDOW
, _T("&New") );
467 wxMenuBar
*menuBar
= new wxMenuBar
;
468 menuBar
->Append(winMenu
, _T("&Window"));
470 winMenu
= new wxMenu
;
471 winMenu
->Append(ID_DEF_ROTATE_LEFT_KEY
, _T("Rotate &left"));
472 winMenu
->Append(ID_DEF_ROTATE_RIGHT_KEY
, _T("Rotate &right"));
473 menuBar
->Append(winMenu
, _T("&Key"));
475 frame
->SetMenuBar(menuBar
);
479 frame
->m_canvas
= new TestGLCanvas( frame
, parentFrame
->m_canvas
,
480 wxID_ANY
, wxDefaultPosition
, wxDefaultSize
);
484 frame
->m_canvas
= new TestGLCanvas(frame
, wxID_ANY
,
485 wxDefaultPosition
, wxDefaultSize
);
494 void MyFrame::OnNewWindow( wxCommandEvent
& WXUNUSED(event
) )
496 (void) Create(this, true);
499 void MyFrame::OnDefRotateLeftKey( wxCommandEvent
& WXUNUSED(event
) )
501 ScanCodeDialog
dial( this, wxID_ANY
, m_canvas
->m_rleft
,
502 wxString(_T("Left")), _T("Define key") );
504 int result
= dial
.ShowModal();
506 if( result
== wxID_OK
)
507 m_canvas
->m_rleft
= dial
.GetValue();
510 void MyFrame::OnDefRotateRightKey( wxCommandEvent
& WXUNUSED(event
) )
512 ScanCodeDialog
dial( this, wxID_ANY
, m_canvas
->m_rright
,
513 wxString(_T("Right")), _T("Define key") );
515 int result
= dial
.ShowModal();
517 if( result
== wxID_OK
)
518 m_canvas
->m_rright
= dial
.GetValue();
521 /*------------------------------------------------------------------
522 Application object ( equivalent to main() )
523 ------------------------------------------------------------------ */
529 // Create the main frame window
530 (void) MyFrame::Create(NULL
);