Moved wxGLCanvas to more normal positions
[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 #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 {
259 printf("don't have double buffer, disabling\n");
260 #ifdef __WXGTK__
261 gl_attrib[9] = None;
262 #endif
263 doubleBuffer = GL_FALSE;
264 }
265 frame->m_canvas = new TestGLCanvas(frame, -1, wxPoint(0, 0), wxSize(200, 200), 0, "TestGLCanvas",
266 gl_attrib);
267
268 // Show the frame
269 frame->Show(TRUE);
270
271 frame->m_canvas->SetCurrent();
272 read_surface( "isosurf.dat" );
273
274 Init();
275
276 return TRUE;
277 }
278
279 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
280 EVT_MENU(wxID_EXIT, MyFrame::OnExit)
281 END_EVENT_TABLE()
282
283 // My frame constructor
284 MyFrame::MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos,
285 const wxSize& size, long style):
286 wxFrame(frame, -1, title, pos, size, style)
287 {
288 m_canvas = NULL;
289 }
290
291 // Intercept menu commands
292 void MyFrame::OnExit(wxCommandEvent& event)
293 {
294 Destroy();
295 }
296
297 /*
298 * TestGLCanvas implementation
299 */
300
301 BEGIN_EVENT_TABLE(TestGLCanvas, wxGLCanvas)
302 EVT_SIZE(TestGLCanvas::OnSize)
303 EVT_PAINT(TestGLCanvas::OnPaint)
304 EVT_CHAR(TestGLCanvas::OnChar)
305 EVT_MOUSE_EVENTS(TestGLCanvas::OnMouseEvent)
306 EVT_ERASE_BACKGROUND(TestGLCanvas::OnEraseBackground)
307 END_EVENT_TABLE()
308
309 TestGLCanvas::TestGLCanvas(wxWindow *parent, wxWindowID id,
310 const wxPoint& pos, const wxSize& size, long style, const wxString& name, int* gl_attrib):
311 wxGLCanvas(parent, id, pos, size, style, name, gl_attrib)
312 {
313 parent->Show(TRUE);
314 SetCurrent();
315 /* Make sure server supports the vertex array extension */
316 char* extensions = (char *) glGetString( GL_EXTENSIONS );
317 if (!extensions || !strstr( extensions, "GL_EXT_vertex_array" )) {
318 use_vertex_arrays = GL_FALSE;
319 }
320 }
321
322
323 TestGLCanvas::~TestGLCanvas(void)
324 {
325 }
326
327 void TestGLCanvas::OnPaint( wxPaintEvent& event )
328 {
329 // This is a dummy, to avoid an endless succession of paint messages.
330 // OnPaint handlers must always create a wxPaintDC.
331 wxPaintDC dc(this);
332
333 draw1();
334 SwapBuffers();
335 }
336
337 void TestGLCanvas::OnSize(wxSizeEvent& event)
338 {
339 SetCurrent();
340 int width, height;
341 GetClientSize(& width, & height);
342 Reshape(width, height);
343 }
344
345 void TestGLCanvas::OnChar(wxKeyEvent& event)
346 {
347 switch(event.KeyCode()) {
348 case WXK_ESCAPE:
349 exit(0);
350 case WXK_LEFT:
351 yrot -= 15.0;
352 break;
353 case WXK_RIGHT:
354 yrot += 15.0;
355 break;
356 case WXK_UP:
357 xrot += 15.0;
358 break;
359 case WXK_DOWN:
360 xrot -= 15.0;
361 break;
362 case 's': case 'S':
363 smooth = !smooth;
364 if (smooth) {
365 glShadeModel(GL_SMOOTH);
366 } else {
367 glShadeModel(GL_FLAT);
368 }
369 break;
370 case 'l': case 'L':
371 lighting = !lighting;
372 if (lighting) {
373 glEnable(GL_LIGHTING);
374 } else {
375 glDisable(GL_LIGHTING);
376 }
377 break;
378 default:
379 {
380 event.Skip();
381 return;
382 }
383 }
384
385 Refresh(FALSE);
386 }
387
388 void TestGLCanvas::OnMouseEvent(wxMouseEvent& event)
389 {
390 static int dragging = 0;
391 static float last_x, last_y;
392
393 //printf("%f %f %d\n", event.GetX(), event.GetY(), (int)event.LeftIsDown());
394 if(event.LeftIsDown()) {
395 if(!dragging) {
396 dragging = 1;
397 } else {
398 yrot += (event.GetX() - last_x)*1.0;
399 xrot += (event.GetY() - last_y)*1.0;
400 Refresh(FALSE);
401 }
402 last_x = event.GetX();
403 last_y = event.GetY();
404 } else
405 dragging = 0;
406 }
407
408 void TestGLCanvas::OnEraseBackground(wxEraseEvent& event)
409 {
410 // Do nothing, to avoid flashing.
411 }
412