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