Home | History | Annotate | Line # | Download | only in demos
      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 "glut_wrap.h"
     37 
     38 #include "readtex.h"
     39 #define TEXTURE_FILE DEMOS_DATA_DIR "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 
    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       glDrawArrays( 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       glDrawArrays( 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       glDrawArrays( 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 
    478    case (GLVERTEX|TRIANGLES):
    479       if (with_state & MATERIALS) {
    480 	 for (j = i = 0 ; i < num_tri_verts ; i += 600, j++) {
    481 	    GLuint nr = MIN(num_tri_verts-i, 600);
    482 	    GLuint k;
    483 	    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col[j]);
    484 	    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col[j]);
    485 	    glBegin( GL_TRIANGLES );
    486 	    for (k = 0 ; k < nr ; k++) {
    487 	       glNormal3fv( &compressed_data[tri_indices[i+k]][3] );
    488 	       glVertex3fv( &compressed_data[tri_indices[i+k]][0] );
    489 	    }
    490 	    glEnd();
    491 	 }
    492       } else {
    493 	 glBegin( GL_TRIANGLES );
    494 	 for (i = 0 ; i < num_tri_verts ; i++) {
    495 	    glNormal3fv( &compressed_data[tri_indices[i]][3] );
    496 	    glVertex3fv( &compressed_data[tri_indices[i]][0] );
    497 	 }
    498 	 glEnd();
    499       }
    500       break;
    501 
    502    case (GLVERTEX|POINTS):
    503       /* Renders all points, but not in strip order...  Shouldn't be a
    504        * problem, but people may be confused as to why points are so
    505        * much faster in this demo...  And why cva doesn't help them...
    506        */
    507       glBegin( GL_POINTS );
    508       for ( i = 0 ; i < numuniq ; i++ ) {
    509          glNormal3fv( &compressed_data[i][3] );
    510          glVertex3fv( &compressed_data[i][0] );
    511       }
    512       glEnd();
    513       break;
    514 
    515    case (GLVERTEX|STRIPS):
    516       if (with_state & MATERIALS) {
    517          glBegin( GL_TRIANGLE_STRIP );
    518          for (i=0;i<numverts;i++) {
    519             if (i % 600 == 0 && i != 0) {
    520                unsigned j = i / 600;
    521                glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col[j]);
    522                glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col[j]);
    523             }
    524             glNormal3fv( &data[i][3] );
    525             glVertex3fv( &data[i][0] );
    526          }
    527          glEnd();
    528       }
    529       else {
    530          glBegin( GL_TRIANGLE_STRIP );
    531          for (i=0;i<numverts;i++) {
    532             glNormal3fv( &data[i][3] );
    533             glVertex3fv( &data[i][0] );
    534          }
    535          glEnd();
    536       }
    537       break;
    538 
    539    default:
    540       fprintf(stderr, "unimplemented mode %x...\n",
    541 	      (with_state & (RENDER_STYLE_MASK|PRIMITIVE_MASK)));
    542       break;
    543    }
    544 }
    545 
    546 
    547 
    548 static void Display(void)
    549 {
    550     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    551     draw_surface( state );
    552     glFlush();
    553     if (doubleBuffer) glutSwapBuffers();
    554 }
    555 
    556 
    557 /* KW: only do this when necessary, so CVA can re-use results.
    558  */
    559 static void set_matrix( void )
    560 {
    561    glMatrixMode(GL_MODELVIEW);
    562    glLoadIdentity();
    563    glTranslatef( 0.0, 0.0, dist );
    564    glRotatef( yrot, 0.0, 1.0, 0.0 );
    565    glRotatef( xrot, 1.0, 0.0, 0.0 );
    566 }
    567 
    568 static void Benchmark( float xdiff, float ydiff )
    569 {
    570    int startTime, endTime;
    571    int draws;
    572    double seconds, fps, triPerSecond;
    573 
    574    printf("Benchmarking...\n");
    575 
    576    draws = 0;
    577    startTime = glutGet(GLUT_ELAPSED_TIME);
    578    xrot = 0.0;
    579    do {
    580       xrot += xdiff;
    581       yrot += ydiff;
    582       set_matrix();
    583       Display();
    584       draws++;
    585       endTime = glutGet(GLUT_ELAPSED_TIME);
    586    } while (endTime - startTime < 5000);   /* 5 seconds */
    587 
    588    /* Results */
    589    seconds = (double) (endTime - startTime) / 1000.0;
    590    triPerSecond = (numverts - 2) * draws / seconds;
    591    fps = draws / seconds;
    592    printf("Result:  triangles/sec: %g  fps: %g\n", triPerSecond, fps);
    593 }
    594 
    595 
    596 static void InitMaterials(void)
    597 {
    598     static float ambient[] = {0.1, 0.1, 0.1, 1.0};
    599     static float diffuse[] = {0.5, 1.0, 1.0, 1.0};
    600     static float position0[] = {0.0, 0.0, 20.0, 0.0};
    601     static float position1[] = {0.0, 0.0, -20.0, 0.0};
    602     static float front_mat_shininess[] = {60.0};
    603     static float front_mat_specular[] = {0.2, 0.2, 0.2, 1.0};
    604     static float front_mat_diffuse[] = {0.5, 0.28, 0.38, 1.0};
    605     /*
    606     static float back_mat_shininess[] = {60.0};
    607     static float back_mat_specular[] = {0.5, 0.5, 0.2, 1.0};
    608     static float back_mat_diffuse[] = {1.0, 1.0, 0.2, 1.0};
    609     */
    610     static float lmodel_ambient[] = {1.0, 1.0, 1.0, 1.0};
    611     static float lmodel_twoside[] = {GL_FALSE};
    612 
    613     glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
    614     glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
    615     glLightfv(GL_LIGHT0, GL_POSITION, position0);
    616     glEnable(GL_LIGHT0);
    617 
    618     glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
    619     glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
    620     glLightfv(GL_LIGHT1, GL_POSITION, position1);
    621     glEnable(GL_LIGHT1);
    622 
    623     glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
    624     glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
    625 
    626     glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_mat_shininess);
    627     glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_mat_specular);
    628     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, front_mat_diffuse);
    629 
    630     glPolygonStipple (halftone);
    631 }
    632 
    633 
    634 
    635 #define UPDATE(o,n,mask) (o&=~mask, o|=n&mask)
    636 #define CHANGED(o,n,mask) ((n&mask) && (n&mask) != (o&mask) )
    637 
    638 static void ModeMenu(int m)
    639 {
    640    m &= allowed;
    641 
    642    if (!m) return;
    643 
    644    if (m==QUIT)
    645       exit(0);
    646 
    647    if (m==GLINFO) {
    648       printf("GL_VERSION: %s\n", (char *) glGetString(GL_VERSION));
    649       printf("GL_EXTENSIONS: %s\n", (char *) glGetString(GL_EXTENSIONS));
    650       printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER));
    651       return;
    652    }
    653 
    654    if (CHANGED(state, m, FILTER_MASK)) {
    655       UPDATE(state, m, FILTER_MASK);
    656       if (m & LINEAR_FILTER) {
    657 	 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    658 	 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    659       } else {
    660 	 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    661 	 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    662       }
    663    }
    664 
    665    if (CHANGED(state, m, LIGHT_MASK)) {
    666       UPDATE(state, m, LIGHT_MASK);
    667       if (m & LIT) {
    668 	 glEnable(GL_LIGHTING);
    669 	 glDisable(GL_TEXTURE_GEN_S);
    670 	 glDisable(GL_TEXTURE_GEN_T);
    671 	 glDisable(GL_TEXTURE_2D);
    672       }
    673       else if (m & UNLIT) {
    674 	 glDisable(GL_LIGHTING);
    675 	 glDisable(GL_TEXTURE_GEN_S);
    676 	 glDisable(GL_TEXTURE_GEN_T);
    677 	 glDisable(GL_TEXTURE_2D);
    678       }
    679       else if (m & REFLECT) {
    680 	 glDisable(GL_LIGHTING);
    681 	 glEnable(GL_TEXTURE_GEN_S);
    682 	 glEnable(GL_TEXTURE_GEN_T);
    683 	 glEnable(GL_TEXTURE_2D);
    684       }
    685    }
    686 
    687    if (CHANGED(state, m, SHADE_MASK)) {
    688       UPDATE(state, m, SHADE_MASK);
    689       if (m & SHADE_SMOOTH)
    690 	 glShadeModel(GL_SMOOTH);
    691       else
    692 	 glShadeModel(GL_FLAT);
    693    }
    694 
    695 
    696    if (CHANGED(state, m, CLIP_MASK)) {
    697       UPDATE(state, m, CLIP_MASK);
    698       if (m & USER_CLIP) {
    699 	 glEnable(GL_CLIP_PLANE0);
    700       } else {
    701 	 glDisable(GL_CLIP_PLANE0);
    702       }
    703    }
    704 
    705    if (CHANGED(state, m, FOG_MASK)) {
    706       UPDATE(state, m, FOG_MASK);
    707       if (m & FOG) {
    708 	 glEnable(GL_FOG);
    709       }
    710       else {
    711 	 glDisable(GL_FOG);
    712       }
    713    }
    714 
    715    if (CHANGED(state, m, STIPPLE_MASK)) {
    716       UPDATE(state, m, STIPPLE_MASK);
    717       if (m & STIPPLE) {
    718 	 glEnable(GL_POLYGON_STIPPLE);
    719       }
    720       else {
    721 	 glDisable(GL_POLYGON_STIPPLE);
    722       }
    723    }
    724 
    725    if (CHANGED(state, m, POLYGON_MASK)) {
    726       UPDATE(state, m, POLYGON_MASK);
    727       if (m & POLYGON_FILL) {
    728 	 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    729       }
    730       else if (m & POLYGON_LINE) {
    731 	 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    732       }
    733       else {
    734 	 glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
    735       }
    736    }
    737 
    738    if (CHANGED(state, m, (LOCK_MASK|RENDER_STYLE_MASK|PRIMITIVE_MASK)))
    739    {
    740       if (m & (PRIMITIVE_MASK)) {
    741 	 UPDATE(state, m, (PRIMITIVE_MASK));
    742       }
    743 
    744       if (m & (RENDER_STYLE_MASK)) {
    745 	 UPDATE(state, m, (RENDER_STYLE_MASK));
    746       }
    747 
    748       if (m & LOCK_MASK) {
    749 	 UPDATE(state, m, (LOCK_MASK));
    750       }
    751 
    752 
    753       print_flags("primitive", state & PRIMITIVE_MASK);
    754       print_flags("render style", state & RENDER_STYLE_MASK);
    755 
    756       if ((state & PRIMITIVE_MASK) != STRIPS &&
    757 	  ((state & RENDER_STYLE_MASK) == DRAW_ELTS ||
    758 	   (state & RENDER_STYLE_MASK) == ARRAY_ELT ||
    759 	   (state & PRIMITIVE_MASK) == POINTS))
    760       {
    761 	 fprintf(stderr, "enabling small arrays\n");
    762 	 /* Rendering any primitive with draw-element/array-element
    763 	  *  --> Can't do strips here as ordering has been lost in
    764 	  *  compaction process...
    765 	  */
    766 	 glVertexPointer( 3, GL_FLOAT, sizeof(data[0]), compressed_data );
    767 	 glNormalPointer( GL_FLOAT, sizeof(data[0]), &compressed_data[0][3] );
    768 #ifdef GL_EXT_compiled_vertex_array
    769 	 if (allowed & LOCKED) {
    770 	    if (state & LOCKED) {
    771 	       glLockArraysEXT( 0, numuniq );
    772 	    } else {
    773 	       glUnlockArraysEXT();
    774 	    }
    775 	 }
    776 #endif
    777       }
    778       else if ((state & PRIMITIVE_MASK) == TRIANGLES &&
    779 	       (state & RENDER_STYLE_MASK) == DRAW_ARRAYS) {
    780 	 fprintf(stderr, "enabling big arrays\n");
    781 	 /* Only get here for TRIANGLES and drawarrays
    782 	  */
    783 	 glVertexPointer( 3, GL_FLOAT, sizeof(data[0]), expanded_data );
    784 	 glNormalPointer( GL_FLOAT, sizeof(data[0]), &expanded_data[0][3] );
    785 
    786 #ifdef GL_EXT_compiled_vertex_array
    787 	 if (allowed & LOCKED) {
    788 	    if (state & LOCKED) {
    789 	       glLockArraysEXT( 0, (numverts-2)*3 );
    790 	    } else {
    791 	       glUnlockArraysEXT();
    792 	    }
    793 	 }
    794 #endif
    795       }
    796       else {
    797 	 fprintf(stderr, "enabling normal arrays\n");
    798 	 glVertexPointer( 3, GL_FLOAT, sizeof(data[0]), data );
    799 	 glNormalPointer( GL_FLOAT, sizeof(data[0]), &data[0][3] );
    800 #ifdef GL_EXT_compiled_vertex_array
    801 	 if (allowed & LOCKED) {
    802 	    if (state & LOCKED) {
    803 	       glLockArraysEXT( 0, numverts );
    804 	    } else {
    805 	       glUnlockArraysEXT();
    806 	    }
    807 	 }
    808 #endif
    809       }
    810 
    811    }
    812 
    813 
    814    if (m & DLIST_MASK) {
    815       UPDATE(state, m, DLIST_MASK);
    816    }
    817 
    818    if (m & MATERIAL_MASK) {
    819       UPDATE(state, m, MATERIAL_MASK);
    820    }
    821 
    822    print_flags("new flags", state);
    823 
    824    glutPostRedisplay();
    825 }
    826 
    827 
    828 
    829 static void Init(int argc, char *argv[])
    830 {
    831    GLfloat fogColor[4] = {0.5,1.0,0.5,1.0};
    832 
    833    xrot = 0;
    834    yrot = 0;
    835    dist = -6;
    836    plane[0] = 1.0;
    837    plane[1] = 0.0;
    838    plane[2] = -1.0;
    839    plane[3] = 0.0;
    840 
    841    glClearColor(0.0, 0.0, 1.0, 0.0);
    842    glEnable( GL_DEPTH_TEST );
    843    glEnableClientState( GL_VERTEX_ARRAY );
    844    glEnableClientState( GL_NORMAL_ARRAY );
    845 
    846    glMatrixMode(GL_PROJECTION);
    847    glLoadIdentity();
    848    glFrustum( -1.0, 1.0, -1.0, 1.0, 5, 25 );
    849 
    850    glMatrixMode(GL_MODELVIEW);
    851    glLoadIdentity();
    852    glClipPlane(GL_CLIP_PLANE0, plane);
    853 
    854    InitMaterials();
    855 
    856    set_matrix();
    857 
    858    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    859    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
    860 
    861    glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
    862    glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
    863 
    864 
    865    /* Green fog is easy to see */
    866    glFogi(GL_FOG_MODE,GL_EXP2);
    867    glFogfv(GL_FOG_COLOR,fogColor);
    868    glFogf(GL_FOG_DENSITY,0.15);
    869    glHint(GL_FOG_HINT,GL_DONT_CARE);
    870 
    871    {
    872       static int firsttime = 1;
    873       if (firsttime) {
    874 	 firsttime = 0;
    875 	 compactify_arrays();
    876 	 expand_arrays();
    877 	 make_tri_indices();
    878 
    879 	 if (!LoadRGBMipmaps(TEXTURE_FILE, GL_RGB)) {
    880 	    printf("Error: couldn't load texture image\n");
    881 	    exit(1);
    882 	 }
    883       }
    884    }
    885 
    886    ModeMenu(SHADE_SMOOTH|
    887 	    LIT|
    888 	    POINT_FILTER|
    889 	    NO_USER_CLIP|
    890 	    NO_MATERIALS|
    891 	    NO_FOG|
    892 	    NO_STIPPLE|
    893 	    IMMEDIATE|
    894 	    STRIPS|
    895 	    UNLOCKED|
    896 	    GLVERTEX);
    897 
    898    if (PrintInfo) {
    899       printf("GL_RENDERER   = %s\n", (char *) glGetString(GL_RENDERER));
    900       printf("GL_VERSION    = %s\n", (char *) glGetString(GL_VERSION));
    901       printf("GL_VENDOR     = %s\n", (char *) glGetString(GL_VENDOR));
    902       printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
    903    }
    904 }
    905 
    906 
    907 
    908 static void Reshape(int width, int height)
    909 {
    910     glViewport(0, 0, (GLint)width, (GLint)height);
    911 }
    912 
    913 
    914 
    915 static void Key( unsigned char key, int x, int y )
    916 {
    917    (void) x;
    918    (void) y;
    919    switch (key) {
    920    case 27:
    921       exit(0);
    922    case 'f':
    923       ModeMenu((state ^ FOG_MASK) & FOG_MASK);
    924       break;
    925    case 's':
    926       ModeMenu((state ^ SHADE_MASK) & SHADE_MASK);
    927       break;
    928    case 't':
    929       ModeMenu((state ^ STIPPLE_MASK) & STIPPLE_MASK);
    930       break;
    931    case 'l':
    932       ModeMenu((state ^ LIGHT_MASK) & (LIT|UNLIT));
    933       break;
    934    case 'm':
    935       ModeMenu((state ^ MATERIAL_MASK) & MATERIAL_MASK);
    936       break;
    937    case 'c':
    938       ModeMenu((state ^ CLIP_MASK) & CLIP_MASK);
    939       break;
    940    case 'v':
    941       ModeMenu((LOCKED|IMMEDIATE|DRAW_ELTS|TRIANGLES) & allowed);
    942       break;
    943    case 'V':
    944       ModeMenu(UNLOCKED|IMMEDIATE|GLVERTEX|STRIPS);
    945       break;
    946    case 'b':
    947       Benchmark(5.0, 0);
    948       break;
    949    case 'B':
    950       Benchmark(0, 5.0);
    951       break;
    952    case 'i':
    953       dist += .25;
    954       set_matrix();
    955       glutPostRedisplay();
    956       break;
    957    case 'I':
    958       dist -= .25;
    959       set_matrix();
    960       glutPostRedisplay();
    961       break;
    962    case '-':
    963    case '_':
    964       plane[3] += 0.5;
    965       glMatrixMode(GL_MODELVIEW);
    966       glLoadIdentity();
    967       glClipPlane(GL_CLIP_PLANE0, plane);
    968       set_matrix();
    969       glutPostRedisplay();
    970       break;
    971    case '+':
    972    case '=':
    973       plane[3] -= 0.5;
    974       glMatrixMode(GL_MODELVIEW);
    975       glLoadIdentity();
    976       glClipPlane(GL_CLIP_PLANE0, plane);
    977       set_matrix();
    978       glutPostRedisplay();
    979       break;
    980    case ' ':
    981       Init(0,0);
    982       break;
    983    }
    984 }
    985 
    986 
    987 static void SpecialKey( int key, int x, int y )
    988 {
    989    (void) x;
    990    (void) y;
    991    switch (key) {
    992    case GLUT_KEY_LEFT:
    993       yrot -= 15.0;
    994       break;
    995    case GLUT_KEY_RIGHT:
    996       yrot += 15.0;
    997       break;
    998    case GLUT_KEY_UP:
    999       xrot += 15.0;
   1000       break;
   1001    case GLUT_KEY_DOWN:
   1002       xrot -= 15.0;
   1003       break;
   1004    default:
   1005       return;
   1006    }
   1007    set_matrix();
   1008    glutPostRedisplay();
   1009 }
   1010 
   1011 
   1012 
   1013 static GLint Args(int argc, char **argv)
   1014 {
   1015    GLint i;
   1016    GLint mode = 0;
   1017 
   1018    for (i = 1; i < argc; i++) {
   1019       if (strcmp(argv[i], "-sb") == 0) {
   1020          doubleBuffer = GL_FALSE;
   1021       }
   1022       else if (strcmp(argv[i], "-db") == 0) {
   1023          doubleBuffer = GL_TRUE;
   1024       }
   1025       else if (strcmp(argv[i], "-info") == 0) {
   1026          PrintInfo = GL_TRUE;
   1027       }
   1028       else if (strcmp(argv[i], "-10") == 0) {
   1029          maxverts = 10;
   1030       }
   1031       else if (strcmp(argv[i], "-100") == 0) {
   1032 	 maxverts = 100;
   1033       }
   1034       else if (strcmp(argv[i], "-1000") == 0) {
   1035 	 maxverts = 1000;
   1036       }
   1037       else {
   1038          printf("%s (Bad option).\n", argv[i]);
   1039 	 return QUIT;
   1040       }
   1041    }
   1042 
   1043    return mode;
   1044 }
   1045 
   1046 int main(int argc, char **argv)
   1047 {
   1048    GLenum type;
   1049 
   1050    GLuint arg_mode = Args(argc, argv);
   1051 
   1052    if (arg_mode & QUIT)
   1053       exit(0);
   1054 
   1055    read_surface(DEMOS_DATA_DIR "isosurf.dat");
   1056 
   1057    glutInitWindowSize(400, 400);
   1058    glutInit( &argc, argv);
   1059 
   1060    type = GLUT_DEPTH;
   1061    type |= GLUT_RGB;
   1062    type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
   1063    glutInitDisplayMode(type);
   1064 
   1065    if (glutCreateWindow("Isosurface") <= 0) {
   1066       exit(0);
   1067    }
   1068 
   1069    glewInit();
   1070 
   1071    /* Make sure server supports vertex arrays */
   1072    if (!GLEW_VERSION_1_1)
   1073    {
   1074       printf("Vertex arrays not supported by this renderer\n");
   1075       allowed &= ~(LOCKED|DRAW_ARRAYS|DRAW_ELTS|ARRAY_ELT);
   1076    }
   1077    else if (!GLEW_EXT_compiled_vertex_array)
   1078    {
   1079       printf("Compiled vertex arrays not supported by this renderer\n");
   1080       allowed &= ~LOCKED;
   1081    }
   1082 
   1083    Init(argc, argv);
   1084    ModeMenu(arg_mode);
   1085 
   1086    glutCreateMenu(ModeMenu);
   1087    glutAddMenuEntry("GL info",               GLINFO);
   1088    glutAddMenuEntry("", 0);
   1089    glutAddMenuEntry("Lit",                   LIT);
   1090    glutAddMenuEntry("Unlit",                 UNLIT);
   1091    glutAddMenuEntry("Reflect",               REFLECT);
   1092    glutAddMenuEntry("", 0);
   1093    glutAddMenuEntry("Smooth",                SHADE_SMOOTH);
   1094    glutAddMenuEntry("Flat",                  SHADE_FLAT);
   1095    glutAddMenuEntry("", 0);
   1096    glutAddMenuEntry("Fog",                   FOG);
   1097    glutAddMenuEntry("No Fog",                NO_FOG);
   1098    glutAddMenuEntry("", 0);
   1099    glutAddMenuEntry("Stipple",               STIPPLE);
   1100    glutAddMenuEntry("No Stipple",            NO_STIPPLE);
   1101    glutAddMenuEntry("", 0);
   1102    glutAddMenuEntry("Polygon Mode Fill",     POLYGON_FILL);
   1103    glutAddMenuEntry("Polygon Mode Line",     POLYGON_LINE);
   1104    glutAddMenuEntry("Polygon Mode Points",   POLYGON_POINT);
   1105    glutAddMenuEntry("", 0);
   1106    glutAddMenuEntry("Point Filtered",        POINT_FILTER);
   1107    glutAddMenuEntry("Linear Filtered",       LINEAR_FILTER);
   1108    glutAddMenuEntry("", 0);
   1109    glutAddMenuEntry("GL_TRIANGLES",          TRIANGLES);
   1110    glutAddMenuEntry("GL_TRIANGLE_STRIPS",    STRIPS);
   1111    glutAddMenuEntry("GL_POINTS",             POINTS);
   1112    glutAddMenuEntry("", 0);
   1113    glutAddMenuEntry("Displaylist",           DISPLAYLIST);
   1114    glutAddMenuEntry("Immediate",             IMMEDIATE);
   1115    glutAddMenuEntry("", 0);
   1116    if (allowed & LOCKED) {
   1117       glutAddMenuEntry("Locked Arrays (CVA)", LOCKED);
   1118       glutAddMenuEntry("Unlocked Arrays",     UNLOCKED);
   1119       glutAddMenuEntry("", 0);
   1120    }
   1121    glutAddMenuEntry("glVertex",               GLVERTEX);
   1122    if (allowed & DRAW_ARRAYS) {
   1123       glutAddMenuEntry("glDrawElements",      DRAW_ELTS);
   1124       glutAddMenuEntry("glDrawArrays",	      DRAW_ARRAYS);
   1125       glutAddMenuEntry("glArrayElement",      ARRAY_ELT);
   1126    }
   1127    glutAddMenuEntry("", 0);
   1128    glutAddMenuEntry("Quit",                   QUIT);
   1129    glutAttachMenu(GLUT_RIGHT_BUTTON);
   1130 
   1131    glutReshapeFunc(Reshape);
   1132    glutKeyboardFunc(Key);
   1133    glutSpecialFunc(SpecialKey);
   1134    glutDisplayFunc(Display);
   1135 
   1136    glutMainLoop();
   1137    return 0;
   1138 }
   1139