reorganized the code to put the logic in wxGLContext-derived class but keep the state...
[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 TestGLContext& MyApp::GetContext(wxGLCanvas *canvas)
70 {
71 if ( !m_glContext )
72 m_glContext = new TestGLContext(canvas);
73
74 m_glContext->SetCurrent(*canvas);
75
76 return *m_glContext;
77 }
78
79 // ----------------------------------------------------------------------------
80 // TestGLContext
81 // ----------------------------------------------------------------------------
82
83 TestGLContext::TestGLContext(wxGLCanvas *canvas)
84 : wxGLContext(canvas)
85 {
86 m_gllist = 0;
87 }
88
89 void TestGLContext::Init()
90 {
91 if ( m_gllist )
92 return;
93
94 /* set viewing projection */
95 glMatrixMode(GL_PROJECTION);
96 glLoadIdentity();
97 glFrustum(-0.5f, 0.5f, -0.5f, 0.5f, 1.0f, 3.0f);
98
99 glEnable(GL_DEPTH_TEST);
100 glEnable(GL_LIGHTING);
101 glEnable(GL_LIGHT0);
102
103 // create the list of commands to draw the cube: then we can just (quickly)
104 // execute it in DrawRotatedCube() later
105 m_gllist = glGenLists(1);
106 glNewList(m_gllist, GL_COMPILE);
107
108 /* draw six faces of a cube */
109 glBegin(GL_QUADS);
110 glNormal3f( 0.0f, 0.0f, 1.0f);
111 glVertex3f( 0.5f, 0.5f, 0.5f); glVertex3f(-0.5f, 0.5f, 0.5f);
112 glVertex3f(-0.5f,-0.5f, 0.5f); glVertex3f( 0.5f,-0.5f, 0.5f);
113
114 glNormal3f( 0.0f, 0.0f,-1.0f);
115 glVertex3f(-0.5f,-0.5f,-0.5f); glVertex3f(-0.5f, 0.5f,-0.5f);
116 glVertex3f( 0.5f, 0.5f,-0.5f); glVertex3f( 0.5f,-0.5f,-0.5f);
117
118 glNormal3f( 0.0f, 1.0f, 0.0f);
119 glVertex3f( 0.5f, 0.5f, 0.5f); glVertex3f( 0.5f, 0.5f,-0.5f);
120 glVertex3f(-0.5f, 0.5f,-0.5f); glVertex3f(-0.5f, 0.5f, 0.5f);
121
122 glNormal3f( 0.0f,-1.0f, 0.0f);
123 glVertex3f(-0.5f,-0.5f,-0.5f); glVertex3f( 0.5f,-0.5f,-0.5f);
124 glVertex3f( 0.5f,-0.5f, 0.5f); glVertex3f(-0.5f,-0.5f, 0.5f);
125
126 glNormal3f( 1.0f, 0.0f, 0.0f);
127 glVertex3f( 0.5f, 0.5f, 0.5f); glVertex3f( 0.5f,-0.5f, 0.5f);
128 glVertex3f( 0.5f,-0.5f,-0.5f); glVertex3f( 0.5f, 0.5f,-0.5f);
129
130 glNormal3f(-1.0f, 0.0f, 0.0f);
131 glVertex3f(-0.5f,-0.5f,-0.5f); glVertex3f(-0.5f,-0.5f, 0.5f);
132 glVertex3f(-0.5f, 0.5f, 0.5f); glVertex3f(-0.5f, 0.5f,-0.5f);
133 glEnd();
134
135 glEndList();
136 }
137
138 void TestGLContext::DrawRotatedCube(float xangle, float yangle)
139 {
140 Init();
141
142 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
143
144 glMatrixMode(GL_MODELVIEW);
145 glLoadIdentity();
146 glTranslatef(0.0f, 0.0f, -2.0f);
147 glRotatef(xangle, 1.0f, 0.0f, 0.0f);
148 glRotatef(yangle, 0.0f, 1.0f, 0.0f);
149
150 glCallList(m_gllist);
151
152 glFlush();
153 }
154
155 // ----------------------------------------------------------------------------
156 // TestGLCanvas
157 // ----------------------------------------------------------------------------
158
159 BEGIN_EVENT_TABLE(TestGLCanvas, wxGLCanvas)
160 EVT_SIZE(TestGLCanvas::OnSize)
161 EVT_PAINT(TestGLCanvas::OnPaint)
162
163 EVT_KEY_DOWN(TestGLCanvas::OnKeyDown)
164 END_EVENT_TABLE()
165
166 TestGLCanvas::TestGLCanvas(wxWindow *parent)
167 : wxGLCanvas(parent, wxID_ANY, NULL /* attribs */)
168 {
169 m_xangle =
170 m_yangle = 30;
171 }
172
173 void TestGLCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
174 {
175 wxPaintDC dc(this);
176
177 wxGetApp().GetContext(this).DrawRotatedCube(m_xangle, m_yangle);
178
179 SwapBuffers();
180 }
181
182 void TestGLCanvas::OnSize(wxSizeEvent& event)
183 {
184 // don't prevent default processing from taking place
185 event.Skip();
186
187 if ( !IsShown() )
188 return;
189
190 // set GL viewport (not called by wxGLCanvas::OnSize on all platforms...)
191 int w, h;
192 GetClientSize(&w, &h);
193
194 wxGetApp().GetContext(this);
195 glViewport(0, 0, w, h);
196 }
197
198 void TestGLCanvas::OnKeyDown( wxKeyEvent& event )
199 {
200 float *p = NULL;
201
202 bool inverse = false;
203
204 switch ( event.GetKeyCode() )
205 {
206 case WXK_RIGHT:
207 inverse = true;
208 // fall through
209
210 case WXK_LEFT:
211 // rotate around Y axis
212 p = &m_yangle;
213 break;
214
215 case WXK_DOWN:
216 inverse = true;
217 // fall through
218
219 case WXK_UP:
220 // rotate around X axis
221 p = &m_xangle;
222 break;
223
224 default:
225 event.Skip();
226 return;
227 }
228
229 float angle = 5;
230 if ( inverse )
231 angle = -angle;
232
233 *p += angle;
234
235 Refresh(false);
236 }
237
238 // ----------------------------------------------------------------------------
239 // MyFrame: main application window
240 // ----------------------------------------------------------------------------
241
242 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
243 EVT_MENU(wxID_NEW, MyFrame::OnNewWindow)
244 EVT_MENU(wxID_CLOSE, MyFrame::OnClose)
245 END_EVENT_TABLE()
246
247 MyFrame::MyFrame()
248 : wxFrame(NULL, wxID_ANY, _T("wxWidgets OpenGL Cube Sample"))
249 {
250 new TestGLCanvas(this);
251
252 SetIcon(wxICON(sample));
253
254 // Make a menubar
255 wxMenu *menu = new wxMenu;
256 menu->Append(wxID_NEW);
257 menu->AppendSeparator();
258 menu->Append(wxID_CLOSE);
259 wxMenuBar *menuBar = new wxMenuBar;
260 menuBar->Append(menu, _T("&Cube"));
261
262 SetMenuBar(menuBar);
263
264 CreateStatusBar();
265
266 SetClientSize(400, 400);
267 Show();
268 }
269
270 void MyFrame::OnClose(wxCommandEvent& WXUNUSED(event))
271 {
272 // true is to force the frame to close
273 Close(true);
274 }
275
276 void MyFrame::OnNewWindow( wxCommandEvent& WXUNUSED(event) )
277 {
278 (void) new MyFrame();
279 }
280