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