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