Quiet compiler warnings.
[mesa.git] / progs / demos / isosurf.c
1 /* $Id: isosurf.c,v 1.15 2002/10/18 17:47:35 kschultz Exp $ */
2
3 /*
4 * Display an isosurface of 3-D wind speed volume.
5 *
6 * Command line options:
7 * -info print GL implementation information
8 *
9 * Brian Paul This file in public domain.
10 */
11
12
13 /* Keys:
14 * =====
15 *
16 * - Arrow keys to rotate
17 * - 's' toggles smooth shading
18 * - 'l' toggles lighting
19 * - 'f' toggles fog
20 * - 'I' and 'i' zoom in and out
21 * - 'c' toggles a user clip plane
22 * - 'm' toggles colorful materials in GL_TRIANGLES modes.
23 * - '+' and '-' move the user clip plane
24 *
25 * Other options are available via the popup menu.
26 */
27
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <math.h>
33 #ifdef _WIN32
34 #include <windows.h>
35 #undef CLIP_MASK
36 #endif
37 #define GL_GLEXT_LEGACY
38 #include "GL/glut.h"
39
40 #include "readtex.c" /* I know, this is a hack. KW: me too. */
41 #define TEXTURE_FILE "../images/reflect.rgb"
42
43 #define LIT 0x00000001
44 #define UNLIT 0x00000002
45 #define REFLECT 0x00000004
46 #define POINT_FILTER 0x00000008
47 #define LINEAR_FILTER 0x00000010
48 #define GLVERTEX 0x00000020
49 #define DRAW_ELTS 0x00000040
50 #define DRAW_ARRAYS 0x00000080
51 #define ARRAY_ELT 0x00000100
52 #define LOCKED 0x00000200
53 #define UNLOCKED 0x00000400
54 #define IMMEDIATE 0x00000800
55 #define DISPLAYLIST 0x00001000
56 #define SHADE_SMOOTH 0x00002000
57 #define SHADE_FLAT 0x00004000
58 #define TRIANGLES 0x00008000
59 #define STRIPS 0x00010000
60 #define POINTS 0x00020000
61 #define USER_CLIP 0x00040000
62 #define NO_USER_CLIP 0x00080000
63 #define MATERIALS 0x00100000
64 #define NO_MATERIALS 0x00200000
65 #define FOG 0x00400000
66 #define NO_FOG 0x00800000
67 #define QUIT 0x01000000
68 #define GLINFO 0x02000000
69 #define STIPPLE 0x04000000
70 #define NO_STIPPLE 0x08000000
71 #define POLYGON_FILL 0x10000000
72 #define POLYGON_LINE 0x20000000
73
74 #define LIGHT_MASK (LIT|UNLIT|REFLECT)
75 #define FILTER_MASK (POINT_FILTER|LINEAR_FILTER)
76 #define RENDER_STYLE_MASK (GLVERTEX|DRAW_ARRAYS|DRAW_ELTS|ARRAY_ELT)
77 #define DLIST_MASK (IMMEDIATE|DISPLAYLIST)
78 #define LOCK_MASK (LOCKED|UNLOCKED)
79 #define MATERIAL_MASK (MATERIALS|NO_MATERIALS)
80 #define PRIMITIVE_MASK (TRIANGLES|STRIPS|POINTS)
81 #define CLIP_MASK (USER_CLIP|NO_USER_CLIP)
82 #define SHADE_MASK (SHADE_SMOOTH|SHADE_FLAT)
83 #define FOG_MASK (FOG|NO_FOG)
84 #define STIPPLE_MASK (STIPPLE|NO_STIPPLE)
85 #define POLYGON_MASK (POLYGON_FILL|POLYGON_LINE)
86
87 #define MAXVERTS 10000
88 static GLint maxverts = MAXVERTS;
89 static float data[MAXVERTS][6];
90 static float compressed_data[MAXVERTS][6];
91 static float expanded_data[MAXVERTS*3][6];
92 static GLuint indices[MAXVERTS];
93 static GLuint tri_indices[MAXVERTS*3];
94 static GLuint strip_indices[MAXVERTS];
95 static GLfloat col[100][4];
96 static GLint numverts, num_tri_verts, numuniq;
97
98 static GLfloat xrot;
99 static GLfloat yrot;
100 static GLfloat dist;
101 static GLint state, allowed = ~0;
102 static GLboolean doubleBuffer = GL_TRUE;
103 static GLdouble plane[4];
104 static GLuint surf1, dlist_state;
105
106 static GLboolean PrintInfo = GL_FALSE;
107
108
109 static GLubyte halftone[] = {
110 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA,
111 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
112 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA,
113 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
114 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA,
115 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
116 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA,
117 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
118 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA,
119 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
120 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55};
121
122
123 static void read_surface( char *filename )
124 {
125 FILE *f;
126
127 f = fopen(filename,"r");
128 if (!f) {
129 printf("couldn't read %s\n", filename);
130 exit(1);
131 }
132
133 numverts = 0;
134 while (!feof(f) && numverts<maxverts) {
135 fscanf( f, "%f %f %f %f %f %f",
136 &data[numverts][0], &data[numverts][1], &data[numverts][2],
137 &data[numverts][3], &data[numverts][4], &data[numverts][5] );
138 numverts++;
139 }
140 numverts--;
141
142 printf("%d vertices, %d triangles\n", numverts, numverts-2);
143 fclose(f);
144 }
145
146
147
148 static void print_flags( const char *msg, GLuint flags )
149 {
150 fprintf(stderr,
151 "%s (0x%x): %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
152 msg, flags,
153 (flags & GLVERTEX) ? "glVertex, " : "",
154 (flags & DRAW_ARRAYS) ? "glDrawArrays, " : "",
155 (flags & DRAW_ELTS) ? "glDrawElements, " : "",
156 (flags & ARRAY_ELT) ? "glArrayElement, " : "",
157 (flags & LOCKED) ? "locked arrays, " : "",
158 (flags & TRIANGLES) ? "GL_TRIANGLES, " : "",
159 (flags & STRIPS) ? "GL_TRIANGLE_STRIP, " : "",
160 (flags & POINTS) ? "GL_POINTS, " : "",
161 (flags & DISPLAYLIST) ? "as a displaylist, " : "",
162 (flags & LIT) ? "lit, " : "",
163 (flags & UNLIT) ? "unlit, " : "",
164 (flags & REFLECT) ? "reflect, " : "",
165 (flags & SHADE_FLAT) ? "flat-shaded, " : "",
166 (flags & USER_CLIP) ? "user_clip, " : "",
167 (flags & MATERIALS) ? "materials, " : "",
168 (flags & FOG) ? "fog, " : "",
169 (flags & STIPPLE) ? "stipple, " : "",
170 (flags & POLYGON_LINE) ? "polygon mode line, " : "");
171 }
172
173
174
175 struct data_idx {
176 float *data;
177 int idx;
178 int uniq_idx;
179 };
180
181
182 #define COMPARE_FUNC( AXIS ) \
183 static int compare_axis_##AXIS( const void *a, const void *b ) \
184 { \
185 float t = ( (*(struct data_idx *)a).data[AXIS] - \
186 (*(struct data_idx *)b).data[AXIS] ); \
187 \
188 if (t < 0) return -1; \
189 if (t > 0) return 1; \
190 return 0; \
191 }
192
193 COMPARE_FUNC(0)
194 COMPARE_FUNC(1)
195 COMPARE_FUNC(2)
196 COMPARE_FUNC(3)
197 COMPARE_FUNC(4)
198 COMPARE_FUNC(5)
199 COMPARE_FUNC(6)
200
201 int (*(compare[7]))( const void *a, const void *b ) =
202 {
203 compare_axis_0,
204 compare_axis_1,
205 compare_axis_2,
206 compare_axis_3,
207 compare_axis_4,
208 compare_axis_5,
209 compare_axis_6,
210 };
211
212
213 #define VEC_ELT(f, s, i) (float *)(((char *)f) + s * i)
214
215 static int sort_axis( int axis,
216 int vec_size,
217 int vec_stride,
218 struct data_idx *indices,
219 int start,
220 int finish,
221 float *out,
222 int uniq,
223 const float fudge )
224 {
225 int i;
226
227 if (finish-start > 2)
228 {
229 qsort( indices+start, finish-start, sizeof(*indices), compare[axis] );
230 }
231 else if (indices[start].data[axis] > indices[start+1].data[axis])
232 {
233 struct data_idx tmp = indices[start];
234 indices[start] = indices[start+1];
235 indices[start+1] = tmp;
236 }
237
238 if (axis == vec_size-1) {
239 for (i = start ; i < finish ; ) {
240 float max = indices[i].data[axis] + fudge;
241 float *dest = VEC_ELT(out, vec_stride, uniq);
242 int j;
243
244 for (j = 0 ; j < vec_size ; j++)
245 dest[j] = indices[i].data[j];
246
247 for ( ; i < finish && max >= indices[i].data[axis]; i++)
248 indices[i].uniq_idx = uniq;
249
250 uniq++;
251 }
252 } else {
253 for (i = start ; i < finish ; ) {
254 int j = i + 1;
255 float max = indices[i].data[axis] + fudge;
256 while (j < finish && max >= indices[j].data[axis]) j++;
257 if (j == i+1) {
258 float *dest = VEC_ELT(out, vec_stride, uniq);
259 int k;
260
261 indices[i].uniq_idx = uniq;
262
263 for (k = 0 ; k < vec_size ; k++)
264 dest[k] = indices[i].data[k];
265
266 uniq++;
267 } else {
268 uniq = sort_axis( axis+1, vec_size, vec_stride,
269 indices, i, j, out, uniq, fudge );
270 }
271 i = j;
272 }
273 }
274
275 return uniq;
276 }
277
278
279 static void extract_indices1( const struct data_idx *in, unsigned int *out,
280 int n )
281 {
282 int i;
283 for ( i = 0 ; i < n ; i++ ) {
284 out[in[i].idx] = in[i].uniq_idx;
285 }
286 }
287
288
289 static void compactify_arrays(void)
290 {
291 int i;
292 struct data_idx *ind;
293
294 ind = (struct data_idx *) malloc( sizeof(struct data_idx) * numverts );
295
296 for (i = 0 ; i < numverts ; i++) {
297 ind[i].idx = i;
298 ind[i].data = data[i];
299 }
300
301 numuniq = sort_axis(0,
302 sizeof(compressed_data[0])/sizeof(float),
303 sizeof(compressed_data[0]),
304 ind,
305 0,
306 numverts,
307 (float *)compressed_data,
308 0,
309 1e-6);
310
311 printf("Nr unique vertex/normal pairs: %d\n", numuniq);
312
313 extract_indices1( ind, indices, numverts );
314 free( ind );
315 }
316
317 static void expand_arrays(void)
318 {
319 int i;
320 int parity = 0;
321 for (i = 2 ; i < numverts ; i++, parity ^= 1) {
322 int v0 = i-2+parity;
323 int v1 = i-1-parity;
324 int v2 = i;
325 memcpy( expanded_data[(i-2)*3+0], data[v0], sizeof(data[0]) );
326 memcpy( expanded_data[(i-2)*3+1], data[v1], sizeof(data[0]) );
327 memcpy( expanded_data[(i-2)*3+2], data[v2], sizeof(data[0]) );
328 }
329 }
330
331 static float myrand( float max )
332 {
333 return max*rand()/(RAND_MAX+1.0);
334 }
335
336
337 static void make_tri_indices( void )
338 {
339 unsigned int *v = tri_indices;
340 unsigned int parity = 0;
341 int i, j;
342
343 for (j=2;j<numverts;j++,parity^=1) {
344 if (parity) {
345 *v++ = indices[j-1];
346 *v++ = indices[j-2];
347 *v++ = indices[j];
348 } else {
349 *v++ = indices[j-2];
350 *v++ = indices[j-1];
351 *v++ = indices[j];
352 }
353 }
354
355 num_tri_verts = v - tri_indices;
356 printf("num_tri_verts: %d\n", num_tri_verts);
357
358 for (i = j = 0 ; i < num_tri_verts ; i += 600, j++) {
359 col[j][3] = 1;
360 col[j][2] = myrand(1);
361 col[j][1] = myrand(1);
362 col[j][0] = myrand(1);
363 }
364
365 for (i = 0; i < numverts ; i++)
366 strip_indices[i] = i;
367 }
368
369 #define MIN(x,y) (x < y) ? x : y
370
371 static void draw_surface( unsigned int with_state )
372 {
373 GLint i, j;
374
375 if (with_state & DISPLAYLIST) {
376 if ((with_state & (RENDER_STYLE_MASK|PRIMITIVE_MASK|MATERIAL_MASK)) !=
377 dlist_state) {
378 /*
379 */
380 fprintf(stderr, "rebuilding displaylist\n");
381
382 if (dlist_state)
383 glDeleteLists( surf1, 1 );
384
385 dlist_state = with_state & (RENDER_STYLE_MASK|PRIMITIVE_MASK|
386 MATERIAL_MASK);
387 surf1 = glGenLists(1);
388 glNewList(surf1, GL_COMPILE);
389 draw_surface( dlist_state );
390 glEndList();
391 }
392
393 glCallList( surf1 );
394 return;
395 }
396
397 switch (with_state & (RENDER_STYLE_MASK|PRIMITIVE_MASK)) {
398 #ifdef GL_EXT_vertex_array
399
400 case (DRAW_ELTS|TRIANGLES):
401 if (with_state & MATERIALS) {
402 for (j = i = 0 ; i < num_tri_verts ; i += 600, j++) {
403 GLuint nr = MIN(num_tri_verts-i, 600);
404 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col[j]);
405 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col[j]);
406 glDrawElements( GL_TRIANGLES, nr, GL_UNSIGNED_INT, tri_indices+i );
407 }
408 } else {
409 glDrawElements( GL_TRIANGLES, num_tri_verts, GL_UNSIGNED_INT,
410 tri_indices );
411 }
412 break;
413
414 case (DRAW_ARRAYS|TRIANGLES):
415 glDrawArraysEXT( GL_TRIANGLES, 0, (numverts-2)*3 );
416 break;
417
418 case (ARRAY_ELT|TRIANGLES):
419 if (with_state & MATERIALS) {
420 for (j = i = 0 ; i < num_tri_verts ; i += 600, j++) {
421 GLuint nr = MIN(num_tri_verts-i, 600);
422 GLuint k;
423 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col[j]);
424 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col[j]);
425 glBegin( GL_TRIANGLES );
426 for (k = 0 ; k < nr ; k++)
427 glArrayElement( tri_indices[i+k] );
428 glEnd();
429 }
430 } else {
431 glBegin( GL_TRIANGLES );
432 for (i = 0 ; i < num_tri_verts ; i++)
433 glArrayElement( tri_indices[i] );
434
435 glEnd();
436 }
437 break;
438
439
440 /* Uses the original arrays (including duplicate elements):
441 */
442 case (DRAW_ARRAYS|STRIPS):
443 glDrawArraysEXT( GL_TRIANGLE_STRIP, 0, numverts );
444 break;
445 case (DRAW_ELTS|STRIPS):
446 glDrawElements( GL_TRIANGLE_STRIP, numverts,
447 GL_UNSIGNED_INT, strip_indices );
448 break;
449
450 /* Uses the original arrays (including duplicate elements):
451 */
452 case (ARRAY_ELT|STRIPS):
453 glBegin( GL_TRIANGLE_STRIP );
454 for (i = 0 ; i < numverts ; i++)
455 glArrayElement( i );
456 glEnd();
457 break;
458
459 case (DRAW_ARRAYS|POINTS):
460 glDrawArraysEXT( GL_POINTS, 0, numuniq );
461 break;
462 case (DRAW_ELTS|POINTS):
463 /* can use numuniq with strip_indices as strip_indices[i] == i.
464 */
465 glDrawElements( GL_POINTS, numuniq,
466 GL_UNSIGNED_INT, strip_indices );
467 break;
468 case (ARRAY_ELT|POINTS):
469 /* just emit each unique element once:
470 */
471 glBegin( GL_POINTS );
472 for (i = 0 ; i < numuniq ; i++)
473 glArrayElement( i );
474 glEnd();
475 break;
476 #endif
477
478 case (GLVERTEX|TRIANGLES):
479 if (with_state & MATERIALS) {
480 for (j = i = 0 ; i < num_tri_verts ; i += 600, j++) {
481 GLuint nr = MIN(num_tri_verts-i, 600);
482 GLuint k;
483 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col[j]);
484 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col[j]);
485 glBegin( GL_TRIANGLES );
486 for (k = 0 ; k < nr ; k++) {
487 glNormal3fv( &compressed_data[tri_indices[i+k]][3] );
488 glVertex3fv( &compressed_data[tri_indices[i+k]][0] );
489 }
490 glEnd();
491 }
492 } else {
493 glBegin( GL_TRIANGLES );
494 for (i = 0 ; i < num_tri_verts ; i++) {
495 glNormal3fv( &compressed_data[tri_indices[i]][3] );
496 glVertex3fv( &compressed_data[tri_indices[i]][0] );
497 }
498 glEnd();
499 }
500 break;
501
502 case (GLVERTEX|POINTS):
503 /* Renders all points, but not in strip order... Shouldn't be a
504 * problem, but people may be confused as to why points are so
505 * much faster in this demo... And why cva doesn't help them...
506 */
507 glBegin( GL_POINTS );
508 for ( i = 0 ; i < numuniq ; i++ ) {
509 glNormal3fv( &compressed_data[i][3] );
510 glVertex3fv( &compressed_data[i][0] );
511 }
512 glEnd();
513 break;
514
515 case (GLVERTEX|STRIPS):
516 glBegin( GL_TRIANGLE_STRIP );
517 for (i=0;i<numverts;i++) {
518 glNormal3fv( &data[i][3] );
519 glVertex3fv( &data[i][0] );
520 }
521 glEnd();
522 break;
523
524 default:
525 fprintf(stderr, "unimplemented mode %x...\n",
526 (with_state & (RENDER_STYLE_MASK|PRIMITIVE_MASK)));
527 break;
528 }
529 }
530
531
532
533 static void Display(void)
534 {
535 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
536 draw_surface( state );
537 glFlush();
538 if (doubleBuffer) glutSwapBuffers();
539 }
540
541
542 /* KW: only do this when necessary, so CVA can re-use results.
543 */
544 static void set_matrix( void )
545 {
546 glMatrixMode(GL_MODELVIEW);
547 glLoadIdentity();
548 glTranslatef( 0.0, 0.0, dist );
549 glRotatef( yrot, 0.0, 1.0, 0.0 );
550 glRotatef( xrot, 1.0, 0.0, 0.0 );
551 }
552
553 static void Benchmark( float xdiff, float ydiff )
554 {
555 int startTime, endTime;
556 int draws;
557 double seconds, fps, triPerSecond;
558
559 printf("Benchmarking...\n");
560
561 draws = 0;
562 startTime = glutGet(GLUT_ELAPSED_TIME);
563 xrot = 0.0;
564 do {
565 xrot += xdiff;
566 yrot += ydiff;
567 set_matrix();
568 Display();
569 draws++;
570 endTime = glutGet(GLUT_ELAPSED_TIME);
571 } while (endTime - startTime < 5000); /* 5 seconds */
572
573 /* Results */
574 seconds = (double) (endTime - startTime) / 1000.0;
575 triPerSecond = (numverts - 2) * draws / seconds;
576 fps = draws / seconds;
577 printf("Result: triangles/sec: %g fps: %g\n", triPerSecond, fps);
578 }
579
580
581 static void InitMaterials(void)
582 {
583 static float ambient[] = {0.1, 0.1, 0.1, 1.0};
584 static float diffuse[] = {0.5, 1.0, 1.0, 1.0};
585 static float position0[] = {0.0, 0.0, 20.0, 0.0};
586 static float position1[] = {0.0, 0.0, -20.0, 0.0};
587 static float front_mat_shininess[] = {60.0};
588 static float front_mat_specular[] = {0.2, 0.2, 0.2, 1.0};
589 static float front_mat_diffuse[] = {0.5, 0.28, 0.38, 1.0};
590 /*
591 static float back_mat_shininess[] = {60.0};
592 static float back_mat_specular[] = {0.5, 0.5, 0.2, 1.0};
593 static float back_mat_diffuse[] = {1.0, 1.0, 0.2, 1.0};
594 */
595 static float lmodel_ambient[] = {1.0, 1.0, 1.0, 1.0};
596 static float lmodel_twoside[] = {GL_FALSE};
597
598 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
599 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
600 glLightfv(GL_LIGHT0, GL_POSITION, position0);
601 glEnable(GL_LIGHT0);
602
603 glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
604 glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
605 glLightfv(GL_LIGHT1, GL_POSITION, position1);
606 glEnable(GL_LIGHT1);
607
608 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
609 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
610
611 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_mat_shininess);
612 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_mat_specular);
613 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, front_mat_diffuse);
614
615 glPolygonStipple (halftone);
616 }
617
618
619
620 #define UPDATE(o,n,mask) (o&=~mask, o|=n&mask)
621 #define CHANGED(o,n,mask) ((n&mask) && (n&mask) != (o&mask) )
622
623 static void ModeMenu(int m)
624 {
625 m &= allowed;
626
627 if (!m) return;
628
629 if (m==QUIT)
630 exit(0);
631
632 if (m==GLINFO) {
633 printf("GL_VERSION: %s\n", (char *) glGetString(GL_VERSION));
634 printf("GL_EXTENSIONS: %s\n", (char *) glGetString(GL_EXTENSIONS));
635 printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER));
636 return;
637 }
638
639 if (CHANGED(state, m, FILTER_MASK)) {
640 UPDATE(state, m, FILTER_MASK);
641 if (m & LINEAR_FILTER) {
642 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
643 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
644 } else {
645 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
646 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
647 }
648 }
649
650 if (CHANGED(state, m, LIGHT_MASK)) {
651 UPDATE(state, m, LIGHT_MASK);
652 if (m & LIT) {
653 glEnable(GL_LIGHTING);
654 glDisable(GL_TEXTURE_GEN_S);
655 glDisable(GL_TEXTURE_GEN_T);
656 glDisable(GL_TEXTURE_2D);
657 }
658 else if (m & UNLIT) {
659 glDisable(GL_LIGHTING);
660 glDisable(GL_TEXTURE_GEN_S);
661 glDisable(GL_TEXTURE_GEN_T);
662 glDisable(GL_TEXTURE_2D);
663 }
664 else if (m & REFLECT) {
665 glDisable(GL_LIGHTING);
666 glEnable(GL_TEXTURE_GEN_S);
667 glEnable(GL_TEXTURE_GEN_T);
668 glEnable(GL_TEXTURE_2D);
669 }
670 }
671
672 if (CHANGED(state, m, SHADE_MASK)) {
673 UPDATE(state, m, SHADE_MASK);
674 if (m & SHADE_SMOOTH)
675 glShadeModel(GL_SMOOTH);
676 else
677 glShadeModel(GL_FLAT);
678 }
679
680
681 if (CHANGED(state, m, CLIP_MASK)) {
682 UPDATE(state, m, CLIP_MASK);
683 if (m & USER_CLIP) {
684 glEnable(GL_CLIP_PLANE0);
685 } else {
686 glDisable(GL_CLIP_PLANE0);
687 }
688 }
689
690 if (CHANGED(state, m, FOG_MASK)) {
691 UPDATE(state, m, FOG_MASK);
692 if (m & FOG) {
693 glEnable(GL_FOG);
694 }
695 else {
696 glDisable(GL_FOG);
697 }
698 }
699
700 if (CHANGED(state, m, STIPPLE_MASK)) {
701 UPDATE(state, m, STIPPLE_MASK);
702 if (m & STIPPLE) {
703 glEnable(GL_POLYGON_STIPPLE);
704 }
705 else {
706 glDisable(GL_POLYGON_STIPPLE);
707 }
708 }
709
710 if (CHANGED(state, m, POLYGON_MASK)) {
711 UPDATE(state, m, POLYGON_MASK);
712 if (m & POLYGON_FILL) {
713 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
714 }
715 else {
716 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
717 }
718 }
719
720 #ifdef GL_EXT_vertex_array
721 if (CHANGED(state, m, (LOCK_MASK|RENDER_STYLE_MASK|PRIMITIVE_MASK)))
722 {
723 if (m & (PRIMITIVE_MASK)) {
724 UPDATE(state, m, (PRIMITIVE_MASK));
725 }
726
727 if (m & (RENDER_STYLE_MASK)) {
728 UPDATE(state, m, (RENDER_STYLE_MASK));
729 }
730
731 if (m & LOCK_MASK) {
732 UPDATE(state, m, (LOCK_MASK));
733 }
734
735
736 print_flags("primitive", state & PRIMITIVE_MASK);
737 print_flags("render style", state & RENDER_STYLE_MASK);
738
739 if ((state & PRIMITIVE_MASK) != STRIPS &&
740 ((state & RENDER_STYLE_MASK) == DRAW_ELTS ||
741 (state & RENDER_STYLE_MASK) == ARRAY_ELT ||
742 (state & PRIMITIVE_MASK) == POINTS))
743 {
744 fprintf(stderr, "enabling small arrays\n");
745 /* Rendering any primitive with draw-element/array-element
746 * --> Can't do strips here as ordering has been lost in
747 * compaction process...
748 */
749 glVertexPointerEXT( 3, GL_FLOAT, sizeof(data[0]), numuniq,
750 compressed_data );
751 glNormalPointerEXT( GL_FLOAT, sizeof(data[0]), numuniq,
752 &compressed_data[0][3]);
753 #ifdef GL_EXT_compiled_vertex_array
754 if (allowed & LOCKED) {
755 if (state & LOCKED) {
756 glLockArraysEXT( 0, numuniq );
757 } else {
758 glUnlockArraysEXT();
759 }
760 }
761 #endif
762 }
763 else if ((state & PRIMITIVE_MASK) == TRIANGLES &&
764 (state & RENDER_STYLE_MASK) == DRAW_ARRAYS) {
765 fprintf(stderr, "enabling big arrays\n");
766 /* Only get here for TRIANGLES and drawarrays
767 */
768 glVertexPointerEXT( 3, GL_FLOAT, sizeof(data[0]), (numverts-2) * 3,
769 expanded_data );
770 glNormalPointerEXT( GL_FLOAT, sizeof(data[0]), (numverts-2) * 3,
771 &expanded_data[0][3]);
772
773 #ifdef GL_EXT_compiled_vertex_array
774 if (allowed & LOCKED) {
775 if (state & LOCKED) {
776 glLockArraysEXT( 0, (numverts-2)*3 );
777 } else {
778 glUnlockArraysEXT();
779 }
780 }
781 #endif
782 }
783 else {
784 fprintf(stderr, "enabling normal arrays\n");
785 glVertexPointerEXT( 3, GL_FLOAT, sizeof(data[0]), numverts, data );
786 glNormalPointerEXT( GL_FLOAT, sizeof(data[0]), numverts, &data[0][3]);
787 #ifdef GL_EXT_compiled_vertex_array
788 if (allowed & LOCKED) {
789 if (state & LOCKED) {
790 glLockArraysEXT( 0, numverts );
791 } else {
792 glUnlockArraysEXT();
793 }
794 }
795 #endif
796 }
797
798 }
799 #endif
800
801
802 if (m & DLIST_MASK) {
803 UPDATE(state, m, DLIST_MASK);
804 }
805
806 if (m & MATERIAL_MASK) {
807 UPDATE(state, m, MATERIAL_MASK);
808 }
809
810 print_flags("new flags", state);
811
812 glutPostRedisplay();
813 }
814
815
816
817 static void Init(int argc, char *argv[])
818 {
819 GLfloat fogColor[4] = {0.5,1.0,0.5,1.0};
820
821 xrot = 0;
822 yrot = 0;
823 dist = -6;
824 plane[0] = 1.0;
825 plane[1] = 0.0;
826 plane[2] = -1.0;
827 plane[3] = 0.0;
828
829 glClearColor(0.0, 0.0, 1.0, 0.0);
830 glEnable( GL_DEPTH_TEST );
831 glEnable( GL_VERTEX_ARRAY_EXT );
832 glEnable( GL_NORMAL_ARRAY_EXT );
833
834 glMatrixMode(GL_PROJECTION);
835 glLoadIdentity();
836 glFrustum( -1.0, 1.0, -1.0, 1.0, 5, 25 );
837
838 glMatrixMode(GL_MODELVIEW);
839 glLoadIdentity();
840 glClipPlane(GL_CLIP_PLANE0, plane);
841
842 InitMaterials();
843
844 set_matrix();
845
846 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
847 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
848
849 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
850 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
851
852
853 /* Green fog is easy to see */
854 glFogi(GL_FOG_MODE,GL_EXP2);
855 glFogfv(GL_FOG_COLOR,fogColor);
856 glFogf(GL_FOG_DENSITY,0.15);
857 glHint(GL_FOG_HINT,GL_DONT_CARE);
858
859 {
860 static int firsttime = 1;
861 if (firsttime) {
862 firsttime = 0;
863 compactify_arrays();
864 expand_arrays();
865 make_tri_indices();
866
867 if (!LoadRGBMipmaps(TEXTURE_FILE, GL_RGB)) {
868 printf("Error: couldn't load texture image\n");
869 exit(1);
870 }
871 }
872 }
873
874 ModeMenu(SHADE_SMOOTH|
875 LIT|
876 POINT_FILTER|
877 NO_USER_CLIP|
878 NO_MATERIALS|
879 NO_FOG|
880 NO_STIPPLE|
881 IMMEDIATE|
882 STRIPS|
883 UNLOCKED|
884 GLVERTEX);
885
886 if (PrintInfo) {
887 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
888 printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
889 printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
890 printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
891 }
892 }
893
894
895
896 static void Reshape(int width, int height)
897 {
898 glViewport(0, 0, (GLint)width, (GLint)height);
899 }
900
901
902
903 static void Key( unsigned char key, int x, int y )
904 {
905 (void) x;
906 (void) y;
907 switch (key) {
908 case 27:
909 exit(0);
910 case 'f':
911 ModeMenu((state ^ FOG_MASK) & FOG_MASK);
912 break;
913 case 's':
914 ModeMenu((state ^ SHADE_MASK) & SHADE_MASK);
915 break;
916 case 't':
917 ModeMenu((state ^ STIPPLE_MASK) & STIPPLE_MASK);
918 break;
919 case 'l':
920 ModeMenu((state ^ LIGHT_MASK) & (LIT|UNLIT));
921 break;
922 case 'm':
923 ModeMenu((state ^ MATERIAL_MASK) & MATERIAL_MASK);
924 break;
925 case 'c':
926 ModeMenu((state ^ CLIP_MASK) & CLIP_MASK);
927 break;
928 case 'v':
929 ModeMenu((LOCKED|IMMEDIATE|DRAW_ELTS|TRIANGLES) & allowed);
930 break;
931 case 'V':
932 ModeMenu(UNLOCKED|IMMEDIATE|GLVERTEX|STRIPS);
933 break;
934 case 'b':
935 Benchmark(5.0, 0);
936 break;
937 case 'B':
938 Benchmark(0, 5.0);
939 break;
940 case 'i':
941 dist += .25;
942 set_matrix();
943 glutPostRedisplay();
944 break;
945 case 'I':
946 dist -= .25;
947 set_matrix();
948 glutPostRedisplay();
949 break;
950 case '-':
951 case '_':
952 plane[3] += 2.0;
953 glMatrixMode(GL_MODELVIEW);
954 glLoadIdentity();
955 glClipPlane(GL_CLIP_PLANE0, plane);
956 set_matrix();
957 glutPostRedisplay();
958 break;
959 case '+':
960 case '=':
961 plane[3] -= 2.0;
962 glMatrixMode(GL_MODELVIEW);
963 glLoadIdentity();
964 glClipPlane(GL_CLIP_PLANE0, plane);
965 set_matrix();
966 glutPostRedisplay();
967 break;
968 case ' ':
969 Init(0,0);
970 break;
971 }
972 }
973
974
975 static void SpecialKey( int key, int x, int y )
976 {
977 (void) x;
978 (void) y;
979 switch (key) {
980 case GLUT_KEY_LEFT:
981 yrot -= 15.0;
982 break;
983 case GLUT_KEY_RIGHT:
984 yrot += 15.0;
985 break;
986 case GLUT_KEY_UP:
987 xrot += 15.0;
988 break;
989 case GLUT_KEY_DOWN:
990 xrot -= 15.0;
991 break;
992 default:
993 return;
994 }
995 set_matrix();
996 glutPostRedisplay();
997 }
998
999
1000
1001 static GLint Args(int argc, char **argv)
1002 {
1003 GLint i;
1004 GLint mode = 0;
1005
1006 for (i = 1; i < argc; i++) {
1007 if (strcmp(argv[i], "-sb") == 0) {
1008 doubleBuffer = GL_FALSE;
1009 }
1010 else if (strcmp(argv[i], "-db") == 0) {
1011 doubleBuffer = GL_TRUE;
1012 }
1013 else if (strcmp(argv[i], "-info") == 0) {
1014 PrintInfo = GL_TRUE;
1015 }
1016 else if (strcmp(argv[i], "-10") == 0) {
1017 maxverts = 10;
1018 }
1019 else if (strcmp(argv[i], "-100") == 0) {
1020 maxverts = 100;
1021 }
1022 else if (strcmp(argv[i], "-1000") == 0) {
1023 maxverts = 1000;
1024 }
1025 else {
1026 printf("%s (Bad option).\n", argv[i]);
1027 return QUIT;
1028 }
1029 }
1030
1031 return mode;
1032 }
1033
1034 int main(int argc, char **argv)
1035 {
1036 GLenum type;
1037 char *extensions;
1038
1039 GLuint arg_mode = Args(argc, argv);
1040
1041 if (arg_mode & QUIT)
1042 exit(0);
1043
1044 read_surface( "isosurf.dat" );
1045
1046 glutInitWindowPosition(0, 0);
1047 glutInitWindowSize(400, 400);
1048
1049 type = GLUT_DEPTH;
1050 type |= GLUT_RGB;
1051 type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
1052 glutInitDisplayMode(type);
1053
1054 if (glutCreateWindow("Isosurface") <= 0) {
1055 exit(0);
1056 }
1057
1058 /* Make sure server supports the vertex array extension */
1059 extensions = (char *) glGetString( GL_EXTENSIONS );
1060
1061 if (!strstr( extensions, "GL_EXT_vertex_array" ))
1062 {
1063 printf("Vertex arrays not supported by this renderer\n");
1064 allowed &= ~(LOCKED|DRAW_ARRAYS|DRAW_ELTS|ARRAY_ELT);
1065 }
1066 else if (!strstr( extensions, "GL_EXT_compiled_vertex_array" ))
1067 {
1068 printf("Compiled vertex arrays not supported by this renderer\n");
1069 allowed &= ~LOCKED;
1070 }
1071
1072 Init(argc, argv);
1073 ModeMenu(arg_mode);
1074
1075 glutCreateMenu(ModeMenu);
1076 glutAddMenuEntry("GL info", GLINFO);
1077 glutAddMenuEntry("", 0);
1078 glutAddMenuEntry("Lit", LIT);
1079 glutAddMenuEntry("Unlit", UNLIT);
1080 glutAddMenuEntry("Reflect", REFLECT);
1081 glutAddMenuEntry("", 0);
1082 glutAddMenuEntry("Smooth", SHADE_SMOOTH);
1083 glutAddMenuEntry("Flat", SHADE_FLAT);
1084 glutAddMenuEntry("", 0);
1085 glutAddMenuEntry("Fog", FOG);
1086 glutAddMenuEntry("No Fog", NO_FOG);
1087 glutAddMenuEntry("", 0);
1088 glutAddMenuEntry("Stipple", STIPPLE);
1089 glutAddMenuEntry("No Stipple", NO_STIPPLE);
1090 glutAddMenuEntry("", 0);
1091 glutAddMenuEntry("Polygon Mode Fill", POLYGON_FILL);
1092 glutAddMenuEntry("Polygon Mode Line", POLYGON_LINE);
1093 glutAddMenuEntry("", 0);
1094 glutAddMenuEntry("Point Filtered", POINT_FILTER);
1095 glutAddMenuEntry("Linear Filtered", LINEAR_FILTER);
1096 glutAddMenuEntry("", 0);
1097 glutAddMenuEntry("GL_TRIANGLES", TRIANGLES);
1098 glutAddMenuEntry("GL_TRIANGLE_STRIPS", STRIPS);
1099 glutAddMenuEntry("GL_POINTS", POINTS);
1100 glutAddMenuEntry("", 0);
1101 glutAddMenuEntry("Displaylist", DISPLAYLIST);
1102 glutAddMenuEntry("Immediate", IMMEDIATE);
1103 glutAddMenuEntry("", 0);
1104 if (allowed & LOCKED) {
1105 glutAddMenuEntry("Locked Arrays (CVA)", LOCKED);
1106 glutAddMenuEntry("Unlocked Arrays", UNLOCKED);
1107 glutAddMenuEntry("", 0);
1108 }
1109 glutAddMenuEntry("glVertex", GLVERTEX);
1110 if (allowed & DRAW_ARRAYS) {
1111 glutAddMenuEntry("glDrawElements", DRAW_ELTS);
1112 glutAddMenuEntry("glDrawArrays", DRAW_ARRAYS);
1113 glutAddMenuEntry("glArrayElement", ARRAY_ELT);
1114 }
1115 glutAddMenuEntry("", 0);
1116 glutAddMenuEntry("Quit", QUIT);
1117 glutAttachMenu(GLUT_RIGHT_BUTTON);
1118
1119 glutReshapeFunc(Reshape);
1120 glutKeyboardFunc(Key);
1121 glutSpecialFunc(SpecialKey);
1122 glutDisplayFunc(Display);
1123
1124 glutMainLoop();
1125 return 0;
1126 }