Applied patch [ 802596 ] warning and error free Open GL samples
[wxWidgets.git] / samples / opengl / cube / cube.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: cube.cpp
3 // Purpose: wxGLCanvas demo program
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #if defined(__GNUG__) && !defined(__APPLE__)
13 #pragma implementation
14 #pragma interface
15 #endif
16
17 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
19
20 #ifdef __BORLANDC__
21 #pragma hdrstop
22 #endif
23
24 #ifndef WX_PRECOMP
25 #include "wx/wx.h"
26 #endif
27
28 #include "wx/log.h"
29
30 #include "cube.h"
31
32 #ifndef __WXMSW__ // for wxStopWatch, see remark below
33 #if defined(__WXMAC__) && !defined(__DARWIN__)
34 #include <utime.h>
35 #include <unistd.h>
36 #else
37 #include <sys/time.h>
38 #include <sys/unistd.h>
39 #endif
40 #else
41 #include <sys/timeb.h>
42 #endif
43
44 #define ID_NEW_WINDOW 10000
45 #define ID_DEF_ROTATE_LEFT_KEY 10001
46 #define ID_DEF_ROTATE_RIGHT_KEY 10002
47
48 /*----------------------------------------------------------
49 Control to get a keycode
50 ----------------------------------------------------------*/
51 class ScanCodeCtrl : public wxTextCtrl
52 {
53 public:
54 ScanCodeCtrl( wxWindow* parent, wxWindowID id, int code,
55 const wxPoint& pos, const wxSize& size );
56 void OnChar( wxKeyEvent& event ) { } /* do nothing */
57 void OnKeyDown(wxKeyEvent& event);
58 private:
59 // any class wishing to process wxWindows events must use this macro
60 DECLARE_EVENT_TABLE()
61 };
62 BEGIN_EVENT_TABLE( ScanCodeCtrl, wxTextCtrl )
63 EVT_CHAR( ScanCodeCtrl::OnChar )
64 EVT_KEY_DOWN( ScanCodeCtrl::OnKeyDown )
65 END_EVENT_TABLE()
66
67 ScanCodeCtrl::ScanCodeCtrl( wxWindow* parent, wxWindowID id, int code,
68 const wxPoint& pos, const wxSize& size )
69 : wxTextCtrl( parent, id, wxEmptyString, pos, size )
70 { wxString buf;
71 buf.Printf( _T("0x%04x"), code );
72 SetValue( buf );
73 }
74
75 void ScanCodeCtrl::OnKeyDown( wxKeyEvent& event )
76 {
77 wxString buf;
78 buf.Printf( _T("0x%04x"), event.GetKeyCode() );
79 SetValue( buf );
80 }
81
82 /*------------------------------------------------------------------
83 Dialog for defining a keypress
84 -------------------------------------------------------------------*/
85
86 class ScanCodeDialog : public wxDialog
87 {
88 public:
89 ScanCodeDialog( wxWindow* parent, wxWindowID id, const int code,
90 const wxString &descr, const wxString& title );
91 int GetValue();
92 private:
93 ScanCodeCtrl *m_ScanCode;
94 wxTextCtrl *m_Description;
95 };
96
97 ScanCodeDialog::ScanCodeDialog( wxWindow* parent, wxWindowID id,
98 const int code, const wxString &descr, const wxString& title )
99 : wxDialog( parent, id, title, wxPoint(-1, -1), wxSize(96*2,76*2) )
100 {
101 new wxStaticText( this, -1, _T("Scancode"), wxPoint(4*2,3*2),
102 wxSize(31*2,12*2) );
103 m_ScanCode = new ScanCodeCtrl( this, -1, code, wxPoint(37*2,6*2),
104 wxSize(53*2,14*2) );
105
106 new wxStaticText( this, -1, _T("Description"), wxPoint(4*2,24*2),
107 wxSize(32*2,12*2) );
108 m_Description = new wxTextCtrl( this, -1, descr, wxPoint(37*2,27*2),
109 wxSize(53*2,14*2) );
110
111 new wxButton( this, wxID_OK, _T("Ok"), wxPoint(20*2,50*2), wxSize(20*2,13*2) );
112 new wxButton( this, wxID_CANCEL, _T("Cancel"), wxPoint(44*2,50*2),
113 wxSize(25*2,13*2) );
114 }
115
116 int ScanCodeDialog::GetValue()
117 {
118 int code;
119 wxString buf = m_ScanCode->GetValue();
120 wxSscanf( buf.c_str(), _T("%i"), &code );
121 return( code );
122 }
123
124 /*----------------------------------------------------------------------
125 Utility function to get the elapsed time (in msec) since a given point
126 in time (in sec) (because current version of wxGetElapsedTime doesn´t
127 works right with glibc-2.1 and linux, at least for me)
128 -----------------------------------------------------------------------*/
129 unsigned long wxStopWatch( unsigned long *sec_base )
130 {
131 unsigned long secs,msec;
132
133 #if defined(__WXMSW__)
134 struct timeb tb;
135 ftime( &tb );
136 secs = tb.time;
137 msec = tb.millitm;
138 #elif defined(__WXMAC__) && !defined(__DARWIN__)
139 wxLongLong tl = wxGetLocalTimeMillis();
140 secs = (unsigned long) (tl.GetValue() / 1000);
141 msec = (unsigned long) (tl.GetValue() - secs*1000);
142 #else
143 // think every unice has gettimeofday
144 struct timeval tv;
145 gettimeofday( &tv, (struct timezone *)NULL );
146 secs = tv.tv_sec;
147 msec = tv.tv_usec/1000;
148 #endif
149
150 if( *sec_base == 0 )
151 *sec_base = secs;
152
153 return( (secs-*sec_base)*1000 + msec );
154 }
155
156 /*----------------------------------------------------------------
157 Implementation of Test-GLCanvas
158 -----------------------------------------------------------------*/
159
160 #if wxUSE_GLCANVAS
161
162 BEGIN_EVENT_TABLE(TestGLCanvas, wxGLCanvas)
163 EVT_SIZE(TestGLCanvas::OnSize)
164 EVT_PAINT(TestGLCanvas::OnPaint)
165 EVT_ERASE_BACKGROUND(TestGLCanvas::OnEraseBackground)
166 EVT_KEY_DOWN( TestGLCanvas::OnKeyDown )
167 EVT_KEY_UP( TestGLCanvas::OnKeyUp )
168 EVT_ENTER_WINDOW( TestGLCanvas::OnEnterWindow )
169 END_EVENT_TABLE()
170
171 unsigned long TestGLCanvas::m_secbase = 0;
172 int TestGLCanvas::m_TimeInitialized = 0;
173 unsigned long TestGLCanvas::m_xsynct;
174 unsigned long TestGLCanvas::m_gsynct;
175
176 TestGLCanvas::TestGLCanvas(wxWindow *parent, wxWindowID id,
177 const wxPoint& pos, const wxSize& size, long style, const wxString& name):
178 wxGLCanvas(parent, (wxGLCanvas*) NULL, id, pos, size, style, name )
179 {
180 m_init = FALSE;
181 m_gllist = 0;
182 m_rleft = WXK_LEFT;
183 m_rright = WXK_RIGHT;
184 }
185
186 TestGLCanvas::TestGLCanvas(wxWindow *parent, const TestGLCanvas &other,
187 wxWindowID id, const wxPoint& pos, const wxSize& size, long style,
188 const wxString& name ) :
189 wxGLCanvas(parent, other.GetContext(), id, pos, size, style, name )
190 {
191 m_init = FALSE;
192 m_gllist = other.m_gllist; /* share display list */
193 m_rleft = WXK_LEFT;
194 m_rright = WXK_RIGHT;
195 }
196
197 TestGLCanvas::~TestGLCanvas()
198 {
199 }
200
201 void TestGLCanvas::Render()
202 {
203 wxPaintDC dc(this);
204
205 #ifndef __WXMOTIF__
206 if (!GetContext()) return;
207 #endif
208
209 SetCurrent();
210 /* init OpenGL once, but after SetCurrent */
211 if (!m_init)
212 {
213 InitGL();
214 m_init = TRUE;
215 }
216
217 glMatrixMode(GL_PROJECTION);
218 glLoadIdentity();
219 glFrustum(-0.5F, 0.5F, -0.5F, 0.5F, 1.0F, 3.0F);
220 glMatrixMode(GL_MODELVIEW);
221
222 /* clear color and depth buffers */
223 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
224
225 if( m_gllist == 0 )
226 {
227 m_gllist = glGenLists( 1 );
228 glNewList( m_gllist, GL_COMPILE_AND_EXECUTE );
229 /* draw six faces of a cube */
230 glBegin(GL_QUADS);
231 glNormal3f( 0.0F, 0.0F, 1.0F);
232 glVertex3f( 0.5F, 0.5F, 0.5F); glVertex3f(-0.5F, 0.5F, 0.5F);
233 glVertex3f(-0.5F,-0.5F, 0.5F); glVertex3f( 0.5F,-0.5F, 0.5F);
234
235 glNormal3f( 0.0F, 0.0F,-1.0F);
236 glVertex3f(-0.5F,-0.5F,-0.5F); glVertex3f(-0.5F, 0.5F,-0.5F);
237 glVertex3f( 0.5F, 0.5F,-0.5F); glVertex3f( 0.5F,-0.5F,-0.5F);
238
239 glNormal3f( 0.0F, 1.0F, 0.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);
242
243 glNormal3f( 0.0F,-1.0F, 0.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);
246
247 glNormal3f( 1.0F, 0.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);
250
251 glNormal3f(-1.0F, 0.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);
254 glEnd();
255
256 glEndList();
257 }
258 else
259 glCallList( m_gllist );
260
261 glFlush();
262 SwapBuffers();
263 }
264
265 void TestGLCanvas::OnEnterWindow( wxMouseEvent& WXUNUSED(event) )
266 {
267 SetFocus();
268 }
269
270 void TestGLCanvas::OnPaint( wxPaintEvent& WXUNUSED(event) )
271 {
272 Render();
273 }
274
275 void TestGLCanvas::OnSize(wxSizeEvent& event)
276 {
277 // this is also necessary to update the context on some platforms
278 wxGLCanvas::OnSize(event);
279
280 // set GL viewport (not called by wxGLCanvas::OnSize on all platforms...)
281 int w, h;
282 GetClientSize(&w, &h);
283 #ifndef __WXMOTIF__
284 if (GetContext())
285 #endif
286 {
287 SetCurrent();
288 glViewport(0, 0, (GLint) w, (GLint) h);
289 }
290 }
291
292 void TestGLCanvas::OnEraseBackground(wxEraseEvent& WXUNUSED(event))
293 {
294 // Do nothing, to avoid flashing.
295 }
296
297 void TestGLCanvas::InitGL()
298 {
299 SetCurrent();
300
301 /* set viewing projection */
302 glMatrixMode(GL_PROJECTION);
303 glFrustum(-0.5F, 0.5F, -0.5F, 0.5F, 1.0F, 3.0F);
304
305 /* position viewer */
306 glMatrixMode(GL_MODELVIEW);
307 glTranslatef(0.0F, 0.0F, -2.0F);
308
309 /* position object */
310 glRotatef(30.0F, 1.0F, 0.0F, 0.0F);
311 glRotatef(30.0F, 0.0F, 1.0F, 0.0F);
312
313 glEnable(GL_DEPTH_TEST);
314 glEnable(GL_LIGHTING);
315 glEnable(GL_LIGHT0);
316 }
317
318 GLfloat TestGLCanvas::CalcRotateSpeed( unsigned long acceltime )
319 {
320 GLfloat t,v;
321
322 t = ((GLfloat)acceltime) / 1000.0f;
323
324 if( t < 0.5f )
325 v = t;
326 else if( t < 1.0f )
327 v = t * (2.0f - t);
328 else
329 v = 0.75f;
330
331 return(v);
332 }
333
334 GLfloat TestGLCanvas::CalcRotateAngle( unsigned long lasttime,
335 unsigned long acceltime )
336 {
337 GLfloat t,s1,s2;
338
339 t = ((GLfloat)(acceltime - lasttime)) / 1000.0f;
340 s1 = CalcRotateSpeed( lasttime );
341 s2 = CalcRotateSpeed( acceltime );
342
343 return( t * (s1 + s2) * 135.0f );
344 }
345
346 void TestGLCanvas::Action( long code, unsigned long lasttime,
347 unsigned long acceltime )
348 {
349 GLfloat angle = CalcRotateAngle( lasttime, acceltime );
350
351 if (code == m_rleft)
352 Rotate( angle );
353 else if (code == m_rright)
354 Rotate( -angle );
355 }
356
357 void TestGLCanvas::OnKeyDown( wxKeyEvent& event )
358 {
359 long evkey = event.GetKeyCode();
360 if (evkey == 0) return;
361
362 if (!m_TimeInitialized)
363 {
364 m_TimeInitialized = 1;
365 m_xsynct = event.m_timeStamp;
366 m_gsynct = wxStopWatch(&m_secbase);
367
368 m_Key = evkey;
369 m_StartTime = 0;
370 m_LastTime = 0;
371 m_LastRedraw = 0;
372 }
373
374 unsigned long currTime = event.m_timeStamp - m_xsynct;
375
376 if (evkey != m_Key)
377 {
378 m_Key = evkey;
379 m_LastRedraw = m_StartTime = m_LastTime = currTime;
380 }
381
382 if (currTime >= m_LastRedraw) // Redraw:
383 {
384 Action( m_Key, m_LastTime-m_StartTime, currTime-m_StartTime );
385
386 #if defined(__WXMAC__) && !defined(__DARWIN__)
387 m_LastRedraw = currTime; // wxStopWatch() doesn't work on Mac...
388 #else
389 m_LastRedraw = wxStopWatch(&m_secbase) - m_gsynct;
390 #endif
391 m_LastTime = currTime;
392 }
393
394 event.Skip();
395 }
396
397 void TestGLCanvas::OnKeyUp( wxKeyEvent& event )
398 {
399 m_Key = 0;
400 m_StartTime = 0;
401 m_LastTime = 0;
402 m_LastRedraw = 0;
403
404 event.Skip();
405 }
406
407 void TestGLCanvas::Rotate( GLfloat deg )
408 {
409 SetCurrent();
410
411 glMatrixMode(GL_MODELVIEW);
412 glRotatef((GLfloat)deg, 0.0F, 0.0F, 1.0F);
413 Refresh(FALSE);
414 }
415
416
417 #endif // wxUSE_GLCANVAS
418
419 /* -----------------------------------------------------------------------
420 Main Window
421 -------------------------------------------------------------------------*/
422
423 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
424 EVT_MENU(wxID_EXIT, MyFrame::OnExit)
425 EVT_MENU( ID_NEW_WINDOW, MyFrame::OnNewWindow)
426 EVT_MENU( ID_DEF_ROTATE_LEFT_KEY, MyFrame::OnDefRotateLeftKey)
427 EVT_MENU( ID_DEF_ROTATE_RIGHT_KEY, MyFrame::OnDefRotateRightKey)
428 END_EVENT_TABLE()
429
430 // My frame constructor
431 MyFrame::MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos,
432 const wxSize& size, long style)
433 : wxFrame(frame, -1, title, pos, size, style)
434 {
435 m_canvas = NULL;
436 }
437
438 // Intercept menu commands
439 void MyFrame::OnExit(wxCommandEvent& WXUNUSED(event))
440 {
441 Destroy();
442 }
443
444 void MyFrame::OnNewWindow(wxCommandEvent& WXUNUSED(event))
445 {
446 MyFrame *frame = new MyFrame(NULL, _T("Cube OpenGL Demo Clone"),
447 wxPoint(50, 50), wxSize(400, 300));
448 // Give it an icon
449 #ifdef __WXMSW__
450 frame->SetIcon(wxIcon(_T("mondrian")));
451 #endif
452
453 // Make a menubar
454 wxMenu *winMenu = new wxMenu;
455
456 winMenu->Append(wxID_EXIT, _T("&Close"));
457 winMenu->Append(ID_NEW_WINDOW, _T("&New") );
458 wxMenuBar *menuBar = new wxMenuBar;
459 menuBar->Append(winMenu, _T("&Window"));
460
461 winMenu = new wxMenu;
462 winMenu->Append(ID_DEF_ROTATE_LEFT_KEY, _T("Rotate &left"));
463 winMenu->Append(ID_DEF_ROTATE_RIGHT_KEY, _T("Rotate &right"));
464 menuBar->Append(winMenu, _T("&Key"));
465
466 frame->SetMenuBar(menuBar);
467
468 #if wxUSE_GLCANVAS
469 frame->m_canvas = new TestGLCanvas( frame, *m_canvas, -1,
470 wxDefaultPosition, wxDefaultSize );
471 #endif
472
473 // Show the frame
474 frame->Show(TRUE);
475 }
476
477 void MyFrame::OnDefRotateLeftKey(wxCommandEvent& WXUNUSED(event))
478 {
479 #if wxUSE_GLCANVAS
480 ScanCodeDialog dial( this, -1, m_canvas->m_rleft,
481 wxString(_T("Left")), _T("Define key") );
482 int result = dial.ShowModal();
483 if( result == wxID_OK )
484 m_canvas->m_rleft = dial.GetValue();
485 #endif
486 }
487
488 void MyFrame::OnDefRotateRightKey(wxCommandEvent& WXUNUSED(event))
489 {
490 #if wxUSE_GLCANVAS
491 ScanCodeDialog dial( this, -1, m_canvas->m_rright,
492 wxString(_T("Right")), _T("Define key") );
493 int result = dial.ShowModal();
494 if( result == wxID_OK )
495 m_canvas->m_rright = dial.GetValue();
496 #endif
497 }
498
499 /*------------------------------------------------------------------
500 Application object ( equivalent to main() )
501 ------------------------------------------------------------------ */
502
503 IMPLEMENT_APP(MyApp)
504
505 bool MyApp::OnInit(void)
506 {
507 wxLog::SetTraceMask(wxTraceMessages);
508
509 // Create the main frame window
510 MyFrame *frame = new MyFrame(NULL, _T("Cube OpenGL Demo"), wxPoint(50, 50),
511 wxSize(400, 300));
512 // Give it an icon
513 #ifdef wx_msw
514 frame->SetIcon(wxIcon("mondrian"));
515 #endif
516
517 // Make a menubar
518 wxMenu *winMenu = new wxMenu;
519
520 winMenu->Append(wxID_EXIT, _T("&Close"));
521 winMenu->Append(ID_NEW_WINDOW, _T("&New") );
522 wxMenuBar *menuBar = new wxMenuBar;
523 menuBar->Append(winMenu, _T("&Window"));
524
525 winMenu = new wxMenu;
526 winMenu->Append(ID_DEF_ROTATE_LEFT_KEY, _T("Rotate &left"));
527 winMenu->Append(ID_DEF_ROTATE_RIGHT_KEY, _T("Rotate &right"));
528 menuBar->Append(winMenu, _T("&Key"));
529
530 frame->SetMenuBar(menuBar);
531
532 #if wxUSE_GLCANVAS
533
534 frame->m_canvas = new TestGLCanvas(frame, -1, wxDefaultPosition, wxDefaultSize);
535
536 // Show the frame
537 frame->Show(TRUE);
538
539 return TRUE;
540
541 #else
542
543 wxMessageBox( _T("This sample has to be compiled with wxUSE_GLCANVAS"), _T("Building error"), wxOK);
544
545 return FALSE;
546
547 #endif
548
549 }