]>
Commit | Line | Data |
---|---|---|
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 | ||
28 | #include "wx/timer.h" | |
29 | #include "wx/glcanvas.h" | |
30 | ||
cb712074 GD |
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 | |
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 | ||
8b089c5e JS |
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 | ||
2db98bf5 | 75 | static void read_surface( wxChar *filename ) |
8b089c5e JS |
76 | { |
77 | FILE *f; | |
78 | ||
2db98bf5 | 79 | f = wxFopen(filename,_T("r")); |
8b089c5e | 80 | if (!f) { |
2db98bf5 | 81 | wxString msg(_T("Couldn't read ")); |
8b089c5e JS |
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", | |
2f6c54eb VZ |
90 | &verts[numverts][0], &verts[numverts][1], &verts[numverts][2], |
91 | &norms[numverts][0], &norms[numverts][1], &norms[numverts][2] ); | |
8b089c5e JS |
92 | numverts++; |
93 | } | |
94 | numverts--; | |
95 | ||
2db98bf5 | 96 | wxPrintf(_T("%d vertices, %d triangles\n"), numverts, numverts-2); |
8b089c5e JS |
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 | ||
2db98bf5 | 202 | static GLenum Args(int argc, wxChar **argv) |
8b089c5e JS |
203 | { |
204 | GLint i; | |
205 | ||
206 | for (i = 1; i < argc; i++) { | |
2db98bf5 | 207 | if (wxStrcmp(argv[i], _T("-sb")) == 0) { |
8b089c5e JS |
208 | doubleBuffer = GL_FALSE; |
209 | } | |
2db98bf5 | 210 | else if (wxStrcmp(argv[i], _T("-db")) == 0) { |
8b089c5e JS |
211 | doubleBuffer = GL_TRUE; |
212 | } | |
2db98bf5 | 213 | else if (wxStrcmp(argv[i], _T("-speed")) == 0) { |
8b089c5e JS |
214 | speed_test = GL_TRUE; |
215 | doubleBuffer = GL_TRUE; | |
216 | } | |
2db98bf5 | 217 | else if (wxStrcmp(argv[i], _T("-va")) == 0) { |
8b089c5e JS |
218 | use_vertex_arrays = GL_TRUE; |
219 | } | |
220 | else { | |
2db98bf5 | 221 | wxString msg(_T("Bad option: ")); |
8b089c5e JS |
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 | |
2db98bf5 | 242 | frame = new MyFrame(NULL, _T("Isosurf GL Sample"), wxPoint(50, 50), wxSize(200, 200)); |
8b089c5e JS |
243 | |
244 | // Give it an icon | |
2db98bf5 | 245 | frame->SetIcon(wxIcon(_T("mondrian"))); |
8b089c5e JS |
246 | |
247 | // Make a menubar | |
248 | wxMenu *fileMenu = new wxMenu; | |
249 | ||
2db98bf5 | 250 | fileMenu->Append(wxID_EXIT, _T("E&xit")); |
8b089c5e | 251 | wxMenuBar *menuBar = new wxMenuBar; |
2db98bf5 | 252 | menuBar->Append(fileMenu, _T("&File")); |
8b089c5e JS |
253 | frame->SetMenuBar(menuBar); |
254 | ||
255 | // Make a TestGLCanvas | |
256 | ||
257 | // JACS | |
258 | #ifdef __WXMSW__ | |
259 | int *gl_attrib = NULL; | |
260 | #else | |
919ae91a | 261 | int gl_attrib[20] = { WX_GL_RGBA, WX_GL_MIN_RED, 1, WX_GL_MIN_GREEN, 1, |
2f6c54eb VZ |
262 | WX_GL_MIN_BLUE, 1, WX_GL_DEPTH_SIZE, 1, |
263 | WX_GL_DOUBLEBUFFER, | |
cb712074 | 264 | # ifdef __WXMAC__ |
2f6c54eb | 265 | GL_NONE }; |
cb712074 | 266 | # else |
2f6c54eb | 267 | None }; |
cb712074 | 268 | # endif |
8b089c5e JS |
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 | } | |
919ae91a | 279 | |
2db98bf5 JS |
280 | #if wxUSE_GLCANVAS |
281 | ||
9d705dfa | 282 | frame->m_canvas = new TestGLCanvas(frame, -1, wxDefaultPosition, wxDefaultSize, |
2db98bf5 | 283 | 0, _T("TestGLCanvas"), gl_attrib ); |
8b089c5e JS |
284 | |
285 | // Show the frame | |
286 | frame->Show(TRUE); | |
287 | ||
288 | frame->m_canvas->SetCurrent(); | |
2db98bf5 | 289 | read_surface( _T("isosurf.dat") ); |
8b089c5e JS |
290 | |
291 | Init(); | |
292 | ||
293 | return TRUE; | |
2db98bf5 JS |
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 | |
8b089c5e JS |
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 | { | |
2db98bf5 | 312 | #if wxUSE_GLCANVAS |
8b089c5e | 313 | m_canvas = NULL; |
2db98bf5 | 314 | #endif |
8b089c5e JS |
315 | } |
316 | ||
317 | // Intercept menu commands | |
2db98bf5 | 318 | void MyFrame::OnExit(wxCommandEvent& WXUNUSED(event)) |
8b089c5e JS |
319 | { |
320 | Destroy(); | |
321 | } | |
322 | ||
323 | /* | |
324 | * TestGLCanvas implementation | |
325 | */ | |
326 | ||
2db98bf5 JS |
327 | #if wxUSE_GLCANVAS |
328 | ||
8b089c5e JS |
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(); | |
919ae91a | 343 | |
8b089c5e JS |
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 | ||
2db98bf5 | 356 | void TestGLCanvas::OnPaint( wxPaintEvent& WXUNUSED(event) ) |
8b089c5e JS |
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 | ||
c661ecca RR |
362 | #ifndef __WXMOTIF__ |
363 | if (!GetContext()) return; | |
364 | #endif | |
365 | ||
919ae91a UN |
366 | SetCurrent(); |
367 | ||
8b089c5e JS |
368 | draw1(); |
369 | SwapBuffers(); | |
370 | } | |
371 | ||
372 | void TestGLCanvas::OnSize(wxSizeEvent& event) | |
373 | { | |
9d705dfa GD |
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...) | |
2f6c54eb VZ |
378 | int w, h; |
379 | GetClientSize(&w, &h); | |
c661ecca | 380 | #ifndef __WXMOTIF__ |
9d705dfa | 381 | if (GetContext()) |
c661ecca | 382 | #endif |
9d705dfa | 383 | { |
2f6c54eb | 384 | SetCurrent(); |
9d705dfa GD |
385 | glViewport(0, 0, (GLint) w, (GLint) h); |
386 | } | |
8b089c5e JS |
387 | } |
388 | ||
389 | void TestGLCanvas::OnChar(wxKeyEvent& event) | |
390 | { | |
b1d4dd7a | 391 | switch(event.GetKeyCode()) { |
8b089c5e | 392 | case WXK_ESCAPE: |
2f6c54eb | 393 | exit(0); |
8b089c5e | 394 | case WXK_LEFT: |
2f6c54eb VZ |
395 | yrot -= 15.0; |
396 | break; | |
8b089c5e | 397 | case WXK_RIGHT: |
2f6c54eb VZ |
398 | yrot += 15.0; |
399 | break; | |
8b089c5e | 400 | case WXK_UP: |
2f6c54eb VZ |
401 | xrot += 15.0; |
402 | break; | |
8b089c5e | 403 | case WXK_DOWN: |
2f6c54eb VZ |
404 | xrot -= 15.0; |
405 | break; | |
8b089c5e | 406 | case 's': case 'S': |
2f6c54eb VZ |
407 | smooth = !smooth; |
408 | if (smooth) { | |
409 | glShadeModel(GL_SMOOTH); | |
410 | } else { | |
411 | glShadeModel(GL_FLAT); | |
412 | } | |
413 | break; | |
8b089c5e | 414 | case 'l': case 'L': |
2f6c54eb VZ |
415 | lighting = !lighting; |
416 | if (lighting) { | |
417 | glEnable(GL_LIGHTING); | |
418 | } else { | |
419 | glDisable(GL_LIGHTING); | |
420 | } | |
421 | break; | |
8b089c5e JS |
422 | default: |
423 | { | |
424 | event.Skip(); | |
2f6c54eb | 425 | return; |
8b089c5e JS |
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()) { | |
2f6c54eb VZ |
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(); | |
8b089c5e | 448 | } else |
2f6c54eb | 449 | dragging = 0; |
8b089c5e JS |
450 | } |
451 | ||
2db98bf5 | 452 | void TestGLCanvas::OnEraseBackground(wxEraseEvent& WXUNUSED(event)) |
8b089c5e JS |
453 | { |
454 | // Do nothing, to avoid flashing. | |
455 | } | |
456 | ||
2db98bf5 | 457 | #endif |