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