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