]> git.saurik.com Git - wxWidgets.git/blob - samples/opengl/isosurf/isosurf.cpp
Workaround for Ctrl-A giving a keycode of 1 in EVT_KEY_DOWN on wxGTK
[wxWidgets.git] / samples / opengl / isosurf / isosurf.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: isosurf.cpp
3 // Purpose: wxGLCanvas demo program
4 // Author: Brian Paul (original gltk version), Wolfram Gloger
5 // Modified by: Julian Smart
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
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 #if !wxUSE_GLCANVAS
29 #error Please set wxUSE_GLCANVAS to 1 in setup.h.
30 #endif
31
32 #include "wx/timer.h"
33 #include "wx/glcanvas.h"
34
35 #ifdef __WXMAC__
36 # ifdef __DARWIN__
37 # include <OpenGL/gl.h>
38 # include <OpenGL/glu.h>
39 # else
40 # include <gl.h>
41 # include <glu.h>
42 # endif
43 #else
44 # include <GL/gl.h>
45 # include <GL/glu.h>
46 #endif
47
48 #include "isosurf.h"
49
50 // The following part is taken largely unchanged from the original C Version
51
52 #include <math.h>
53
54 GLboolean speed_test = GL_FALSE;
55 GLboolean use_vertex_arrays = GL_FALSE;
56
57 GLboolean doubleBuffer = GL_TRUE;
58
59 GLboolean smooth = GL_TRUE;
60 GLboolean lighting = GL_TRUE;
61
62
63 #define MAXVERTS 10000
64
65 static GLfloat verts[MAXVERTS][3];
66 static GLfloat norms[MAXVERTS][3];
67 static GLint numverts;
68
69 static GLfloat xrot;
70 static GLfloat yrot;
71
72
73 static void read_surface( char *filename )
74 {
75 FILE *f;
76
77 f = fopen(filename,"r");
78 if (!f) {
79 wxString msg("Couldn't read ");
80 msg += filename;
81 wxMessageBox(msg);
82 return;
83 }
84
85 numverts = 0;
86 while (!feof(f) && numverts<MAXVERTS) {
87 fscanf( f, "%f %f %f %f %f %f",
88 &verts[numverts][0], &verts[numverts][1], &verts[numverts][2],
89 &norms[numverts][0], &norms[numverts][1], &norms[numverts][2] );
90 numverts++;
91 }
92 numverts--;
93
94 printf("%d vertices, %d triangles\n", numverts, numverts-2);
95 fclose(f);
96 }
97
98
99 static void draw_surface( void )
100 {
101 GLint i;
102
103 #ifdef GL_EXT_vertex_array
104 if (use_vertex_arrays) {
105 glDrawArraysEXT( GL_TRIANGLE_STRIP, 0, numverts );
106 }
107 else {
108 #endif
109 glBegin( GL_TRIANGLE_STRIP );
110 for (i=0;i<numverts;i++) {
111 glNormal3fv( norms[i] );
112 glVertex3fv( verts[i] );
113 }
114 glEnd();
115 #ifdef GL_EXT_vertex_array
116 }
117 #endif
118 }
119
120
121 static void draw1(void)
122 {
123 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
124 glPushMatrix();
125 glRotatef( yrot, 0.0, 1.0, 0.0 );
126 glRotatef( xrot, 1.0, 0.0, 0.0 );
127
128 draw_surface();
129
130 glPopMatrix();
131
132 glFlush();
133 }
134
135
136 static void InitMaterials(void)
137 {
138 static float ambient[] = {0.1, 0.1, 0.1, 1.0};
139 static float diffuse[] = {0.5, 1.0, 1.0, 1.0};
140 static float position0[] = {0.0, 0.0, 20.0, 0.0};
141 static float position1[] = {0.0, 0.0, -20.0, 0.0};
142 static float front_mat_shininess[] = {60.0};
143 static float front_mat_specular[] = {0.2, 0.2, 0.2, 1.0};
144 static float front_mat_diffuse[] = {0.5, 0.28, 0.38, 1.0};
145 /*
146 static float back_mat_shininess[] = {60.0};
147 static float back_mat_specular[] = {0.5, 0.5, 0.2, 1.0};
148 static float back_mat_diffuse[] = {1.0, 1.0, 0.2, 1.0};
149 */
150 static float lmodel_ambient[] = {1.0, 1.0, 1.0, 1.0};
151 static float lmodel_twoside[] = {GL_FALSE};
152
153 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
154 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
155 glLightfv(GL_LIGHT0, GL_POSITION, position0);
156 glEnable(GL_LIGHT0);
157
158 glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
159 glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
160 glLightfv(GL_LIGHT1, GL_POSITION, position1);
161 glEnable(GL_LIGHT1);
162
163 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
164 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
165 glEnable(GL_LIGHTING);
166
167 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_mat_shininess);
168 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_mat_specular);
169 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, front_mat_diffuse);
170 }
171
172
173 static void Init(void)
174 {
175 glClearColor(0.0, 0.0, 0.0, 0.0);
176
177 glShadeModel(GL_SMOOTH);
178 glEnable(GL_DEPTH_TEST);
179
180 InitMaterials();
181
182 glMatrixMode(GL_PROJECTION);
183 glLoadIdentity();
184 glFrustum( -1.0, 1.0, -1.0, 1.0, 5, 25 );
185
186 glMatrixMode(GL_MODELVIEW);
187 glLoadIdentity();
188 glTranslatef( 0.0, 0.0, -6.0 );
189
190 #ifdef GL_EXT_vertex_array
191 if (use_vertex_arrays) {
192 glVertexPointerEXT( 3, GL_FLOAT, 0, numverts, verts );
193 glNormalPointerEXT( GL_FLOAT, 0, numverts, norms );
194 glEnable( GL_VERTEX_ARRAY_EXT );
195 glEnable( GL_NORMAL_ARRAY_EXT );
196 }
197 #endif
198 }
199
200
201 static void Reshape(int width, int height)
202 {
203 glViewport(0, 0, (GLint)width, (GLint)height);
204 }
205
206
207 static GLenum Args(int argc, char **argv)
208 {
209 GLint i;
210
211 for (i = 1; i < argc; i++) {
212 if (strcmp(argv[i], "-sb") == 0) {
213 doubleBuffer = GL_FALSE;
214 }
215 else if (strcmp(argv[i], "-db") == 0) {
216 doubleBuffer = GL_TRUE;
217 }
218 else if (strcmp(argv[i], "-speed") == 0) {
219 speed_test = GL_TRUE;
220 doubleBuffer = GL_TRUE;
221 }
222 else if (strcmp(argv[i], "-va") == 0) {
223 use_vertex_arrays = GL_TRUE;
224 }
225 else {
226 wxString msg("Bad option: ");
227 msg += argv[i];
228 wxMessageBox(msg);
229 return GL_FALSE;
230 }
231 }
232
233 return GL_TRUE;
234 }
235
236 // The following part was written for wxWindows 1.66
237 MyFrame *frame = NULL;
238
239 IMPLEMENT_APP(MyApp)
240
241 // `Main program' equivalent, creating windows and returning main app frame
242 bool MyApp::OnInit(void)
243 {
244 Args(argc, argv);
245
246 // Create the main frame window
247 frame = new MyFrame(NULL, "Isosurf GL Sample", wxPoint(50, 50), wxSize(200, 200));
248
249 // Give it an icon
250 frame->SetIcon(wxIcon("mondrian"));
251
252 // Make a menubar
253 wxMenu *fileMenu = new wxMenu;
254
255 fileMenu->Append(wxID_EXIT, "E&xit");
256 wxMenuBar *menuBar = new wxMenuBar;
257 menuBar->Append(fileMenu, "&File");
258 frame->SetMenuBar(menuBar);
259
260 // Make a TestGLCanvas
261
262 // JACS
263 #ifdef __WXMSW__
264 int *gl_attrib = NULL;
265 #else
266 int gl_attrib[20] = { WX_GL_RGBA, WX_GL_MIN_RED, 1, WX_GL_MIN_GREEN, 1,
267 WX_GL_MIN_BLUE, 1, WX_GL_DEPTH_SIZE, 1,
268 WX_GL_DOUBLEBUFFER,
269 # ifdef __WXMAC__
270 GL_NONE };
271 # else
272 None };
273 # endif
274 #endif
275
276 if(!doubleBuffer)
277 {
278 printf("don't have double buffer, disabling\n");
279 #ifdef __WXGTK__
280 gl_attrib[9] = None;
281 #endif
282 doubleBuffer = GL_FALSE;
283 }
284
285 frame->m_canvas = new TestGLCanvas(frame, -1, wxPoint(0, 0), wxSize(200, 200),
286 0, "TestGLCanvas", gl_attrib );
287
288 // Show the frame
289 frame->Show(TRUE);
290
291 frame->m_canvas->SetCurrent();
292 read_surface( "isosurf.dat" );
293
294 Init();
295
296 return TRUE;
297 }
298
299 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
300 EVT_MENU(wxID_EXIT, MyFrame::OnExit)
301 END_EVENT_TABLE()
302
303 // My frame constructor
304 MyFrame::MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos,
305 const wxSize& size, long style):
306 wxFrame(frame, -1, title, pos, size, style)
307 {
308 m_canvas = NULL;
309 }
310
311 // Intercept menu commands
312 void MyFrame::OnExit(wxCommandEvent& event)
313 {
314 Destroy();
315 }
316
317 /*
318 * TestGLCanvas implementation
319 */
320
321 BEGIN_EVENT_TABLE(TestGLCanvas, wxGLCanvas)
322 EVT_SIZE(TestGLCanvas::OnSize)
323 EVT_PAINT(TestGLCanvas::OnPaint)
324 EVT_CHAR(TestGLCanvas::OnChar)
325 EVT_MOUSE_EVENTS(TestGLCanvas::OnMouseEvent)
326 EVT_ERASE_BACKGROUND(TestGLCanvas::OnEraseBackground)
327 END_EVENT_TABLE()
328
329 TestGLCanvas::TestGLCanvas(wxWindow *parent, wxWindowID id,
330 const wxPoint& pos, const wxSize& size, long style, const wxString& name, int* gl_attrib):
331 wxGLCanvas(parent, id, pos, size, style, name, gl_attrib)
332 {
333 parent->Show(TRUE);
334 SetCurrent();
335
336 /* Make sure server supports the vertex array extension */
337 char* extensions = (char *) glGetString( GL_EXTENSIONS );
338 if (!extensions || !strstr( extensions, "GL_EXT_vertex_array" )) {
339 use_vertex_arrays = GL_FALSE;
340 }
341 }
342
343
344 TestGLCanvas::~TestGLCanvas(void)
345 {
346 }
347
348 void TestGLCanvas::OnPaint( wxPaintEvent& event )
349 {
350 // This is a dummy, to avoid an endless succession of paint messages.
351 // OnPaint handlers must always create a wxPaintDC.
352 wxPaintDC dc(this);
353
354 #ifndef __WXMOTIF__
355 if (!GetContext()) return;
356 #endif
357
358 SetCurrent();
359
360 draw1();
361 SwapBuffers();
362 }
363
364 void TestGLCanvas::OnSize(wxSizeEvent& event)
365 {
366 #ifndef __WXMOTIF__
367 if (!GetContext()) return;
368 #endif
369
370 SetCurrent();
371 int width, height;
372 GetClientSize(& width, & height);
373 Reshape(width, height);
374 }
375
376 void TestGLCanvas::OnChar(wxKeyEvent& event)
377 {
378 switch(event.KeyCode()) {
379 case WXK_ESCAPE:
380 exit(0);
381 case WXK_LEFT:
382 yrot -= 15.0;
383 break;
384 case WXK_RIGHT:
385 yrot += 15.0;
386 break;
387 case WXK_UP:
388 xrot += 15.0;
389 break;
390 case WXK_DOWN:
391 xrot -= 15.0;
392 break;
393 case 's': case 'S':
394 smooth = !smooth;
395 if (smooth) {
396 glShadeModel(GL_SMOOTH);
397 } else {
398 glShadeModel(GL_FLAT);
399 }
400 break;
401 case 'l': case 'L':
402 lighting = !lighting;
403 if (lighting) {
404 glEnable(GL_LIGHTING);
405 } else {
406 glDisable(GL_LIGHTING);
407 }
408 break;
409 default:
410 {
411 event.Skip();
412 return;
413 }
414 }
415
416 Refresh(FALSE);
417 }
418
419 void TestGLCanvas::OnMouseEvent(wxMouseEvent& event)
420 {
421 static int dragging = 0;
422 static float last_x, last_y;
423
424 //printf("%f %f %d\n", event.GetX(), event.GetY(), (int)event.LeftIsDown());
425 if(event.LeftIsDown()) {
426 if(!dragging) {
427 dragging = 1;
428 } else {
429 yrot += (event.GetX() - last_x)*1.0;
430 xrot += (event.GetY() - last_y)*1.0;
431 Refresh(FALSE);
432 }
433 last_x = event.GetX();
434 last_y = event.GetY();
435 } else
436 dragging = 0;
437 }
438
439 void TestGLCanvas::OnEraseBackground(wxEraseEvent& event)
440 {
441 // Do nothing, to avoid flashing.
442 }
443