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