rename the menu to avoid conflict with a standard Mac menu
[wxWidgets.git] / samples / opengl / cube / cube.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: cube.cpp
3 // Purpose: wxGLCanvas demo program
4 // Author: Julian Smart
5 // Modified by: Vadim Zeitlin to use new wxGLCanvas API (2007-04-09)
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #ifndef WX_PRECOMP
28 #include "wx/wx.h"
29 #endif
30
31 #if !wxUSE_GLCANVAS
32 #error "OpenGL required: set wxUSE_GLCANVAS to 1 and rebuild the library"
33 #endif
34
35 #include "cube.h"
36
37 #if !defined(__WXMSW__) && !defined(__WXPM__)
38 #include "../../sample.xpm"
39 #endif
40
41 // ============================================================================
42 // implementation
43 // ============================================================================
44
45 // ----------------------------------------------------------------------------
46 // MyApp: the application object
47 // ----------------------------------------------------------------------------
48
49 IMPLEMENT_APP(MyApp)
50
51 bool MyApp::OnInit()
52 {
53 if ( !wxApp::OnInit() )
54 return false;
55
56 // Create the main window
57 new MyFrame();
58
59 return true;
60 }
61
62 int MyApp::OnExit()
63 {
64 delete m_glContext;
65
66 return wxApp::OnExit();
67 }
68
69 void MyApp::SetCurrent(wxGLCanvas *canvas)
70 {
71 wxCHECK_RET( canvas, _T("canvas can't be NULL") );
72
73 if ( !m_glContext )
74 m_glContext = new wxGLContext(canvas);
75
76 m_glContext->SetCurrent(*canvas);
77 }
78
79 // ----------------------------------------------------------------------------
80 // TestGLCanvas
81 // ----------------------------------------------------------------------------
82
83 BEGIN_EVENT_TABLE(TestGLCanvas, wxGLCanvas)
84 EVT_SIZE(TestGLCanvas::OnSize)
85 EVT_PAINT(TestGLCanvas::OnPaint)
86
87 EVT_KEY_DOWN(TestGLCanvas::OnKeyDown)
88 END_EVENT_TABLE()
89
90 static const int attribs[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, 0 };
91
92 TestGLCanvas::TestGLCanvas(wxWindow *parent)
93 : wxGLCanvas(parent, wxID_ANY, NULL /* attribs */)
94 {
95 m_gllist = 0;
96
97 // notice that we can't call InitGL() from here: we must wait until the
98 // window is shown on screen to be able to perform OpenGL calls
99 }
100
101 // this function is called on each repaint so it should be fast
102 void TestGLCanvas::Render()
103 {
104 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
105 glCallList(m_gllist);
106
107 glFlush();
108 SwapBuffers();
109 }
110
111 void TestGLCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
112 {
113 wxGetApp().SetCurrent(this);
114
115 // initialize if not done yet
116 InitGL();
117
118 wxPaintDC dc(this);
119
120 Render();
121 }
122
123 void TestGLCanvas::OnSize(wxSizeEvent& event)
124 {
125 // don't prevent default processing from taking place
126 event.Skip();
127
128 if ( !IsInitialized() )
129 return;
130
131 // set GL viewport (not called by wxGLCanvas::OnSize on all platforms...)
132 int w, h;
133 GetClientSize(&w, &h);
134
135 wxGetApp().SetCurrent(this);
136 glViewport(0, 0, w, h);
137 }
138
139 void TestGLCanvas::InitGL()
140 {
141 if ( IsInitialized() )
142 return;
143
144 /* set viewing projection */
145 glMatrixMode(GL_PROJECTION);
146 glLoadIdentity();
147 glFrustum(-0.5f, 0.5f, -0.5f, 0.5f, 1.0f, 3.0f);
148
149 /* position viewer */
150 glMatrixMode(GL_MODELVIEW);
151 glLoadIdentity();
152 glTranslatef(0.0f, 0.0f, -2.0f);
153
154 /* position object */
155 glRotatef(30.0f, 1.0f, 0.0f, 0.0f);
156 glRotatef(30.0f, 0.0f, 1.0f, 0.0f);
157
158 glEnable(GL_DEPTH_TEST);
159 glEnable(GL_LIGHTING);
160 glEnable(GL_LIGHT0);
161
162 // create the list of commands to draw the cube: then we can just (quickly)
163 // execute it in Render() later
164 m_gllist = glGenLists(1);
165 glNewList(m_gllist, GL_COMPILE);
166
167 /* draw six faces of a cube */
168 glBegin(GL_QUADS);
169 glNormal3f( 0.0f, 0.0f, 1.0f);
170 glVertex3f( 0.5f, 0.5f, 0.5f); glVertex3f(-0.5f, 0.5f, 0.5f);
171 glVertex3f(-0.5f,-0.5f, 0.5f); glVertex3f( 0.5f,-0.5f, 0.5f);
172
173 glNormal3f( 0.0f, 0.0f,-1.0f);
174 glVertex3f(-0.5f,-0.5f,-0.5f); glVertex3f(-0.5f, 0.5f,-0.5f);
175 glVertex3f( 0.5f, 0.5f,-0.5f); glVertex3f( 0.5f,-0.5f,-0.5f);
176
177 glNormal3f( 0.0f, 1.0f, 0.0f);
178 glVertex3f( 0.5f, 0.5f, 0.5f); glVertex3f( 0.5f, 0.5f,-0.5f);
179 glVertex3f(-0.5f, 0.5f,-0.5f); glVertex3f(-0.5f, 0.5f, 0.5f);
180
181 glNormal3f( 0.0f,-1.0f, 0.0f);
182 glVertex3f(-0.5f,-0.5f,-0.5f); glVertex3f( 0.5f,-0.5f,-0.5f);
183 glVertex3f( 0.5f,-0.5f, 0.5f); glVertex3f(-0.5f,-0.5f, 0.5f);
184
185 glNormal3f( 1.0f, 0.0f, 0.0f);
186 glVertex3f( 0.5f, 0.5f, 0.5f); glVertex3f( 0.5f,-0.5f, 0.5f);
187 glVertex3f( 0.5f,-0.5f,-0.5f); glVertex3f( 0.5f, 0.5f,-0.5f);
188
189 glNormal3f(-1.0f, 0.0f, 0.0f);
190 glVertex3f(-0.5f,-0.5f,-0.5f); glVertex3f(-0.5f,-0.5f, 0.5f);
191 glVertex3f(-0.5f, 0.5f, 0.5f); glVertex3f(-0.5f, 0.5f,-0.5f);
192 glEnd();
193
194 glEndList();
195 }
196
197 void TestGLCanvas::OnKeyDown( wxKeyEvent& event )
198 {
199 GLfloat x = 0,
200 y = 0,
201 z = 0;
202
203 bool inverse = false;
204
205 switch ( event.GetKeyCode() )
206 {
207 case WXK_RIGHT:
208 inverse = true;
209 // fall through
210
211 case WXK_LEFT:
212 // rotate around Z axis
213 z = 1;
214 break;
215
216 case WXK_DOWN:
217 inverse = true;
218 // fall through
219
220 case WXK_UP:
221 // rotate around Y axis
222 y = 1;
223 break;
224
225 default:
226 event.Skip();
227 return;
228 }
229
230 float angle = 5;
231 if ( inverse )
232 angle = -angle;
233
234 wxGetApp().SetCurrent(this);
235
236 glMatrixMode(GL_MODELVIEW);
237 glRotatef(angle, x, y, z);
238
239 // refresh all cubes
240 for ( wxWindowList::const_iterator i = wxTopLevelWindows.begin();
241 i != wxTopLevelWindows.end();
242 ++i )
243 {
244 MyFrame *frame = (MyFrame *)*i;
245 frame->RefreshCanvas();
246 }
247 }
248
249 // ----------------------------------------------------------------------------
250 // MyFrame: main application window
251 // ----------------------------------------------------------------------------
252
253 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
254 EVT_MENU(wxID_NEW, MyFrame::OnNewWindow)
255 EVT_MENU(wxID_CLOSE, MyFrame::OnClose)
256 END_EVENT_TABLE()
257
258 MyFrame::MyFrame()
259 : wxFrame(NULL, wxID_ANY, _T("wxWidgets OpenGL Cube Sample"),
260 wxDefaultPosition, wxSize(400, 300))
261 {
262 m_canvas = new TestGLCanvas(this);
263
264 SetIcon(wxICON(sample));
265
266 // Make a menubar
267 wxMenu *menu = new wxMenu;
268 menu->Append(wxID_NEW);
269 menu->AppendSeparator();
270 menu->Append(wxID_CLOSE);
271 wxMenuBar *menuBar = new wxMenuBar;
272 menuBar->Append(menu, _T("&Cube"));
273
274 SetMenuBar(menuBar);
275
276 CreateStatusBar();
277
278 Show();
279 }
280
281 void MyFrame::OnClose(wxCommandEvent& WXUNUSED(event))
282 {
283 // true is to force the frame to close
284 Close(true);
285 }
286
287 void MyFrame::OnNewWindow( wxCommandEvent& WXUNUSED(event) )
288 {
289 (void) new MyFrame();
290 }
291
292 void MyFrame::RefreshCanvas()
293 {
294 m_canvas->Refresh(false);
295 }