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