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