blob: 8ab73e917fef20d230eab43a10f1888184cb75cb [file] [log] [blame]
Keith Whitwell44c73931999-09-03 14:56:40 +00001/* $Id: isosurf.c,v 1.2 1999/09/03 14:56:40 keithw Exp $ */
jtgafb833d1999-08-19 00:55:39 +00002
3/*
Keith Whitwell44c73931999-09-03 14:56:40 +00004 * Display an isosurface of 3-D wind speed volume.
5 *
jtgafb833d1999-08-19 00:55:39 +00006 * Brian Paul This file in public domain.
7 */
8
Keith Whitwell44c73931999-09-03 14:56:40 +00009
10/* Keys:
11 * =====
12 *
13 * - Arrow keys to rotate
14 * - 's' toggles smooth shading
15 * - 'l' toggles lighting
16 * - 'f' toggles fog
17 * - 'I' and 'i' zoom in and out
18 * - 'c' toggles a user clip plane
19 * - 'm' toggles colorful materials in GL_TRIANGLES modes.
20 * - '+' and '-' move the user clip plane
21 *
22 * Other options are available via the popup menu.
23 */
24
jtgafb833d1999-08-19 00:55:39 +000025/*
26 * $Log: isosurf.c,v $
Keith Whitwell44c73931999-09-03 14:56:40 +000027 * Revision 1.2 1999/09/03 14:56:40 keithw
28 * Fog, displaylist and zoom operations
jtgafb833d1999-08-19 00:55:39 +000029 *
30 * Revision 3.4 1999/04/24 01:10:47 keithw
31 * clip planes, materials
32 *
33 * Revision 3.3 1999/03/31 19:42:14 keithw
34 * support for cva
35 *
36 * Revision 3.1 1998/11/01 20:30:20 brianp
37 * added benchmark feature (b key)
38 *
39 * Revision 3.0 1998/02/14 18:42:29 brianp
40 * initial rev
41 *
42 */
43
44
45
46#include <stdio.h>
47#include <string.h>
48#include <stdlib.h>
49#include <math.h>
50#include "GL/glut.h"
51
52#include "../util/readtex.c" /* I know, this is a hack. KW: me too. */
53#define TEXTURE_FILE "../images/reflect.rgb"
54
55#define LIT 0x1
56#define UNLIT 0x2
57#define TEXTURE 0x4
58#define NO_TEXTURE 0x8
59#define REFLECT 0x10
60#define NO_REFLECT 0x20
61#define POINT_FILTER 0x40
62#define LINEAR_FILTER 0x80
Keith Whitwell44c73931999-09-03 14:56:40 +000063#define GLVERTEX 0x100
jtgafb833d1999-08-19 00:55:39 +000064#define DRAW_ARRAYS 0x200 /* or draw_elts, if compiled */
65#define ARRAY_ELT 0x400
66#define COMPILED 0x800
Keith Whitwell44c73931999-09-03 14:56:40 +000067#define IMMEDIATE 0x1000
jtgafb833d1999-08-19 00:55:39 +000068#define SHADE_SMOOTH 0x2000
69#define SHADE_FLAT 0x4000
70#define TRIANGLES 0x8000
71#define STRIPS 0x10000
72#define USER_CLIP 0x20000
73#define NO_USER_CLIP 0x40000
74#define MATERIALS 0x80000
75#define NO_MATERIALS 0x100000
Keith Whitwell44c73931999-09-03 14:56:40 +000076#define FOG 0x200000
77#define NO_FOG 0x400000
jtgafb833d1999-08-19 00:55:39 +000078#define QUIT 0x800000
Keith Whitwell44c73931999-09-03 14:56:40 +000079#define DISPLAYLIST 0x1000000
jtgafb833d1999-08-19 00:55:39 +000080
81#define LIGHT_MASK (LIT|UNLIT)
82#define TEXTURE_MASK (TEXTURE|NO_TEXTURE)
83#define REFLECT_MASK (REFLECT|NO_REFLECT)
84#define FILTER_MASK (POINT_FILTER|LINEAR_FILTER)
Keith Whitwell44c73931999-09-03 14:56:40 +000085#define RENDER_STYLE_MASK (GLVERTEX|DRAW_ARRAYS|ARRAY_ELT)
86#define COMPILED_MASK (COMPILED|IMMEDIATE|DISPLAYLIST)
jtgafb833d1999-08-19 00:55:39 +000087#define MATERIAL_MASK (MATERIALS|NO_MATERIALS)
88#define PRIMITIVE_MASK (TRIANGLES|STRIPS)
89#define CLIP_MASK (USER_CLIP|NO_USER_CLIP)
90#define SHADE_MASK (SHADE_SMOOTH|SHADE_FLAT)
Keith Whitwell44c73931999-09-03 14:56:40 +000091#define FOG_MASK (FOG|NO_FOG)
jtgafb833d1999-08-19 00:55:39 +000092
93#define MAXVERTS 10000
94static float data[MAXVERTS][6];
95static float compressed_data[MAXVERTS][6];
96static GLuint indices[MAXVERTS];
97static GLuint tri_indices[MAXVERTS*3];
98static GLfloat col[100][4];
99static GLint numverts, num_tri_verts, numuniq;
100
101static GLfloat xrot;
102static GLfloat yrot;
Keith Whitwell44c73931999-09-03 14:56:40 +0000103static GLfloat dist = -6;
jtgafb833d1999-08-19 00:55:39 +0000104static GLint state, allowed = ~0;
105static GLboolean doubleBuffer = GL_TRUE;
106static GLdouble plane[4] = {1.0, 0.0, -1.0, 0.0};
Keith Whitwell44c73931999-09-03 14:56:40 +0000107static GLuint surf1;
jtgafb833d1999-08-19 00:55:39 +0000108
109static void read_surface( char *filename )
110{
111 FILE *f;
112
113 f = fopen(filename,"r");
114 if (!f) {
115 printf("couldn't read %s\n", filename);
116 exit(1);
117 }
118
119 numverts = 0;
120 while (!feof(f) && numverts<MAXVERTS) {
121 fscanf( f, "%f %f %f %f %f %f",
122 &data[numverts][0], &data[numverts][1], &data[numverts][2],
123 &data[numverts][3], &data[numverts][4], &data[numverts][5] );
124 numverts++;
125 }
126 numverts--;
127
128 printf("%d vertices, %d triangles\n", numverts, numverts-2);
129 fclose(f);
130}
131
132
133
134
135struct data_idx {
136 float *data;
137 int idx;
138 int uniq_idx;
139};
140
141
142#define COMPARE_FUNC( AXIS ) \
143int compare_axis_##AXIS( const void *a, const void *b ) \
144{ \
145 float t = ( (*(struct data_idx *)a).data[AXIS] - \
146 (*(struct data_idx *)b).data[AXIS] ); \
147 \
148 if (t < 0) return -1; \
149 if (t > 0) return 1; \
150 return 0; \
151}
152
153COMPARE_FUNC(0)
154COMPARE_FUNC(1)
155COMPARE_FUNC(2)
156COMPARE_FUNC(3)
157COMPARE_FUNC(4)
158COMPARE_FUNC(5)
159COMPARE_FUNC(6)
160
161int (*(compare[7]))( const void *a, const void *b ) =
162{
163 compare_axis_0,
164 compare_axis_1,
165 compare_axis_2,
166 compare_axis_3,
167 compare_axis_4,
168 compare_axis_5,
169 compare_axis_6,
170};
171
172
173#define VEC_ELT(f, s, i) (float *)(((char *)f) + s * i)
174
175static int sort_axis( int axis,
176 int vec_size,
177 int vec_stride,
178 struct data_idx *indices,
179 int start,
180 int finish,
181 float *out,
182 int uniq,
183 const float fudge )
184{
185 int i;
186
187 if (finish-start > 2)
188 {
189 qsort( indices+start, finish-start, sizeof(*indices), compare[axis] );
190 }
191 else if (indices[start].data[axis] > indices[start+1].data[axis])
192 {
193 struct data_idx tmp = indices[start];
194 indices[start] = indices[start+1];
195 indices[start+1] = tmp;
196 }
197
198 if (axis == vec_size-1) {
199 for (i = start ; i < finish ; ) {
200 float max = indices[i].data[axis] + fudge;
201 float *dest = VEC_ELT(out, vec_stride, uniq);
202 int j;
203
204 for (j = 0 ; j < vec_size ; j++)
205 dest[j] = indices[i].data[j];
206
207 for ( ; i < finish && max >= indices[i].data[axis]; i++)
208 indices[i].uniq_idx = uniq;
209
210 uniq++;
211 }
212 } else {
213 for (i = start ; i < finish ; ) {
214 int j = i + 1;
215 float max = indices[i].data[axis] + fudge;
216 while (j < finish && max >= indices[j].data[axis]) j++;
217 if (j == i+1) {
218 float *dest = VEC_ELT(out, vec_stride, uniq);
219 int k;
220
221 indices[i].uniq_idx = uniq;
222
223 for (k = 0 ; k < vec_size ; k++)
224 dest[k] = indices[i].data[k];
225
226 uniq++;
227 } else {
228 uniq = sort_axis( axis+1, vec_size, vec_stride,
229 indices, i, j, out, uniq, fudge );
230 }
231 i = j;
232 }
233 }
234
235 return uniq;
236}
237
238
239static void extract_indices1( const struct data_idx *in, unsigned int *out,
240 int n )
241{
242 int i;
243 for ( i = 0 ; i < n ; i++ ) {
244 out[in[i].idx] = in[i].uniq_idx;
245 }
246}
247
248
249static void compactify_arrays()
250{
251 int i;
252 struct data_idx *ind;
253
254 ind = (struct data_idx *) malloc( sizeof(struct data_idx) * numverts );
255
256 for (i = 0 ; i < numverts ; i++) {
257 ind[i].idx = i;
258 ind[i].data = data[i];
259 }
260
261 numuniq = sort_axis(0,
262 sizeof(compressed_data[0])/sizeof(float),
263 sizeof(compressed_data[0]),
264 ind,
265 0,
266 numverts,
267 (float *)compressed_data,
268 0,
269 1e-6);
270
271 printf("Nr unique vertex/normal pairs: %d\n", numuniq);
272
273 extract_indices1( ind, indices, numverts );
274 free( ind );
275}
276
277static float myrand( float max )
278{
279 return max*rand()/(RAND_MAX+1.0);
280}
281
282
283static void make_tri_indices( void )
284{
285 unsigned int *v = tri_indices;
286 unsigned int parity = 0;
287 unsigned int i, j;
288
289 for (j=2;j<numverts;j++,parity^=1) {
290 if (parity) {
291 *v++ = indices[j-1];
292 *v++ = indices[j-2];
293 *v++ = indices[j];
294 } else {
295 *v++ = indices[j-2];
296 *v++ = indices[j-1];
297 *v++ = indices[j];
298 }
299 }
300
301 num_tri_verts = v - tri_indices;
302 printf("num_tri_verts: %d\n", num_tri_verts);
303
304 for (i = j = 0 ; i < num_tri_verts ; i += 600, j++) {
305 col[j][3] = 1;
306 col[j][2] = myrand(1);
307 col[j][1] = myrand(1);
308 col[j][0] = myrand(1);
309 }
310}
311
312#define MIN(x,y) (x < y) ? x : y
313
Keith Whitwell44c73931999-09-03 14:56:40 +0000314static void draw_surface( int with_state )
jtgafb833d1999-08-19 00:55:39 +0000315{
316 GLuint i, j;
317
Keith Whitwell44c73931999-09-03 14:56:40 +0000318 switch (with_state & (COMPILED_MASK|RENDER_STYLE_MASK|PRIMITIVE_MASK)) {
jtgafb833d1999-08-19 00:55:39 +0000319#ifdef GL_EXT_vertex_array
320
321 case (COMPILED|DRAW_ARRAYS|STRIPS):
322 glDrawElements( GL_TRIANGLE_STRIP, numverts, GL_UNSIGNED_INT, indices );
323 break;
324
325
326 case (COMPILED|ARRAY_ELT|STRIPS):
327 glBegin( GL_TRIANGLE_STRIP );
328 for (i = 0 ; i < numverts ; i++)
329 glArrayElement( indices[i] );
330 glEnd();
331 break;
332
333 case (COMPILED|DRAW_ARRAYS|TRIANGLES):
Keith Whitwell44c73931999-09-03 14:56:40 +0000334 case (IMMEDIATE|DRAW_ARRAYS|TRIANGLES):
335 if (with_state & MATERIALS) {
jtgafb833d1999-08-19 00:55:39 +0000336 for (j = i = 0 ; i < num_tri_verts ; i += 600, j++) {
337 GLuint nr = MIN(num_tri_verts-i, 600);
338 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col[j]);
339 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col[j]);
340 glDrawElements( GL_TRIANGLES, nr, GL_UNSIGNED_INT, tri_indices+i );
341 }
342 } else {
343 glDrawElements( GL_TRIANGLES, num_tri_verts, GL_UNSIGNED_INT,
344 tri_indices );
345 }
346
347 break;
348
349 /* Uses the original arrays (including duplicate elements):
350 */
Keith Whitwell44c73931999-09-03 14:56:40 +0000351 case (IMMEDIATE|DRAW_ARRAYS|STRIPS):
jtgafb833d1999-08-19 00:55:39 +0000352 glDrawArraysEXT( GL_TRIANGLE_STRIP, 0, numverts );
353 break;
354
355 /* Uses the original arrays (including duplicate elements):
356 */
Keith Whitwell44c73931999-09-03 14:56:40 +0000357 case (IMMEDIATE|ARRAY_ELT|STRIPS):
jtgafb833d1999-08-19 00:55:39 +0000358 glBegin( GL_TRIANGLE_STRIP );
359 for (i = 0 ; i < numverts ; i++)
360 glArrayElement( i );
361 glEnd();
362 break;
363
Keith Whitwell44c73931999-09-03 14:56:40 +0000364 case (IMMEDIATE|ARRAY_ELT|TRIANGLES):
jtgafb833d1999-08-19 00:55:39 +0000365 case (COMPILED|ARRAY_ELT|TRIANGLES):
Keith Whitwell44c73931999-09-03 14:56:40 +0000366 if (with_state & MATERIALS) {
jtgafb833d1999-08-19 00:55:39 +0000367 for (j = i = 0 ; i < num_tri_verts ; i += 600, j++) {
368 GLuint nr = MIN(num_tri_verts-i, 600);
369 GLuint k;
370 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col[j]);
371 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col[j]);
372 glBegin( GL_TRIANGLES );
373 for (k = 0 ; k < nr ; k++)
374 glArrayElement( tri_indices[i+k] );
375 glEnd();
376 }
377 } else {
378 glBegin( GL_TRIANGLES );
379 for (i = 0 ; i < num_tri_verts ; i++)
380 glArrayElement( tri_indices[i] );
Keith Whitwell44c73931999-09-03 14:56:40 +0000381
jtgafb833d1999-08-19 00:55:39 +0000382 glEnd();
383 }
384 break;
385
Keith Whitwell44c73931999-09-03 14:56:40 +0000386 case (IMMEDIATE|GLVERTEX|TRIANGLES):
387 if (with_state & MATERIALS) {
jtgafb833d1999-08-19 00:55:39 +0000388 for (j = i = 0 ; i < num_tri_verts ; i += 600, j++) {
389 GLuint nr = MIN(num_tri_verts-i, 600);
390 GLuint k;
391 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col[j]);
392 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col[j]);
393 glBegin( GL_TRIANGLES );
394 for (k = 0 ; k < nr ; k++) {
395 glNormal3fv( &compressed_data[tri_indices[i+k]][3] );
396 glVertex3fv( &compressed_data[tri_indices[i+k]][0] );
397 }
398 glEnd();
399 }
400 } else {
401 glBegin( GL_TRIANGLES );
402 for (i = 0 ; i < num_tri_verts ; i++) {
403 glNormal3fv( &compressed_data[tri_indices[i]][3] );
404 glVertex3fv( &compressed_data[tri_indices[i]][0] );
405 }
406 glEnd();
407 }
408 break;
409
Keith Whitwell44c73931999-09-03 14:56:40 +0000410 case (DISPLAYLIST|GLVERTEX|STRIPS):
411 if (!surf1)
412 surf1 = BuildList( GL_COMPILE_AND_EXECUTE );
413 else
414 glCallList(surf1);
415 break;
416
jtgafb833d1999-08-19 00:55:39 +0000417#endif
418
419 /* Uses the original arrays (including duplicate elements):
420 */
421 default:
422 glBegin( GL_TRIANGLE_STRIP );
423 for (i=0;i<numverts;i++) {
424 glNormal3fv( &data[i][3] );
425 glVertex3fv( &data[i][0] );
426 }
427 glEnd();
428 }
429}
430
431
432
433static void Display(void)
434{
435 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
Keith Whitwell44c73931999-09-03 14:56:40 +0000436 draw_surface( state );
jtgafb833d1999-08-19 00:55:39 +0000437 glFlush();
438 if (doubleBuffer) glutSwapBuffers();
439}
440
Keith Whitwell44c73931999-09-03 14:56:40 +0000441int BuildList( int mode )
442{
443 int rv = glGenLists(1);
444 glNewList(rv, mode );
445 draw_surface( IMMEDIATE|GLVERTEX|STRIPS );
446 glEndList();
447 return rv;
448}
449
jtgafb833d1999-08-19 00:55:39 +0000450/* KW: only do this when necessary, so CVA can re-use results.
451 */
452static void set_matrix( void )
453{
454 glMatrixMode(GL_MODELVIEW);
455 glLoadIdentity();
Keith Whitwell44c73931999-09-03 14:56:40 +0000456 glTranslatef( 0.0, 0.0, dist );
jtgafb833d1999-08-19 00:55:39 +0000457 glRotatef( yrot, 0.0, 1.0, 0.0 );
458 glRotatef( xrot, 1.0, 0.0, 0.0 );
459}
460
461static void Benchmark( float xdiff, float ydiff )
462{
463 int startTime, endTime;
464 int draws;
465 double seconds, fps, triPerSecond;
466
467 printf("Benchmarking...\n");
468
469 draws = 0;
470 startTime = glutGet(GLUT_ELAPSED_TIME);
471 xrot = 0.0;
472 do {
473 xrot += xdiff;
474 yrot += ydiff;
475 set_matrix();
476 Display();
477 draws++;
478 endTime = glutGet(GLUT_ELAPSED_TIME);
479 } while (endTime - startTime < 5000); /* 5 seconds */
480
481 /* Results */
482 seconds = (double) (endTime - startTime) / 1000.0;
483 triPerSecond = (numverts - 2) * draws / seconds;
484 fps = draws / seconds;
485 printf("Result: triangles/sec: %g fps: %g\n", triPerSecond, fps);
486}
487
488
489static void InitMaterials(void)
490{
491 static float ambient[] = {0.1, 0.1, 0.1, 1.0};
492 static float diffuse[] = {0.5, 1.0, 1.0, 1.0};
493 static float position0[] = {0.0, 0.0, 20.0, 0.0};
494 static float position1[] = {0.0, 0.0, -20.0, 0.0};
495 static float front_mat_shininess[] = {60.0};
496 static float front_mat_specular[] = {0.2, 0.2, 0.2, 1.0};
497 static float front_mat_diffuse[] = {0.5, 0.28, 0.38, 1.0};
498 /*
499 static float back_mat_shininess[] = {60.0};
500 static float back_mat_specular[] = {0.5, 0.5, 0.2, 1.0};
501 static float back_mat_diffuse[] = {1.0, 1.0, 0.2, 1.0};
502 */
503 static float lmodel_ambient[] = {1.0, 1.0, 1.0, 1.0};
504 static float lmodel_twoside[] = {GL_FALSE};
505
506 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
507 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
508 glLightfv(GL_LIGHT0, GL_POSITION, position0);
509 glEnable(GL_LIGHT0);
510
511 glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
512 glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
513 glLightfv(GL_LIGHT1, GL_POSITION, position1);
514 glEnable(GL_LIGHT1);
515
516 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
517 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
518
519 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_mat_shininess);
520 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_mat_specular);
521 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, front_mat_diffuse);
522}
523
524
525
526#define UPDATE(o,n,mask) (o&=~mask, o|=n&mask)
527#define CHANGED(o,n,mask) ((n&mask) && \
528 (n&mask) != (o&mask) ? UPDATE(o,n,mask) : 0)
529
530static void ModeMenu(int m)
531{
532 m &= allowed;
533
534 if (!m) return;
535
536 if (m==QUIT)
537 exit(0);
538
539 if (CHANGED(state, m, FILTER_MASK)) {
540 if (m & LINEAR_FILTER) {
541 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
542 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
543 } else {
544 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
545 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
546 }
547 }
548
549 if (CHANGED(state, m, LIGHT_MASK)) {
550 if (m & LIT)
551 glEnable(GL_LIGHTING);
552 else
553 glDisable(GL_LIGHTING);
554 }
555
556 if (CHANGED(state, m, SHADE_MASK)) {
557 if (m & SHADE_SMOOTH)
558 glShadeModel(GL_SMOOTH);
559 else
560 glShadeModel(GL_FLAT);
561 }
562
563
564 if (CHANGED(state, m, TEXTURE_MASK)) {
565 if (m & TEXTURE)
566 glEnable(GL_TEXTURE_2D);
567 else
568 glDisable(GL_TEXTURE_2D);
569 }
570
571 if (CHANGED(state, m, REFLECT_MASK)) {
572 if (m & REFLECT) {
573 glEnable(GL_TEXTURE_GEN_S);
574 glEnable(GL_TEXTURE_GEN_T);
575 } else {
576 glDisable(GL_TEXTURE_GEN_S);
577 glDisable(GL_TEXTURE_GEN_T);
578 }
579 }
580
581 if (CHANGED(state, m, CLIP_MASK)) {
582 if (m & USER_CLIP) {
583 glEnable(GL_CLIP_PLANE0);
584 } else {
585 glDisable(GL_CLIP_PLANE0);
586 }
587 }
588
Keith Whitwell44c73931999-09-03 14:56:40 +0000589 if (CHANGED(state, m, FOG_MASK)) {
590 if (m & FOG)
591 {
592 glEnable(GL_FOG);
593 printf("FOG enable\n");
594 }
595 else
596 {
597 glDisable(GL_FOG);
598 printf("FOG disable\n");
599 }
600 }
601
jtgafb833d1999-08-19 00:55:39 +0000602#ifdef GL_EXT_vertex_array
603 if (CHANGED(state, m, (COMPILED_MASK|RENDER_STYLE_MASK|PRIMITIVE_MASK)))
604 {
Keith Whitwell44c73931999-09-03 14:56:40 +0000605 if ((m & (COMPILED_MASK|PRIMITIVE_MASK)) == (IMMEDIATE|STRIPS))
jtgafb833d1999-08-19 00:55:39 +0000606 {
607 glVertexPointerEXT( 3, GL_FLOAT, sizeof(data[0]), numverts, data );
608 glNormalPointerEXT( GL_FLOAT, sizeof(data[0]), numverts, &data[0][3]);
609 }
610 else
611 {
612 glVertexPointerEXT( 3, GL_FLOAT, sizeof(data[0]), numuniq,
613 compressed_data );
614 glNormalPointerEXT( GL_FLOAT, sizeof(data[0]), numuniq,
615 &compressed_data[0][3]);
616 }
617#ifdef GL_EXT_compiled_vertex_array
618 if (m & COMPILED) {
619 glLockArraysEXT( 0, numuniq );
620 } else {
621 glUnlockArraysEXT();
622 }
623#endif
624 }
625#endif
626
627 if (m & (RENDER_STYLE_MASK|PRIMITIVE_MASK)) {
628 UPDATE(state, m, (RENDER_STYLE_MASK|PRIMITIVE_MASK));
629 }
630
631 if (m & MATERIAL_MASK) {
632 UPDATE(state, m, MATERIAL_MASK);
633 }
634
635 glutPostRedisplay();
636}
637
638
639
640static void Init(void)
641{
Keith Whitwell44c73931999-09-03 14:56:40 +0000642 GLfloat fogColor[4] = {0.5,1.0,0.5,1.0};
643
jtgafb833d1999-08-19 00:55:39 +0000644 glClearColor(0.0, 0.0, 0.0, 0.0);
645 glEnable( GL_DEPTH_TEST );
646 glEnable( GL_VERTEX_ARRAY_EXT );
647 glEnable( GL_NORMAL_ARRAY_EXT );
648
649 InitMaterials();
650
651 glMatrixMode(GL_PROJECTION);
652 glLoadIdentity();
653 glFrustum( -1.0, 1.0, -1.0, 1.0, 5, 25 );
654
655 glMatrixMode(GL_MODELVIEW);
656 glLoadIdentity();
657 glClipPlane(GL_CLIP_PLANE0, plane);
658
659 set_matrix();
660
661 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
662 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
663
664 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
665 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
666
667 if (!LoadRGBMipmaps(TEXTURE_FILE, GL_RGB)) {
668 printf("Error: couldn't load texture image\n");
669 exit(1);
670 }
671
Keith Whitwell44c73931999-09-03 14:56:40 +0000672 /* Green fog is easy to see */
673 glFogi(GL_FOG_MODE,GL_EXP2);
674 glFogfv(GL_FOG_COLOR,fogColor);
675 glFogf(GL_FOG_DENSITY,0.15);
676 glHint(GL_FOG_HINT,GL_DONT_CARE);
677
678
jtgafb833d1999-08-19 00:55:39 +0000679 if (allowed & COMPILED) {
680 compactify_arrays();
681 make_tri_indices();
682 }
683
Keith Whitwell44c73931999-09-03 14:56:40 +0000684 surf1 = BuildList( GL_COMPILE );
685
jtgafb833d1999-08-19 00:55:39 +0000686 ModeMenu(SHADE_SMOOTH|
687 LIT|
688 NO_TEXTURE|
689 NO_REFLECT|
690 POINT_FILTER|
Keith Whitwell44c73931999-09-03 14:56:40 +0000691 IMMEDIATE|
jtgafb833d1999-08-19 00:55:39 +0000692 NO_USER_CLIP|
693 NO_MATERIALS|
Keith Whitwell44c73931999-09-03 14:56:40 +0000694 NO_FOG|
695 GLVERTEX);
jtgafb833d1999-08-19 00:55:39 +0000696}
697
698
699
700static void Reshape(int width, int height)
701{
702 glViewport(0, 0, (GLint)width, (GLint)height);
703}
704
705
706
707static void Key( unsigned char key, int x, int y )
708{
709 switch (key) {
Keith Whitwell44c73931999-09-03 14:56:40 +0000710 case 27:
711 exit(0);
712 case 'f':
713 ModeMenu((state ^ FOG_MASK) & FOG_MASK);
714 break;
715 case 's':
716 ModeMenu((state ^ SHADE_MASK) & SHADE_MASK);
717 break;
718 case 'l':
719 ModeMenu((state ^ LIGHT_MASK) & LIGHT_MASK);
720 break;
721 case 'm':
722 ModeMenu((state ^ MATERIAL_MASK) & MATERIAL_MASK);
723 break;
724 case 'c':
725 ModeMenu((state ^ CLIP_MASK) & CLIP_MASK);
726 break;
727 case 'b':
728 Benchmark(5.0, 0);
729 break;
730 case 'B':
731 Benchmark(0, 5.0);
732 break;
733 case 'i':
734 dist += .25;
735 set_matrix();
736 glutPostRedisplay();
737 break;
738 case 'I':
739 dist -= .25;
740 set_matrix();
741 glutPostRedisplay();
742 break;
743 case '-':
744 case '_':
745 plane[3] += 2.0;
746 glMatrixMode(GL_MODELVIEW);
747 glLoadIdentity();
748 glClipPlane(GL_CLIP_PLANE0, plane);
749 set_matrix();
750 glutPostRedisplay();
751 break;
752 case '+':
753 case '=':
754 plane[3] -= 2.0;
755 glMatrixMode(GL_MODELVIEW);
756 glLoadIdentity();
757 glClipPlane(GL_CLIP_PLANE0, plane);
758 set_matrix();
759 glutPostRedisplay();
760 break;
jtgafb833d1999-08-19 00:55:39 +0000761
762 }
763}
764
765
766static void SpecialKey( int key, int x, int y )
767{
768 switch (key) {
769 case GLUT_KEY_LEFT:
770 yrot -= 15.0;
771 break;
772 case GLUT_KEY_RIGHT:
773 yrot += 15.0;
774 break;
775 case GLUT_KEY_UP:
776 xrot += 15.0;
777 break;
778 case GLUT_KEY_DOWN:
779 xrot -= 15.0;
780 break;
781 default:
782 return;
783 }
784 set_matrix();
785 glutPostRedisplay();
786}
787
788
789
790static GLint Args(int argc, char **argv)
791{
792 GLint i;
793 GLint mode = 0;
794
795 for (i = 1; i < argc; i++) {
796 if (strcmp(argv[i], "-sb") == 0) {
797 doubleBuffer = GL_FALSE;
798 }
799 else if (strcmp(argv[i], "-db") == 0) {
800 doubleBuffer = GL_TRUE;
801 }
802 else {
803 printf("%s (Bad option).\n", argv[i]);
804 return QUIT;
805 }
806 }
807
808 return mode;
809}
810
811int main(int argc, char **argv)
812{
813 GLenum type;
814 char *extensions;
815
816 GLuint arg_mode = Args(argc, argv);
817
818 if (arg_mode & QUIT)
819 exit(0);
820
821 read_surface( "isosurf.dat" );
822
823 glutInitWindowPosition(0, 0);
824 glutInitWindowSize(400, 400);
825
826 type = GLUT_DEPTH;
827 type |= GLUT_RGB;
828 type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
829 glutInitDisplayMode(type);
830
831 if (glutCreateWindow("Isosurface") <= 0) {
832 exit(0);
833 }
834
835 /* Make sure server supports the vertex array extension */
836 extensions = (char *) glGetString( GL_EXTENSIONS );
837
838 if (!strstr( extensions, "GL_EXT_vertex_array" ))
839 {
840 printf("Vertex arrays not supported by this renderer\n");
841 allowed &= ~(COMPILED|DRAW_ARRAYS|ARRAY_ELT);
842 }
843 else if (!strstr( extensions, "GL_EXT_compiled_vertex_array" ))
844 {
845 printf("Compiled vertex arrays not supported by this renderer\n");
846 allowed &= ~COMPILED;
847 }
848
849 Init();
850 ModeMenu(arg_mode);
851
852 glutCreateMenu(ModeMenu);
853 glutAddMenuEntry("Lit", LIT|NO_TEXTURE|NO_REFLECT);
854 glutAddMenuEntry("Unlit", UNLIT|NO_TEXTURE|NO_REFLECT);
855/* glutAddMenuEntry("Textured", TEXTURE); */
856 glutAddMenuEntry("Reflect", TEXTURE|REFLECT);
857 glutAddMenuEntry("", 0);
858 glutAddMenuEntry("Smooth", SHADE_SMOOTH);
859 glutAddMenuEntry("Flat", SHADE_FLAT);
860 glutAddMenuEntry("", 0);
Keith Whitwell44c73931999-09-03 14:56:40 +0000861 glutAddMenuEntry("Fog", FOG);
862 glutAddMenuEntry("No Fog", NO_FOG);
863 glutAddMenuEntry("", 0);
jtgafb833d1999-08-19 00:55:39 +0000864 glutAddMenuEntry("Point Filtered", POINT_FILTER);
865 glutAddMenuEntry("Linear Filtered", LINEAR_FILTER);
866 glutAddMenuEntry("", 0);
Keith Whitwell44c73931999-09-03 14:56:40 +0000867 glutAddMenuEntry("glVertex (STRIPS)", IMMEDIATE|GLVERTEX|STRIPS);
868 glutAddMenuEntry("glVertex (TRIANGLES)", IMMEDIATE|GLVERTEX|TRIANGLES);
869 glutAddMenuEntry("", 0);
870 glutAddMenuEntry("glVertex display list (STRIPS)",
871 DISPLAYLIST|GLVERTEX|STRIPS);
jtgafb833d1999-08-19 00:55:39 +0000872 glutAddMenuEntry("", 0);
873 if (allowed & DRAW_ARRAYS) {
874 glutAddMenuEntry("DrawArrays (STRIPS)",
Keith Whitwell44c73931999-09-03 14:56:40 +0000875 IMMEDIATE|DRAW_ARRAYS|STRIPS);
jtgafb833d1999-08-19 00:55:39 +0000876 glutAddMenuEntry("ArrayElement (STRIPS)",
Keith Whitwell44c73931999-09-03 14:56:40 +0000877 IMMEDIATE|ARRAY_ELT|STRIPS);
jtgafb833d1999-08-19 00:55:39 +0000878 glutAddMenuEntry("DrawElements (TRIANGLES)",
Keith Whitwell44c73931999-09-03 14:56:40 +0000879 IMMEDIATE|DRAW_ARRAYS|TRIANGLES);
jtgafb833d1999-08-19 00:55:39 +0000880 glutAddMenuEntry("ArrayElement (TRIANGLES)",
Keith Whitwell44c73931999-09-03 14:56:40 +0000881 IMMEDIATE|ARRAY_ELT|TRIANGLES);
jtgafb833d1999-08-19 00:55:39 +0000882 glutAddMenuEntry("", 0);
883
884 }
885 if (allowed & COMPILED) {
886 glutAddMenuEntry("Compiled DrawElements (TRIANGLES)",
887 COMPILED|DRAW_ARRAYS|TRIANGLES);
888 glutAddMenuEntry("Compiled DrawElements (STRIPS)",
889 COMPILED|DRAW_ARRAYS|STRIPS);
Keith Whitwell44c73931999-09-03 14:56:40 +0000890 glutAddMenuEntry("Compiled ArrayElement (TRIANGLES)",
891 COMPILED|ARRAY_ELT|TRIANGLES);
892 glutAddMenuEntry("Compiled ArrayElement (STRIPS)",
jtgafb833d1999-08-19 00:55:39 +0000893 COMPILED|ARRAY_ELT|STRIPS);
894 glutAddMenuEntry("", 0);
895 }
896 glutAddMenuEntry("Quit", QUIT);
897 glutAttachMenu(GLUT_RIGHT_BUTTON);
898
899 glutReshapeFunc(Reshape);
900 glutKeyboardFunc(Key);
901 glutSpecialFunc(SpecialKey);
902 glutDisplayFunc(Display);
903 glutMainLoop();
904 return 0;
905}