brighter colors
[mesa.git] / progs / demos / isosurf.c
1 /* $Id: isosurf.c,v 1.6 2000/06/27 17:04:43 brianp 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 #define GL_GLEXT_LEGACY
34 #include "GL/glut.h"
35
36 #include "../util/readtex.c" /* I know, this is a hack. KW: me too. */
37 #define TEXTURE_FILE "../images/reflect.rgb"
38
39 #define LIT 0x1
40 #define UNLIT 0x2
41 #define TEXTURE 0x4
42 #define NO_TEXTURE 0x8
43 #define REFLECT 0x10
44 #define NO_REFLECT 0x20
45 #define POINT_FILTER 0x40
46 #define LINEAR_FILTER 0x80
47 #define GLVERTEX 0x100
48 #define DRAW_ARRAYS 0x200 /* or draw_elts, if compiled */
49 #define ARRAY_ELT 0x400
50 #define COMPILED 0x800
51 #define IMMEDIATE 0x1000
52 #define SHADE_SMOOTH 0x2000
53 #define SHADE_FLAT 0x4000
54 #define TRIANGLES 0x8000
55 #define STRIPS 0x10000
56 #define USER_CLIP 0x20000
57 #define NO_USER_CLIP 0x40000
58 #define MATERIALS 0x80000
59 #define NO_MATERIALS 0x100000
60 #define FOG 0x200000
61 #define NO_FOG 0x400000
62 #define QUIT 0x800000
63 #define DISPLAYLIST 0x1000000
64 #define GLINFO 0x2000000
65 #define STIPPLE 0x4000000
66 #define NO_STIPPLE 0x8000000
67
68 #define LIGHT_MASK (LIT|UNLIT)
69 #define TEXTURE_MASK (TEXTURE|NO_TEXTURE)
70 #define REFLECT_MASK (REFLECT|NO_REFLECT)
71 #define FILTER_MASK (POINT_FILTER|LINEAR_FILTER)
72 #define RENDER_STYLE_MASK (GLVERTEX|DRAW_ARRAYS|ARRAY_ELT)
73 #define COMPILED_MASK (COMPILED|IMMEDIATE|DISPLAYLIST)
74 #define MATERIAL_MASK (MATERIALS|NO_MATERIALS)
75 #define PRIMITIVE_MASK (TRIANGLES|STRIPS)
76 #define CLIP_MASK (USER_CLIP|NO_USER_CLIP)
77 #define SHADE_MASK (SHADE_SMOOTH|SHADE_FLAT)
78 #define FOG_MASK (FOG|NO_FOG)
79 #define STIPPLE_MASK (STIPPLE|NO_STIPPLE)
80
81 #define MAXVERTS 10000
82 static float data[MAXVERTS][6];
83 static float compressed_data[MAXVERTS][6];
84 static GLuint indices[MAXVERTS];
85 static GLuint tri_indices[MAXVERTS*3];
86 static GLfloat col[100][4];
87 static GLint numverts, num_tri_verts, numuniq;
88
89 static GLfloat xrot;
90 static GLfloat yrot;
91 static GLfloat dist = -6;
92 static GLint state, allowed = ~0;
93 static GLboolean doubleBuffer = GL_TRUE;
94 static GLdouble plane[4] = {1.0, 0.0, -1.0, 0.0};
95 static GLuint surf1;
96
97 static GLboolean PrintInfo = GL_FALSE;
98
99
100 static GLubyte halftone[] = {
101 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA,
102 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
103 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA,
104 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
105 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA,
106 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
107 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA,
108 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
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};
112
113 /* forward decl */
114 int BuildList( int mode );
115
116
117 static void read_surface( char *filename )
118 {
119 FILE *f;
120
121 f = fopen(filename,"r");
122 if (!f) {
123 printf("couldn't read %s\n", filename);
124 exit(1);
125 }
126
127 numverts = 0;
128 while (!feof(f) && numverts<MAXVERTS) {
129 fscanf( f, "%f %f %f %f %f %f",
130 &data[numverts][0], &data[numverts][1], &data[numverts][2],
131 &data[numverts][3], &data[numverts][4], &data[numverts][5] );
132 numverts++;
133 }
134 numverts--;
135
136 printf("%d vertices, %d triangles\n", numverts, numverts-2);
137 fclose(f);
138 }
139
140
141
142
143 struct data_idx {
144 float *data;
145 int idx;
146 int uniq_idx;
147 };
148
149
150 #define COMPARE_FUNC( AXIS ) \
151 static int compare_axis_##AXIS( const void *a, const void *b ) \
152 { \
153 float t = ( (*(struct data_idx *)a).data[AXIS] - \
154 (*(struct data_idx *)b).data[AXIS] ); \
155 \
156 if (t < 0) return -1; \
157 if (t > 0) return 1; \
158 return 0; \
159 }
160
161 COMPARE_FUNC(0)
162 COMPARE_FUNC(1)
163 COMPARE_FUNC(2)
164 COMPARE_FUNC(3)
165 COMPARE_FUNC(4)
166 COMPARE_FUNC(5)
167 COMPARE_FUNC(6)
168
169 int (*(compare[7]))( const void *a, const void *b ) =
170 {
171 compare_axis_0,
172 compare_axis_1,
173 compare_axis_2,
174 compare_axis_3,
175 compare_axis_4,
176 compare_axis_5,
177 compare_axis_6,
178 };
179
180
181 #define VEC_ELT(f, s, i) (float *)(((char *)f) + s * i)
182
183 static int sort_axis( int axis,
184 int vec_size,
185 int vec_stride,
186 struct data_idx *indices,
187 int start,
188 int finish,
189 float *out,
190 int uniq,
191 const float fudge )
192 {
193 int i;
194
195 if (finish-start > 2)
196 {
197 qsort( indices+start, finish-start, sizeof(*indices), compare[axis] );
198 }
199 else if (indices[start].data[axis] > indices[start+1].data[axis])
200 {
201 struct data_idx tmp = indices[start];
202 indices[start] = indices[start+1];
203 indices[start+1] = tmp;
204 }
205
206 if (axis == vec_size-1) {
207 for (i = start ; i < finish ; ) {
208 float max = indices[i].data[axis] + fudge;
209 float *dest = VEC_ELT(out, vec_stride, uniq);
210 int j;
211
212 for (j = 0 ; j < vec_size ; j++)
213 dest[j] = indices[i].data[j];
214
215 for ( ; i < finish && max >= indices[i].data[axis]; i++)
216 indices[i].uniq_idx = uniq;
217
218 uniq++;
219 }
220 } else {
221 for (i = start ; i < finish ; ) {
222 int j = i + 1;
223 float max = indices[i].data[axis] + fudge;
224 while (j < finish && max >= indices[j].data[axis]) j++;
225 if (j == i+1) {
226 float *dest = VEC_ELT(out, vec_stride, uniq);
227 int k;
228
229 indices[i].uniq_idx = uniq;
230
231 for (k = 0 ; k < vec_size ; k++)
232 dest[k] = indices[i].data[k];
233
234 uniq++;
235 } else {
236 uniq = sort_axis( axis+1, vec_size, vec_stride,
237 indices, i, j, out, uniq, fudge );
238 }
239 i = j;
240 }
241 }
242
243 return uniq;
244 }
245
246
247 static void extract_indices1( const struct data_idx *in, unsigned int *out,
248 int n )
249 {
250 int i;
251 for ( i = 0 ; i < n ; i++ ) {
252 out[in[i].idx] = in[i].uniq_idx;
253 }
254 }
255
256
257 static void compactify_arrays(void)
258 {
259 int i;
260 struct data_idx *ind;
261
262 ind = (struct data_idx *) malloc( sizeof(struct data_idx) * numverts );
263
264 for (i = 0 ; i < numverts ; i++) {
265 ind[i].idx = i;
266 ind[i].data = data[i];
267 }
268
269 numuniq = sort_axis(0,
270 sizeof(compressed_data[0])/sizeof(float),
271 sizeof(compressed_data[0]),
272 ind,
273 0,
274 numverts,
275 (float *)compressed_data,
276 0,
277 1e-6);
278
279 printf("Nr unique vertex/normal pairs: %d\n", numuniq);
280
281 extract_indices1( ind, indices, numverts );
282 free( ind );
283 }
284
285 static float myrand( float max )
286 {
287 return max*rand()/(RAND_MAX+1.0);
288 }
289
290
291 static void make_tri_indices( void )
292 {
293 unsigned int *v = tri_indices;
294 unsigned int parity = 0;
295 unsigned int i, j;
296
297 for (j=2;j<numverts;j++,parity^=1) {
298 if (parity) {
299 *v++ = indices[j-1];
300 *v++ = indices[j-2];
301 *v++ = indices[j];
302 } else {
303 *v++ = indices[j-2];
304 *v++ = indices[j-1];
305 *v++ = indices[j];
306 }
307 }
308
309 num_tri_verts = v - tri_indices;
310 printf("num_tri_verts: %d\n", num_tri_verts);
311
312 for (i = j = 0 ; i < num_tri_verts ; i += 600, j++) {
313 col[j][3] = 1;
314 col[j][2] = myrand(1);
315 col[j][1] = myrand(1);
316 col[j][0] = myrand(1);
317 }
318 }
319
320 #define MIN(x,y) (x < y) ? x : y
321
322 static void draw_surface( int with_state )
323 {
324 GLuint i, j;
325
326 switch (with_state & (COMPILED_MASK|RENDER_STYLE_MASK|PRIMITIVE_MASK)) {
327 #ifdef GL_EXT_vertex_array
328
329 case (COMPILED|DRAW_ARRAYS|STRIPS):
330 glDrawElements( GL_TRIANGLE_STRIP, numverts, GL_UNSIGNED_INT, indices );
331 break;
332
333
334 case (COMPILED|ARRAY_ELT|STRIPS):
335 glBegin( GL_TRIANGLE_STRIP );
336 for (i = 0 ; i < numverts ; i++)
337 glArrayElement( indices[i] );
338 glEnd();
339 break;
340
341 case (COMPILED|DRAW_ARRAYS|TRIANGLES):
342 case (IMMEDIATE|DRAW_ARRAYS|TRIANGLES):
343 if (with_state & MATERIALS) {
344 for (j = i = 0 ; i < num_tri_verts ; i += 600, j++) {
345 GLuint nr = MIN(num_tri_verts-i, 600);
346 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col[j]);
347 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col[j]);
348 glDrawElements( GL_TRIANGLES, nr, GL_UNSIGNED_INT, tri_indices+i );
349 }
350 } else {
351 glDrawElements( GL_TRIANGLES, num_tri_verts, GL_UNSIGNED_INT,
352 tri_indices );
353 }
354
355 break;
356
357 /* Uses the original arrays (including duplicate elements):
358 */
359 case (IMMEDIATE|DRAW_ARRAYS|STRIPS):
360 glDrawArraysEXT( GL_TRIANGLE_STRIP, 0, numverts );
361 break;
362
363 /* Uses the original arrays (including duplicate elements):
364 */
365 case (IMMEDIATE|ARRAY_ELT|STRIPS):
366 glBegin( GL_TRIANGLE_STRIP );
367 for (i = 0 ; i < numverts ; i++)
368 glArrayElement( i );
369 glEnd();
370 break;
371
372 case (IMMEDIATE|ARRAY_ELT|TRIANGLES):
373 case (COMPILED|ARRAY_ELT|TRIANGLES):
374 if (with_state & MATERIALS) {
375 for (j = i = 0 ; i < num_tri_verts ; i += 600, j++) {
376 GLuint nr = MIN(num_tri_verts-i, 600);
377 GLuint k;
378 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col[j]);
379 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col[j]);
380 glBegin( GL_TRIANGLES );
381 for (k = 0 ; k < nr ; k++)
382 glArrayElement( tri_indices[i+k] );
383 glEnd();
384 }
385 } else {
386 glBegin( GL_TRIANGLES );
387 for (i = 0 ; i < num_tri_verts ; i++)
388 glArrayElement( tri_indices[i] );
389
390 glEnd();
391 }
392 break;
393
394 case (IMMEDIATE|GLVERTEX|TRIANGLES):
395 if (with_state & MATERIALS) {
396 for (j = i = 0 ; i < num_tri_verts ; i += 600, j++) {
397 GLuint nr = MIN(num_tri_verts-i, 600);
398 GLuint k;
399 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col[j]);
400 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col[j]);
401 glBegin( GL_TRIANGLES );
402 for (k = 0 ; k < nr ; k++) {
403 glNormal3fv( &compressed_data[tri_indices[i+k]][3] );
404 glVertex3fv( &compressed_data[tri_indices[i+k]][0] );
405 }
406 glEnd();
407 }
408 } else {
409 glBegin( GL_TRIANGLES );
410 for (i = 0 ; i < num_tri_verts ; i++) {
411 glNormal3fv( &compressed_data[tri_indices[i]][3] );
412 glVertex3fv( &compressed_data[tri_indices[i]][0] );
413 }
414 glEnd();
415 }
416 break;
417
418 case (DISPLAYLIST|GLVERTEX|STRIPS):
419 if (!surf1)
420 surf1 = BuildList( GL_COMPILE_AND_EXECUTE );
421 else
422 glCallList(surf1);
423 break;
424
425 #endif
426
427 /* Uses the original arrays (including duplicate elements):
428 */
429 default:
430 glBegin( GL_TRIANGLE_STRIP );
431 for (i=0;i<numverts;i++) {
432 glNormal3fv( &data[i][3] );
433 glVertex3fv( &data[i][0] );
434 }
435 glEnd();
436 }
437 }
438
439
440
441 static void Display(void)
442 {
443 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
444 draw_surface( state );
445 glFlush();
446 if (doubleBuffer) glutSwapBuffers();
447 }
448
449 int BuildList( int mode )
450 {
451 int rv = glGenLists(1);
452 glNewList(rv, mode );
453 draw_surface( IMMEDIATE|GLVERTEX|STRIPS );
454 glEndList();
455 return rv;
456 }
457
458 /* KW: only do this when necessary, so CVA can re-use results.
459 */
460 static void set_matrix( void )
461 {
462 glMatrixMode(GL_MODELVIEW);
463 glLoadIdentity();
464 glTranslatef( 0.0, 0.0, dist );
465 glRotatef( yrot, 0.0, 1.0, 0.0 );
466 glRotatef( xrot, 1.0, 0.0, 0.0 );
467 }
468
469 static void Benchmark( float xdiff, float ydiff )
470 {
471 int startTime, endTime;
472 int draws;
473 double seconds, fps, triPerSecond;
474
475 printf("Benchmarking...\n");
476
477 draws = 0;
478 startTime = glutGet(GLUT_ELAPSED_TIME);
479 xrot = 0.0;
480 do {
481 xrot += xdiff;
482 yrot += ydiff;
483 set_matrix();
484 Display();
485 draws++;
486 endTime = glutGet(GLUT_ELAPSED_TIME);
487 } while (endTime - startTime < 5000); /* 5 seconds */
488
489 /* Results */
490 seconds = (double) (endTime - startTime) / 1000.0;
491 triPerSecond = (numverts - 2) * draws / seconds;
492 fps = draws / seconds;
493 printf("Result: triangles/sec: %g fps: %g\n", triPerSecond, fps);
494 }
495
496
497 static void InitMaterials(void)
498 {
499 static float ambient[] = {0.1, 0.1, 0.1, 1.0};
500 static float diffuse[] = {0.5, 1.0, 1.0, 1.0};
501 static float position0[] = {0.0, 0.0, 20.0, 0.0};
502 static float position1[] = {0.0, 0.0, -20.0, 0.0};
503 static float front_mat_shininess[] = {60.0};
504 static float front_mat_specular[] = {0.2, 0.2, 0.2, 1.0};
505 static float front_mat_diffuse[] = {0.5, 0.28, 0.38, 1.0};
506 /*
507 static float back_mat_shininess[] = {60.0};
508 static float back_mat_specular[] = {0.5, 0.5, 0.2, 1.0};
509 static float back_mat_diffuse[] = {1.0, 1.0, 0.2, 1.0};
510 */
511 static float lmodel_ambient[] = {1.0, 1.0, 1.0, 1.0};
512 static float lmodel_twoside[] = {GL_FALSE};
513
514 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
515 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
516 glLightfv(GL_LIGHT0, GL_POSITION, position0);
517 glEnable(GL_LIGHT0);
518
519 glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
520 glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
521 glLightfv(GL_LIGHT1, GL_POSITION, position1);
522 glEnable(GL_LIGHT1);
523
524 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
525 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
526
527 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_mat_shininess);
528 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_mat_specular);
529 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, front_mat_diffuse);
530
531 glPolygonStipple (halftone);
532 }
533
534
535
536 #define UPDATE(o,n,mask) (o&=~mask, o|=n&mask)
537 #define CHANGED(o,n,mask) ((n&mask) && \
538 (n&mask) != (o&mask) ? UPDATE(o,n,mask) : 0)
539
540 static void ModeMenu(int m)
541 {
542 m &= allowed;
543
544 if (!m) return;
545
546 if (m==QUIT)
547 exit(0);
548
549 if (m==GLINFO) {
550 printf("GL_VERSION: %s\n", (char *) glGetString(GL_VERSION));
551 printf("GL_EXTENSIONS: %s\n", (char *) glGetString(GL_EXTENSIONS));
552 printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER));
553 return;
554 }
555
556 if (CHANGED(state, m, FILTER_MASK)) {
557 if (m & LINEAR_FILTER) {
558 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
559 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
560 } else {
561 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
562 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
563 }
564 }
565
566 if (CHANGED(state, m, LIGHT_MASK)) {
567 if (m & LIT)
568 glEnable(GL_LIGHTING);
569 else
570 glDisable(GL_LIGHTING);
571 }
572
573 if (CHANGED(state, m, SHADE_MASK)) {
574 if (m & SHADE_SMOOTH)
575 glShadeModel(GL_SMOOTH);
576 else
577 glShadeModel(GL_FLAT);
578 }
579
580
581 if (CHANGED(state, m, TEXTURE_MASK)) {
582 if (m & TEXTURE)
583 glEnable(GL_TEXTURE_2D);
584 else
585 glDisable(GL_TEXTURE_2D);
586 }
587
588 if (CHANGED(state, m, REFLECT_MASK)) {
589 if (m & REFLECT) {
590 glEnable(GL_TEXTURE_GEN_S);
591 glEnable(GL_TEXTURE_GEN_T);
592 } else {
593 glDisable(GL_TEXTURE_GEN_S);
594 glDisable(GL_TEXTURE_GEN_T);
595 }
596 }
597
598 if (CHANGED(state, m, CLIP_MASK)) {
599 if (m & USER_CLIP) {
600 glEnable(GL_CLIP_PLANE0);
601 } else {
602 glDisable(GL_CLIP_PLANE0);
603 }
604 }
605
606 if (CHANGED(state, m, FOG_MASK)) {
607 if (m & FOG)
608 {
609 glEnable(GL_FOG);
610 printf("FOG enable\n");
611 }
612 else
613 {
614 glDisable(GL_FOG);
615 printf("FOG disable\n");
616 }
617 }
618
619 if (CHANGED(state, m, STIPPLE_MASK)) {
620 if (m & STIPPLE)
621 {
622 glEnable(GL_POLYGON_STIPPLE);
623 printf("STIPPLE enable\n");
624 }
625 else
626 {
627 glDisable(GL_POLYGON_STIPPLE);
628 printf("STIPPLE disable\n");
629 }
630 }
631
632 #ifdef GL_EXT_vertex_array
633 if (CHANGED(state, m, (COMPILED_MASK|RENDER_STYLE_MASK|PRIMITIVE_MASK)))
634 {
635 if ((m & (COMPILED_MASK|PRIMITIVE_MASK)) == (IMMEDIATE|STRIPS))
636 {
637 glVertexPointerEXT( 3, GL_FLOAT, sizeof(data[0]), numverts, data );
638 glNormalPointerEXT( GL_FLOAT, sizeof(data[0]), numverts, &data[0][3]);
639 }
640 else
641 {
642 glVertexPointerEXT( 3, GL_FLOAT, sizeof(data[0]), numuniq,
643 compressed_data );
644 glNormalPointerEXT( GL_FLOAT, sizeof(data[0]), numuniq,
645 &compressed_data[0][3]);
646 }
647 #ifdef GL_EXT_compiled_vertex_array
648 if (allowed & COMPILED) {
649 if (m & COMPILED) {
650 glLockArraysEXT( 0, numuniq );
651 } else {
652 glUnlockArraysEXT();
653 }
654 }
655 #endif
656 }
657 #endif
658
659 if (m & (RENDER_STYLE_MASK|PRIMITIVE_MASK)) {
660 UPDATE(state, m, (RENDER_STYLE_MASK|PRIMITIVE_MASK));
661 }
662
663 if (m & MATERIAL_MASK) {
664 UPDATE(state, m, MATERIAL_MASK);
665 }
666
667 glutPostRedisplay();
668 }
669
670
671
672 static void Init(int argc, char *argv[])
673 {
674 GLfloat fogColor[4] = {0.5,1.0,0.5,1.0};
675
676 glClearColor(0.0, 0.0, 1.0, 0.0);
677 glEnable( GL_DEPTH_TEST );
678 glEnable( GL_VERTEX_ARRAY_EXT );
679 glEnable( GL_NORMAL_ARRAY_EXT );
680
681 InitMaterials();
682
683 glMatrixMode(GL_PROJECTION);
684 glLoadIdentity();
685 glFrustum( -1.0, 1.0, -1.0, 1.0, 5, 25 );
686
687 glMatrixMode(GL_MODELVIEW);
688 glLoadIdentity();
689 glClipPlane(GL_CLIP_PLANE0, plane);
690
691 set_matrix();
692
693 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
694 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
695
696 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
697 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
698
699 if (!LoadRGBMipmaps(TEXTURE_FILE, GL_RGB)) {
700 printf("Error: couldn't load texture image\n");
701 exit(1);
702 }
703
704 /* Green fog is easy to see */
705 glFogi(GL_FOG_MODE,GL_EXP2);
706 glFogfv(GL_FOG_COLOR,fogColor);
707 glFogf(GL_FOG_DENSITY,0.15);
708 glHint(GL_FOG_HINT,GL_DONT_CARE);
709
710
711 compactify_arrays();
712 make_tri_indices();
713
714 surf1 = BuildList( GL_COMPILE );
715
716 ModeMenu(SHADE_SMOOTH|
717 LIT|
718 NO_TEXTURE|
719 NO_REFLECT|
720 POINT_FILTER|
721 IMMEDIATE|
722 NO_USER_CLIP|
723 NO_MATERIALS|
724 NO_FOG|
725 NO_STIPPLE|
726 GLVERTEX);
727
728 if (PrintInfo) {
729 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
730 printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
731 printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
732 printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
733 }
734 }
735
736
737
738 static void Reshape(int width, int height)
739 {
740 glViewport(0, 0, (GLint)width, (GLint)height);
741 }
742
743
744
745 static void Key( unsigned char key, int x, int y )
746 {
747 (void) x;
748 (void) y;
749 switch (key) {
750 case 27:
751 exit(0);
752 case 'f':
753 ModeMenu((state ^ FOG_MASK) & FOG_MASK);
754 break;
755 case 's':
756 ModeMenu((state ^ SHADE_MASK) & SHADE_MASK);
757 break;
758 case 't':
759 ModeMenu((state ^ STIPPLE_MASK) & STIPPLE_MASK);
760 break;
761 case 'l':
762 ModeMenu((state ^ LIGHT_MASK) & LIGHT_MASK);
763 break;
764 case 'm':
765 ModeMenu((state ^ MATERIAL_MASK) & MATERIAL_MASK);
766 break;
767 case 'c':
768 ModeMenu((state ^ CLIP_MASK) & CLIP_MASK);
769 break;
770 case 'v':
771 if (allowed&COMPILED)
772 ModeMenu(COMPILED|DRAW_ARRAYS|TRIANGLES);
773 break;
774 case 'V':
775 ModeMenu(IMMEDIATE|GLVERTEX|STRIPS);
776 break;
777 case 'b':
778 Benchmark(5.0, 0);
779 break;
780 case 'B':
781 Benchmark(0, 5.0);
782 break;
783 case 'i':
784 dist += .25;
785 set_matrix();
786 glutPostRedisplay();
787 break;
788 case 'I':
789 dist -= .25;
790 set_matrix();
791 glutPostRedisplay();
792 break;
793 case '-':
794 case '_':
795 plane[3] += 2.0;
796 glMatrixMode(GL_MODELVIEW);
797 glLoadIdentity();
798 glClipPlane(GL_CLIP_PLANE0, plane);
799 set_matrix();
800 glutPostRedisplay();
801 break;
802 case '+':
803 case '=':
804 plane[3] -= 2.0;
805 glMatrixMode(GL_MODELVIEW);
806 glLoadIdentity();
807 glClipPlane(GL_CLIP_PLANE0, plane);
808 set_matrix();
809 glutPostRedisplay();
810 break;
811
812 }
813 }
814
815
816 static void SpecialKey( int key, int x, int y )
817 {
818 (void) x;
819 (void) y;
820 switch (key) {
821 case GLUT_KEY_LEFT:
822 yrot -= 15.0;
823 break;
824 case GLUT_KEY_RIGHT:
825 yrot += 15.0;
826 break;
827 case GLUT_KEY_UP:
828 xrot += 15.0;
829 break;
830 case GLUT_KEY_DOWN:
831 xrot -= 15.0;
832 break;
833 default:
834 return;
835 }
836 set_matrix();
837 glutPostRedisplay();
838 }
839
840
841
842 static GLint Args(int argc, char **argv)
843 {
844 GLint i;
845 GLint mode = 0;
846
847 for (i = 1; i < argc; i++) {
848 if (strcmp(argv[i], "-sb") == 0) {
849 doubleBuffer = GL_FALSE;
850 }
851 else if (strcmp(argv[i], "-db") == 0) {
852 doubleBuffer = GL_TRUE;
853 }
854 else if (strcmp(argv[i], "-info") == 0) {
855 PrintInfo = GL_TRUE;
856 }
857 else {
858 printf("%s (Bad option).\n", argv[i]);
859 return QUIT;
860 }
861 }
862
863 return mode;
864 }
865
866 int main(int argc, char **argv)
867 {
868 GLenum type;
869 char *extensions;
870
871 GLuint arg_mode = Args(argc, argv);
872
873 if (arg_mode & QUIT)
874 exit(0);
875
876 read_surface( "isosurf.dat" );
877
878 glutInitWindowPosition(0, 0);
879 glutInitWindowSize(400, 400);
880
881 type = GLUT_DEPTH;
882 type |= GLUT_RGB;
883 type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
884 glutInitDisplayMode(type);
885
886 if (glutCreateWindow("Isosurface") <= 0) {
887 exit(0);
888 }
889
890 /* Make sure server supports the vertex array extension */
891 extensions = (char *) glGetString( GL_EXTENSIONS );
892
893 if (!strstr( extensions, "GL_EXT_vertex_array" ))
894 {
895 printf("Vertex arrays not supported by this renderer\n");
896 allowed &= ~(COMPILED|DRAW_ARRAYS|ARRAY_ELT);
897 }
898 else if (!strstr( extensions, "GL_EXT_compiled_vertex_array" ))
899 {
900 printf("Compiled vertex arrays not supported by this renderer\n");
901 allowed &= ~COMPILED;
902 }
903
904 Init(argc, argv);
905 ModeMenu(arg_mode);
906
907 glutCreateMenu(ModeMenu);
908 glutAddMenuEntry("GL info", GLINFO);
909 glutAddMenuEntry("", 0);
910 glutAddMenuEntry("Lit", LIT|NO_TEXTURE|NO_REFLECT);
911 glutAddMenuEntry("Unlit", UNLIT|NO_TEXTURE|NO_REFLECT);
912 /* glutAddMenuEntry("Textured", TEXTURE); */
913 glutAddMenuEntry("Reflect", TEXTURE|REFLECT);
914 glutAddMenuEntry("", 0);
915 glutAddMenuEntry("Smooth", SHADE_SMOOTH);
916 glutAddMenuEntry("Flat", SHADE_FLAT);
917 glutAddMenuEntry("", 0);
918 glutAddMenuEntry("Fog", FOG);
919 glutAddMenuEntry("No Fog", NO_FOG);
920 glutAddMenuEntry("", 0);
921 glutAddMenuEntry("Stipple", STIPPLE);
922 glutAddMenuEntry("No Stipple", NO_STIPPLE);
923 glutAddMenuEntry("", 0);
924 glutAddMenuEntry("Point Filtered", POINT_FILTER);
925 glutAddMenuEntry("Linear Filtered", LINEAR_FILTER);
926 glutAddMenuEntry("", 0);
927 glutAddMenuEntry("glVertex (STRIPS)", IMMEDIATE|GLVERTEX|STRIPS);
928 glutAddMenuEntry("glVertex (TRIANGLES)", IMMEDIATE|GLVERTEX|TRIANGLES);
929 glutAddMenuEntry("", 0);
930 glutAddMenuEntry("glVertex display list (STRIPS)",
931 DISPLAYLIST|GLVERTEX|STRIPS);
932 glutAddMenuEntry("", 0);
933 if (allowed & DRAW_ARRAYS) {
934 glutAddMenuEntry("DrawArrays (STRIPS)",
935 IMMEDIATE|DRAW_ARRAYS|STRIPS);
936 glutAddMenuEntry("ArrayElement (STRIPS)",
937 IMMEDIATE|ARRAY_ELT|STRIPS);
938 glutAddMenuEntry("DrawElements (TRIANGLES)",
939 IMMEDIATE|DRAW_ARRAYS|TRIANGLES);
940 glutAddMenuEntry("ArrayElement (TRIANGLES)",
941 IMMEDIATE|ARRAY_ELT|TRIANGLES);
942 glutAddMenuEntry("", 0);
943
944 }
945 if (allowed & COMPILED) {
946 glutAddMenuEntry("Compiled DrawElements (TRIANGLES)",
947 COMPILED|DRAW_ARRAYS|TRIANGLES);
948 glutAddMenuEntry("Compiled DrawElements (STRIPS)",
949 COMPILED|DRAW_ARRAYS|STRIPS);
950 glutAddMenuEntry("Compiled ArrayElement (TRIANGLES)",
951 COMPILED|ARRAY_ELT|TRIANGLES);
952 glutAddMenuEntry("Compiled ArrayElement (STRIPS)",
953 COMPILED|ARRAY_ELT|STRIPS);
954 glutAddMenuEntry("", 0);
955 }
956 glutAddMenuEntry("Quit", QUIT);
957 glutAttachMenu(GLUT_RIGHT_BUTTON);
958
959 glutReshapeFunc(Reshape);
960 glutKeyboardFunc(Key);
961 glutSpecialFunc(SpecialKey);
962 glutDisplayFunc(Display);
963
964 glutMainLoop();
965 return 0;
966 }