132001f49Smrg
232001f49Smrg/*
332001f49Smrg * Display an isosurface of 3-D wind speed volume.
432001f49Smrg *
532001f49Smrg * Command line options:
632001f49Smrg *    -info      print GL implementation information
732001f49Smrg *
832001f49Smrg * Brian Paul  This file in public domain.
932001f49Smrg */
1032001f49Smrg
1132001f49Smrg
1232001f49Smrg/* Keys:
1332001f49Smrg * =====
1432001f49Smrg *
1532001f49Smrg *   - Arrow keys to rotate
1632001f49Smrg *   - 's' toggles smooth shading
1732001f49Smrg *   - 'l' toggles lighting
1832001f49Smrg *   - 'f' toggles fog
1932001f49Smrg *   - 'I' and 'i' zoom in and out
2032001f49Smrg *   - 'c' toggles a user clip plane
2132001f49Smrg *   - 'm' toggles colorful materials in GL_TRIANGLES modes.
2232001f49Smrg *   - '+' and '-' move the user clip plane
2332001f49Smrg *
2432001f49Smrg * Other options are available via the popup menu.
2532001f49Smrg */
2632001f49Smrg
2732001f49Smrg#include <stdio.h>
2832001f49Smrg#include <string.h>
2932001f49Smrg#include <stdlib.h>
3032001f49Smrg#include <math.h>
3132001f49Smrg#ifdef _WIN32
3232001f49Smrg#include <windows.h>
3332001f49Smrg#undef CLIP_MASK
3432001f49Smrg#endif
3532001f49Smrg#include <GL/glew.h>
3632001f49Smrg#include "glut_wrap.h"
3732001f49Smrg
3832001f49Smrg#include "readtex.h"
3932001f49Smrg#define TEXTURE_FILE DEMOS_DATA_DIR "reflect.rgb"
4032001f49Smrg
4132001f49Smrg#define LIT		0x00000001
4232001f49Smrg#define UNLIT		0x00000002
4332001f49Smrg#define REFLECT		0x00000004
4432001f49Smrg#define POINT_FILTER	0x00000008
4532001f49Smrg#define LINEAR_FILTER	0x00000010
4632001f49Smrg#define GLVERTEX	0x00000020
4732001f49Smrg#define DRAW_ELTS	0x00000040
4832001f49Smrg#define DRAW_ARRAYS	0x00000080
4932001f49Smrg#define ARRAY_ELT	0x00000100
5032001f49Smrg#define LOCKED	        0x00000200
5132001f49Smrg#define UNLOCKED	0x00000400
5232001f49Smrg#define IMMEDIATE	0x00000800
5332001f49Smrg#define DISPLAYLIST	0x00001000
5432001f49Smrg#define SHADE_SMOOTH	0x00002000
5532001f49Smrg#define SHADE_FLAT	0x00004000
5632001f49Smrg#define TRIANGLES	0x00008000
5732001f49Smrg#define STRIPS		0x00010000
5832001f49Smrg#define POINTS		0x00020000
5932001f49Smrg#define USER_CLIP	0x00040000
6032001f49Smrg#define NO_USER_CLIP	0x00080000
6132001f49Smrg#define MATERIALS	0x00100000
6232001f49Smrg#define NO_MATERIALS	0x00200000
6332001f49Smrg#define FOG		0x00400000
6432001f49Smrg#define NO_FOG		0x00800000
6532001f49Smrg#define QUIT		0x01000000
6632001f49Smrg#define GLINFO		0x02000000
6732001f49Smrg#define STIPPLE		0x04000000
6832001f49Smrg#define NO_STIPPLE	0x08000000
6932001f49Smrg#define POLYGON_FILL	0x10000000
7032001f49Smrg#define POLYGON_LINE	0x20000000
7132001f49Smrg#define POLYGON_POINT	0x40000000
7232001f49Smrg
7332001f49Smrg#define LIGHT_MASK		(LIT|UNLIT|REFLECT)
7432001f49Smrg#define FILTER_MASK		(POINT_FILTER|LINEAR_FILTER)
7532001f49Smrg#define RENDER_STYLE_MASK	(GLVERTEX|DRAW_ARRAYS|DRAW_ELTS|ARRAY_ELT)
7632001f49Smrg#define DLIST_MASK		(IMMEDIATE|DISPLAYLIST)
7732001f49Smrg#define LOCK_MASK		(LOCKED|UNLOCKED)
7832001f49Smrg#define MATERIAL_MASK		(MATERIALS|NO_MATERIALS)
7932001f49Smrg#define PRIMITIVE_MASK		(TRIANGLES|STRIPS|POINTS)
8032001f49Smrg#define CLIP_MASK		(USER_CLIP|NO_USER_CLIP)
8132001f49Smrg#define SHADE_MASK		(SHADE_SMOOTH|SHADE_FLAT)
8232001f49Smrg#define FOG_MASK		(FOG|NO_FOG)
8332001f49Smrg#define STIPPLE_MASK		(STIPPLE|NO_STIPPLE)
8432001f49Smrg#define POLYGON_MASK		(POLYGON_FILL|POLYGON_LINE|POLYGON_POINT)
8532001f49Smrg
8632001f49Smrg#define MAXVERTS 10000
8732001f49Smrgstatic GLint maxverts = MAXVERTS;
8832001f49Smrgstatic float data[MAXVERTS][6];
8932001f49Smrgstatic float compressed_data[MAXVERTS][6];
9032001f49Smrgstatic float expanded_data[MAXVERTS*3][6];
9132001f49Smrgstatic GLuint indices[MAXVERTS];
9232001f49Smrgstatic GLuint tri_indices[MAXVERTS*3];
9332001f49Smrgstatic GLuint strip_indices[MAXVERTS];
9432001f49Smrgstatic GLfloat col[100][4];
9532001f49Smrgstatic GLint numverts, num_tri_verts, numuniq;
9632001f49Smrg
9732001f49Smrgstatic GLfloat xrot;
9832001f49Smrgstatic GLfloat yrot;
9932001f49Smrgstatic GLfloat dist;
10032001f49Smrgstatic GLint state, allowed = ~0;
10132001f49Smrgstatic GLboolean doubleBuffer = GL_TRUE;
10232001f49Smrgstatic GLdouble plane[4];
10332001f49Smrgstatic GLuint surf1, dlist_state;
10432001f49Smrg
10532001f49Smrgstatic GLboolean PrintInfo = GL_FALSE;
10632001f49Smrg
10732001f49Smrg
10832001f49Smrgstatic GLubyte halftone[] = {
10932001f49Smrg   0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA,
11032001f49Smrg   0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
11132001f49Smrg   0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA,
11232001f49Smrg   0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
11332001f49Smrg   0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA,
11432001f49Smrg   0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
11532001f49Smrg   0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA,
11632001f49Smrg   0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
11732001f49Smrg   0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA,
11832001f49Smrg   0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
11932001f49Smrg   0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55};
12032001f49Smrg
12132001f49Smrg
12232001f49Smrgstatic void read_surface( char *filename )
12332001f49Smrg{
12432001f49Smrg   FILE *f;
12532001f49Smrg
12632001f49Smrg   f = fopen(filename,"r");
12732001f49Smrg   if (!f) {
12832001f49Smrg      printf("couldn't read %s\n", filename);
12932001f49Smrg      exit(1);
13032001f49Smrg   }
13132001f49Smrg
13232001f49Smrg   numverts = 0;
13332001f49Smrg   while (!feof(f) && numverts<maxverts) {
13432001f49Smrg      int result;
13532001f49Smrg      result = fscanf( f, "%f %f %f  %f %f %f",
13632001f49Smrg	               &data[numverts][0], &data[numverts][1], &data[numverts][2],
13732001f49Smrg	               &data[numverts][3], &data[numverts][4], &data[numverts][5] );
13832001f49Smrg      (void) result;
13932001f49Smrg      numverts++;
14032001f49Smrg   }
14132001f49Smrg   numverts--;
14232001f49Smrg
14332001f49Smrg   printf("%d vertices, %d triangles\n", numverts, numverts-2);
14432001f49Smrg   fclose(f);
14532001f49Smrg}
14632001f49Smrg
14732001f49Smrg
14832001f49Smrg
14932001f49Smrgstatic void print_flags( const char *msg, GLuint flags )
15032001f49Smrg{
15132001f49Smrg   fprintf(stderr,
15232001f49Smrg	   "%s (0x%x): %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
15332001f49Smrg	   msg, flags,
15432001f49Smrg	   (flags & GLVERTEX) ? "glVertex, " : "",
15532001f49Smrg	   (flags & DRAW_ARRAYS) ? "glDrawArrays, " : "",
15632001f49Smrg	   (flags & DRAW_ELTS) ? "glDrawElements, " : "",
15732001f49Smrg	   (flags & ARRAY_ELT) ? "glArrayElement, " : "",
15832001f49Smrg	   (flags & LOCKED) ? "locked arrays, " : "",
15932001f49Smrg	   (flags & TRIANGLES) ? "GL_TRIANGLES, " : "",
16032001f49Smrg	   (flags & STRIPS) ? "GL_TRIANGLE_STRIP, " : "",
16132001f49Smrg	   (flags & POINTS) ? "GL_POINTS, " : "",
16232001f49Smrg	   (flags & DISPLAYLIST) ? "as a displaylist, " : "",
16332001f49Smrg	   (flags & LIT) ? "lit, " : "",
16432001f49Smrg	   (flags & UNLIT) ? "unlit, " : "",
16532001f49Smrg	   (flags & REFLECT) ? "reflect, " : "",
16632001f49Smrg	   (flags & SHADE_FLAT) ? "flat-shaded, " : "",
16732001f49Smrg	   (flags & USER_CLIP) ? "user_clip, " : "",
16832001f49Smrg	   (flags & MATERIALS) ? "materials, " : "",
16932001f49Smrg	   (flags & FOG) ? "fog, " : "",
17032001f49Smrg	   (flags & STIPPLE) ? "stipple, " : "",
17132001f49Smrg	   (flags & POLYGON_LINE) ? "polygon mode line, " : "",
17232001f49Smrg	   (flags & POLYGON_POINT) ? "polygon mode point, " : "");
17332001f49Smrg}
17432001f49Smrg
17532001f49Smrg
17632001f49Smrg
17732001f49Smrgstruct data_idx {
17832001f49Smrg   float *data;
17932001f49Smrg   int idx;
18032001f49Smrg   int uniq_idx;
18132001f49Smrg};
18232001f49Smrg
18332001f49Smrg
18432001f49Smrg#define COMPARE_FUNC( AXIS )                            \
18532001f49Smrgstatic int compare_axis_##AXIS( const void *a, const void *b )	\
18632001f49Smrg{							\
18732001f49Smrg   float t = ( (*(struct data_idx *)a).data[AXIS] -	\
18832001f49Smrg	       (*(struct data_idx *)b).data[AXIS] );	\
18932001f49Smrg   							\
19032001f49Smrg   if (t < 0) return -1;				\
19132001f49Smrg   if (t > 0) return 1;					\
19232001f49Smrg   return 0;						\
19332001f49Smrg}
19432001f49Smrg
19532001f49SmrgCOMPARE_FUNC(0)
19632001f49SmrgCOMPARE_FUNC(1)
19732001f49SmrgCOMPARE_FUNC(2)
19832001f49SmrgCOMPARE_FUNC(3)
19932001f49SmrgCOMPARE_FUNC(4)
20032001f49SmrgCOMPARE_FUNC(5)
20132001f49SmrgCOMPARE_FUNC(6)
20232001f49Smrg
20332001f49Smrgint (*(compare[7]))( const void *a, const void *b ) =
20432001f49Smrg{
20532001f49Smrg   compare_axis_0,
20632001f49Smrg   compare_axis_1,
20732001f49Smrg   compare_axis_2,
20832001f49Smrg   compare_axis_3,
20932001f49Smrg   compare_axis_4,
21032001f49Smrg   compare_axis_5,
21132001f49Smrg   compare_axis_6,
21232001f49Smrg};
21332001f49Smrg
21432001f49Smrg
21532001f49Smrg#define VEC_ELT(f, s, i)  (float *)(((char *)f) + s * i)
21632001f49Smrg
21732001f49Smrgstatic int sort_axis( int axis,
21832001f49Smrg		      int vec_size,
21932001f49Smrg		      int vec_stride,
22032001f49Smrg		      struct data_idx *indices,
22132001f49Smrg		      int start,
22232001f49Smrg		      int finish,
22332001f49Smrg		      float *out,
22432001f49Smrg		      int uniq,
22532001f49Smrg		      const float fudge )
22632001f49Smrg{
22732001f49Smrg   int i;
22832001f49Smrg
22932001f49Smrg   if (finish-start > 2)
23032001f49Smrg   {
23132001f49Smrg      qsort( indices+start, finish-start, sizeof(*indices), compare[axis] );
23232001f49Smrg   }
23332001f49Smrg   else if (indices[start].data[axis] > indices[start+1].data[axis])
23432001f49Smrg   {
23532001f49Smrg      struct data_idx tmp = indices[start];
23632001f49Smrg      indices[start] = indices[start+1];
23732001f49Smrg      indices[start+1] = tmp;
23832001f49Smrg   }
23932001f49Smrg
24032001f49Smrg   if (axis == vec_size-1) {
24132001f49Smrg      for (i = start ; i < finish ; ) {
24232001f49Smrg	 float max = indices[i].data[axis] + fudge;
24332001f49Smrg	 float *dest = VEC_ELT(out, vec_stride, uniq);
24432001f49Smrg	 int j;
24532001f49Smrg
24632001f49Smrg	 for (j = 0 ; j < vec_size ; j++)
24732001f49Smrg	    dest[j] = indices[i].data[j];
24832001f49Smrg
24932001f49Smrg	 for ( ; i < finish && max >= indices[i].data[axis]; i++)
25032001f49Smrg	    indices[i].uniq_idx = uniq;
25132001f49Smrg
25232001f49Smrg	 uniq++;
25332001f49Smrg      }
25432001f49Smrg   } else {
25532001f49Smrg      for (i = start ; i < finish ; ) {
25632001f49Smrg	 int j = i + 1;
25732001f49Smrg	 float max = indices[i].data[axis] + fudge;
25832001f49Smrg	 while (j < finish && max >= indices[j].data[axis]) j++;
25932001f49Smrg	 if (j == i+1) {
26032001f49Smrg	    float *dest = VEC_ELT(out, vec_stride, uniq);
26132001f49Smrg	    int k;
26232001f49Smrg
26332001f49Smrg	    indices[i].uniq_idx = uniq;
26432001f49Smrg
26532001f49Smrg	    for (k = 0 ; k < vec_size ; k++)
26632001f49Smrg	       dest[k] = indices[i].data[k];
26732001f49Smrg
26832001f49Smrg	    uniq++;
26932001f49Smrg	 } else {
27032001f49Smrg	    uniq = sort_axis( axis+1, vec_size, vec_stride,
27132001f49Smrg			      indices, i, j, out, uniq, fudge );
27232001f49Smrg	 }
27332001f49Smrg	 i = j;
27432001f49Smrg      }
27532001f49Smrg   }
27632001f49Smrg
27732001f49Smrg   return uniq;
27832001f49Smrg}
27932001f49Smrg
28032001f49Smrg
28132001f49Smrgstatic void extract_indices1( const struct data_idx *in, unsigned int *out,
28232001f49Smrg			      int n )
28332001f49Smrg{
28432001f49Smrg   int i;
28532001f49Smrg   for ( i = 0 ; i < n ; i++ ) {
28632001f49Smrg      out[in[i].idx] = in[i].uniq_idx;
28732001f49Smrg   }
28832001f49Smrg}
28932001f49Smrg
29032001f49Smrg
29132001f49Smrgstatic void compactify_arrays(void)
29232001f49Smrg{
29332001f49Smrg   int i;
29432001f49Smrg   struct data_idx *ind;
29532001f49Smrg
29632001f49Smrg   ind = (struct data_idx *) malloc( sizeof(struct data_idx) * numverts );
29732001f49Smrg
29832001f49Smrg   for (i = 0 ; i < numverts ; i++) {
29932001f49Smrg      ind[i].idx = i;
30032001f49Smrg      ind[i].data = data[i];
30132001f49Smrg   }
30232001f49Smrg
30332001f49Smrg   numuniq = sort_axis(0,
30432001f49Smrg		       sizeof(compressed_data[0])/sizeof(float),
30532001f49Smrg		       sizeof(compressed_data[0]),
30632001f49Smrg		       ind,
30732001f49Smrg		       0,
30832001f49Smrg		       numverts,
30932001f49Smrg		       (float *)compressed_data,
31032001f49Smrg		       0,
31132001f49Smrg		       1e-6);
31232001f49Smrg
31332001f49Smrg   printf("Nr unique vertex/normal pairs: %d\n", numuniq);
31432001f49Smrg
31532001f49Smrg   extract_indices1( ind, indices, numverts );
31632001f49Smrg   free( ind );
31732001f49Smrg}
31832001f49Smrg
31932001f49Smrgstatic void expand_arrays(void)
32032001f49Smrg{
32132001f49Smrg   int i;
32232001f49Smrg   int parity = 0;
32332001f49Smrg   for (i = 2 ; i < numverts ; i++, parity ^= 1) {
32432001f49Smrg      int v0 = i-2+parity;
32532001f49Smrg      int v1 = i-1-parity;
32632001f49Smrg      int v2 = i;
32732001f49Smrg      memcpy( expanded_data[(i-2)*3+0], data[v0], sizeof(data[0]) );
32832001f49Smrg      memcpy( expanded_data[(i-2)*3+1], data[v1], sizeof(data[0]) );
32932001f49Smrg      memcpy( expanded_data[(i-2)*3+2], data[v2], sizeof(data[0]) );
33032001f49Smrg   }
33132001f49Smrg}
33232001f49Smrg
33332001f49Smrgstatic float myrand( float max )
33432001f49Smrg{
33532001f49Smrg   return max*rand()/(RAND_MAX+1.0);
33632001f49Smrg}
33732001f49Smrg
33832001f49Smrg
33932001f49Smrgstatic void make_tri_indices( void )
34032001f49Smrg{
34132001f49Smrg   unsigned int *v = tri_indices;
34232001f49Smrg   unsigned int parity = 0;
34332001f49Smrg   int i, j;
34432001f49Smrg
34532001f49Smrg   for (j=2;j<numverts;j++,parity^=1) {
34632001f49Smrg      if (parity) {
34732001f49Smrg	 *v++ = indices[j-1];
34832001f49Smrg	 *v++ = indices[j-2];
34932001f49Smrg	 *v++ = indices[j];
35032001f49Smrg      } else {
35132001f49Smrg	 *v++ = indices[j-2];
35232001f49Smrg	 *v++ = indices[j-1];
35332001f49Smrg	 *v++ = indices[j];
35432001f49Smrg      }
35532001f49Smrg   }
35632001f49Smrg
35732001f49Smrg   num_tri_verts = v - tri_indices;
35832001f49Smrg   printf("num_tri_verts: %d\n", num_tri_verts);
35932001f49Smrg
36032001f49Smrg   for (i = j = 0 ; i < num_tri_verts ; i += 600, j++) {
36132001f49Smrg      col[j][3] = 1;
36232001f49Smrg      col[j][2] = myrand(1);
36332001f49Smrg      col[j][1] = myrand(1);
36432001f49Smrg      col[j][0] = myrand(1);
36532001f49Smrg   }
36632001f49Smrg
36732001f49Smrg   for (i = 0; i < numverts ; i++)
36832001f49Smrg      strip_indices[i] = i;
36932001f49Smrg}
37032001f49Smrg
37132001f49Smrg#define MIN(x,y) (x < y) ? x : y
37232001f49Smrg
37332001f49Smrgstatic void draw_surface( unsigned int with_state )
37432001f49Smrg{
37532001f49Smrg   GLint i, j;
37632001f49Smrg
37732001f49Smrg   if (with_state & DISPLAYLIST) {
37832001f49Smrg      if ((with_state & (RENDER_STYLE_MASK|PRIMITIVE_MASK|MATERIAL_MASK)) !=
37932001f49Smrg	  dlist_state) {
38032001f49Smrg	 /*
38132001f49Smrg	  */
38232001f49Smrg	 fprintf(stderr, "rebuilding displaylist\n");
38332001f49Smrg
38432001f49Smrg	 if (dlist_state)
38532001f49Smrg	    glDeleteLists( surf1, 1 );
38632001f49Smrg
38732001f49Smrg	 dlist_state = with_state & (RENDER_STYLE_MASK|PRIMITIVE_MASK|
38832001f49Smrg				     MATERIAL_MASK);
38932001f49Smrg	 surf1 = glGenLists(1);
39032001f49Smrg	 glNewList(surf1, GL_COMPILE);
39132001f49Smrg	 draw_surface( dlist_state );
39232001f49Smrg	 glEndList();
39332001f49Smrg      }
39432001f49Smrg
39532001f49Smrg      glCallList( surf1 );
39632001f49Smrg      return;
39732001f49Smrg   }
39832001f49Smrg
39932001f49Smrg   switch (with_state & (RENDER_STYLE_MASK|PRIMITIVE_MASK)) {
40032001f49Smrg
40132001f49Smrg   case (DRAW_ELTS|TRIANGLES):
40232001f49Smrg      if (with_state & MATERIALS) {
40332001f49Smrg	 for (j = i = 0 ; i < num_tri_verts ; i += 600, j++) {
40432001f49Smrg	    GLuint nr = MIN(num_tri_verts-i, 600);
40532001f49Smrg	    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col[j]);
40632001f49Smrg	    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col[j]);
40732001f49Smrg	    glDrawElements( GL_TRIANGLES, nr, GL_UNSIGNED_INT, tri_indices+i );
40832001f49Smrg	 }
40932001f49Smrg      } else {
41032001f49Smrg	 glDrawElements( GL_TRIANGLES, num_tri_verts, GL_UNSIGNED_INT,
41132001f49Smrg			 tri_indices );
41232001f49Smrg      }
41332001f49Smrg      break;
41432001f49Smrg
41532001f49Smrg   case (DRAW_ARRAYS|TRIANGLES):
41632001f49Smrg      glDrawArrays( GL_TRIANGLES, 0, (numverts-2)*3 );
41732001f49Smrg      break;
41832001f49Smrg
41932001f49Smrg   case (ARRAY_ELT|TRIANGLES):
42032001f49Smrg      if (with_state & MATERIALS) {
42132001f49Smrg	 for (j = i = 0 ; i < num_tri_verts ; i += 600, j++) {
42232001f49Smrg	    GLuint nr = MIN(num_tri_verts-i, 600);
42332001f49Smrg	    GLuint k;
42432001f49Smrg	    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col[j]);
42532001f49Smrg	    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col[j]);
42632001f49Smrg	    glBegin( GL_TRIANGLES );
42732001f49Smrg	    for (k = 0 ; k < nr ; k++)
42832001f49Smrg	       glArrayElement( tri_indices[i+k] );
42932001f49Smrg	    glEnd();
43032001f49Smrg	 }
43132001f49Smrg      } else {
43232001f49Smrg	 glBegin( GL_TRIANGLES );
43332001f49Smrg	 for (i = 0 ; i < num_tri_verts ; i++)
43432001f49Smrg	    glArrayElement( tri_indices[i] );
43532001f49Smrg
43632001f49Smrg	 glEnd();
43732001f49Smrg      }
43832001f49Smrg      break;
43932001f49Smrg
44032001f49Smrg
44132001f49Smrg      /* Uses the original arrays (including duplicate elements):
44232001f49Smrg       */
44332001f49Smrg   case (DRAW_ARRAYS|STRIPS):
44432001f49Smrg      glDrawArrays( GL_TRIANGLE_STRIP, 0, numverts );
44532001f49Smrg      break;
44632001f49Smrg   case (DRAW_ELTS|STRIPS):
44732001f49Smrg      glDrawElements( GL_TRIANGLE_STRIP, numverts,
44832001f49Smrg		      GL_UNSIGNED_INT, strip_indices );
44932001f49Smrg      break;
45032001f49Smrg
45132001f49Smrg      /* Uses the original arrays (including duplicate elements):
45232001f49Smrg       */
45332001f49Smrg   case (ARRAY_ELT|STRIPS):
45432001f49Smrg      glBegin( GL_TRIANGLE_STRIP );
45532001f49Smrg      for (i = 0 ; i < numverts ; i++)
45632001f49Smrg	 glArrayElement( i );
45732001f49Smrg      glEnd();
45832001f49Smrg      break;
45932001f49Smrg
46032001f49Smrg   case (DRAW_ARRAYS|POINTS):
46132001f49Smrg      glDrawArrays( GL_POINTS, 0, numuniq );
46232001f49Smrg      break;
46332001f49Smrg   case (DRAW_ELTS|POINTS):
46432001f49Smrg      /* can use numuniq with strip_indices as strip_indices[i] == i.
46532001f49Smrg       */
46632001f49Smrg      glDrawElements( GL_POINTS, numuniq,
46732001f49Smrg		      GL_UNSIGNED_INT, strip_indices );
46832001f49Smrg      break;
46932001f49Smrg   case (ARRAY_ELT|POINTS):
47032001f49Smrg      /* just emit each unique element once:
47132001f49Smrg       */
47232001f49Smrg      glBegin( GL_POINTS );
47332001f49Smrg      for (i = 0 ; i < numuniq ; i++)
47432001f49Smrg	 glArrayElement( i );
47532001f49Smrg      glEnd();
47632001f49Smrg      break;
47732001f49Smrg
47832001f49Smrg   case (GLVERTEX|TRIANGLES):
47932001f49Smrg      if (with_state & MATERIALS) {
48032001f49Smrg	 for (j = i = 0 ; i < num_tri_verts ; i += 600, j++) {
48132001f49Smrg	    GLuint nr = MIN(num_tri_verts-i, 600);
48232001f49Smrg	    GLuint k;
48332001f49Smrg	    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col[j]);
48432001f49Smrg	    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col[j]);
48532001f49Smrg	    glBegin( GL_TRIANGLES );
48632001f49Smrg	    for (k = 0 ; k < nr ; k++) {
48732001f49Smrg	       glNormal3fv( &compressed_data[tri_indices[i+k]][3] );
48832001f49Smrg	       glVertex3fv( &compressed_data[tri_indices[i+k]][0] );
48932001f49Smrg	    }
49032001f49Smrg	    glEnd();
49132001f49Smrg	 }
49232001f49Smrg      } else {
49332001f49Smrg	 glBegin( GL_TRIANGLES );
49432001f49Smrg	 for (i = 0 ; i < num_tri_verts ; i++) {
49532001f49Smrg	    glNormal3fv( &compressed_data[tri_indices[i]][3] );
49632001f49Smrg	    glVertex3fv( &compressed_data[tri_indices[i]][0] );
49732001f49Smrg	 }
49832001f49Smrg	 glEnd();
49932001f49Smrg      }
50032001f49Smrg      break;
50132001f49Smrg
50232001f49Smrg   case (GLVERTEX|POINTS):
50332001f49Smrg      /* Renders all points, but not in strip order...  Shouldn't be a
50432001f49Smrg       * problem, but people may be confused as to why points are so
50532001f49Smrg       * much faster in this demo...  And why cva doesn't help them...
50632001f49Smrg       */
50732001f49Smrg      glBegin( GL_POINTS );
50832001f49Smrg      for ( i = 0 ; i < numuniq ; i++ ) {
50932001f49Smrg         glNormal3fv( &compressed_data[i][3] );
51032001f49Smrg         glVertex3fv( &compressed_data[i][0] );
51132001f49Smrg      }
51232001f49Smrg      glEnd();
51332001f49Smrg      break;
51432001f49Smrg
51532001f49Smrg   case (GLVERTEX|STRIPS):
51632001f49Smrg      if (with_state & MATERIALS) {
51732001f49Smrg         glBegin( GL_TRIANGLE_STRIP );
51832001f49Smrg         for (i=0;i<numverts;i++) {
51932001f49Smrg            if (i % 600 == 0 && i != 0) {
52032001f49Smrg               unsigned j = i / 600;
52132001f49Smrg               glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, col[j]);
52232001f49Smrg               glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col[j]);
52332001f49Smrg            }
52432001f49Smrg            glNormal3fv( &data[i][3] );
52532001f49Smrg            glVertex3fv( &data[i][0] );
52632001f49Smrg         }
52732001f49Smrg         glEnd();
52832001f49Smrg      }
52932001f49Smrg      else {
53032001f49Smrg         glBegin( GL_TRIANGLE_STRIP );
53132001f49Smrg         for (i=0;i<numverts;i++) {
53232001f49Smrg            glNormal3fv( &data[i][3] );
53332001f49Smrg            glVertex3fv( &data[i][0] );
53432001f49Smrg         }
53532001f49Smrg         glEnd();
53632001f49Smrg      }
53732001f49Smrg      break;
53832001f49Smrg
53932001f49Smrg   default:
54032001f49Smrg      fprintf(stderr, "unimplemented mode %x...\n",
54132001f49Smrg	      (with_state & (RENDER_STYLE_MASK|PRIMITIVE_MASK)));
54232001f49Smrg      break;
54332001f49Smrg   }
54432001f49Smrg}
54532001f49Smrg
54632001f49Smrg
54732001f49Smrg
54832001f49Smrgstatic void Display(void)
54932001f49Smrg{
55032001f49Smrg    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
55132001f49Smrg    draw_surface( state );
55232001f49Smrg    glFlush();
55332001f49Smrg    if (doubleBuffer) glutSwapBuffers();
55432001f49Smrg}
55532001f49Smrg
55632001f49Smrg
55732001f49Smrg/* KW: only do this when necessary, so CVA can re-use results.
55832001f49Smrg */
55932001f49Smrgstatic void set_matrix( void )
56032001f49Smrg{
56132001f49Smrg   glMatrixMode(GL_MODELVIEW);
56232001f49Smrg   glLoadIdentity();
56332001f49Smrg   glTranslatef( 0.0, 0.0, dist );
56432001f49Smrg   glRotatef( yrot, 0.0, 1.0, 0.0 );
56532001f49Smrg   glRotatef( xrot, 1.0, 0.0, 0.0 );
56632001f49Smrg}
56732001f49Smrg
56832001f49Smrgstatic void Benchmark( float xdiff, float ydiff )
56932001f49Smrg{
57032001f49Smrg   int startTime, endTime;
57132001f49Smrg   int draws;
57232001f49Smrg   double seconds, fps, triPerSecond;
57332001f49Smrg
57432001f49Smrg   printf("Benchmarking...\n");
57532001f49Smrg
57632001f49Smrg   draws = 0;
57732001f49Smrg   startTime = glutGet(GLUT_ELAPSED_TIME);
57832001f49Smrg   xrot = 0.0;
57932001f49Smrg   do {
58032001f49Smrg      xrot += xdiff;
58132001f49Smrg      yrot += ydiff;
58232001f49Smrg      set_matrix();
58332001f49Smrg      Display();
58432001f49Smrg      draws++;
58532001f49Smrg      endTime = glutGet(GLUT_ELAPSED_TIME);
58632001f49Smrg   } while (endTime - startTime < 5000);   /* 5 seconds */
58732001f49Smrg
58832001f49Smrg   /* Results */
58932001f49Smrg   seconds = (double) (endTime - startTime) / 1000.0;
59032001f49Smrg   triPerSecond = (numverts - 2) * draws / seconds;
59132001f49Smrg   fps = draws / seconds;
59232001f49Smrg   printf("Result:  triangles/sec: %g  fps: %g\n", triPerSecond, fps);
59332001f49Smrg}
59432001f49Smrg
59532001f49Smrg
59632001f49Smrgstatic void InitMaterials(void)
59732001f49Smrg{
59832001f49Smrg    static float ambient[] = {0.1, 0.1, 0.1, 1.0};
59932001f49Smrg    static float diffuse[] = {0.5, 1.0, 1.0, 1.0};
60032001f49Smrg    static float position0[] = {0.0, 0.0, 20.0, 0.0};
60132001f49Smrg    static float position1[] = {0.0, 0.0, -20.0, 0.0};
60232001f49Smrg    static float front_mat_shininess[] = {60.0};
60332001f49Smrg    static float front_mat_specular[] = {0.2, 0.2, 0.2, 1.0};
60432001f49Smrg    static float front_mat_diffuse[] = {0.5, 0.28, 0.38, 1.0};
60532001f49Smrg    /*
60632001f49Smrg    static float back_mat_shininess[] = {60.0};
60732001f49Smrg    static float back_mat_specular[] = {0.5, 0.5, 0.2, 1.0};
60832001f49Smrg    static float back_mat_diffuse[] = {1.0, 1.0, 0.2, 1.0};
60932001f49Smrg    */
61032001f49Smrg    static float lmodel_ambient[] = {1.0, 1.0, 1.0, 1.0};
61132001f49Smrg    static float lmodel_twoside[] = {GL_FALSE};
61232001f49Smrg
61332001f49Smrg    glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
61432001f49Smrg    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
61532001f49Smrg    glLightfv(GL_LIGHT0, GL_POSITION, position0);
61632001f49Smrg    glEnable(GL_LIGHT0);
61732001f49Smrg
61832001f49Smrg    glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
61932001f49Smrg    glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
62032001f49Smrg    glLightfv(GL_LIGHT1, GL_POSITION, position1);
62132001f49Smrg    glEnable(GL_LIGHT1);
62232001f49Smrg
62332001f49Smrg    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
62432001f49Smrg    glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
62532001f49Smrg
62632001f49Smrg    glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_mat_shininess);
62732001f49Smrg    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_mat_specular);
62832001f49Smrg    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, front_mat_diffuse);
62932001f49Smrg
63032001f49Smrg    glPolygonStipple (halftone);
63132001f49Smrg}
63232001f49Smrg
63332001f49Smrg
63432001f49Smrg
63532001f49Smrg#define UPDATE(o,n,mask) (o&=~mask, o|=n&mask)
63632001f49Smrg#define CHANGED(o,n,mask) ((n&mask) && (n&mask) != (o&mask) )
63732001f49Smrg
63832001f49Smrgstatic void ModeMenu(int m)
63932001f49Smrg{
64032001f49Smrg   m &= allowed;
64132001f49Smrg
64232001f49Smrg   if (!m) return;
64332001f49Smrg
64432001f49Smrg   if (m==QUIT)
64532001f49Smrg      exit(0);
64632001f49Smrg
64732001f49Smrg   if (m==GLINFO) {
64832001f49Smrg      printf("GL_VERSION: %s\n", (char *) glGetString(GL_VERSION));
64932001f49Smrg      printf("GL_EXTENSIONS: %s\n", (char *) glGetString(GL_EXTENSIONS));
65032001f49Smrg      printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER));
65132001f49Smrg      return;
65232001f49Smrg   }
65332001f49Smrg
65432001f49Smrg   if (CHANGED(state, m, FILTER_MASK)) {
65532001f49Smrg      UPDATE(state, m, FILTER_MASK);
65632001f49Smrg      if (m & LINEAR_FILTER) {
65732001f49Smrg	 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
65832001f49Smrg	 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
65932001f49Smrg      } else {
66032001f49Smrg	 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
66132001f49Smrg	 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
66232001f49Smrg      }
66332001f49Smrg   }
66432001f49Smrg
66532001f49Smrg   if (CHANGED(state, m, LIGHT_MASK)) {
66632001f49Smrg      UPDATE(state, m, LIGHT_MASK);
66732001f49Smrg      if (m & LIT) {
66832001f49Smrg	 glEnable(GL_LIGHTING);
66932001f49Smrg	 glDisable(GL_TEXTURE_GEN_S);
67032001f49Smrg	 glDisable(GL_TEXTURE_GEN_T);
67132001f49Smrg	 glDisable(GL_TEXTURE_2D);
67232001f49Smrg      }
67332001f49Smrg      else if (m & UNLIT) {
67432001f49Smrg	 glDisable(GL_LIGHTING);
67532001f49Smrg	 glDisable(GL_TEXTURE_GEN_S);
67632001f49Smrg	 glDisable(GL_TEXTURE_GEN_T);
67732001f49Smrg	 glDisable(GL_TEXTURE_2D);
67832001f49Smrg      }
67932001f49Smrg      else if (m & REFLECT) {
68032001f49Smrg	 glDisable(GL_LIGHTING);
68132001f49Smrg	 glEnable(GL_TEXTURE_GEN_S);
68232001f49Smrg	 glEnable(GL_TEXTURE_GEN_T);
68332001f49Smrg	 glEnable(GL_TEXTURE_2D);
68432001f49Smrg      }
68532001f49Smrg   }
68632001f49Smrg
68732001f49Smrg   if (CHANGED(state, m, SHADE_MASK)) {
68832001f49Smrg      UPDATE(state, m, SHADE_MASK);
68932001f49Smrg      if (m & SHADE_SMOOTH)
69032001f49Smrg	 glShadeModel(GL_SMOOTH);
69132001f49Smrg      else
69232001f49Smrg	 glShadeModel(GL_FLAT);
69332001f49Smrg   }
69432001f49Smrg
69532001f49Smrg
69632001f49Smrg   if (CHANGED(state, m, CLIP_MASK)) {
69732001f49Smrg      UPDATE(state, m, CLIP_MASK);
69832001f49Smrg      if (m & USER_CLIP) {
69932001f49Smrg	 glEnable(GL_CLIP_PLANE0);
70032001f49Smrg      } else {
70132001f49Smrg	 glDisable(GL_CLIP_PLANE0);
70232001f49Smrg      }
70332001f49Smrg   }
70432001f49Smrg
70532001f49Smrg   if (CHANGED(state, m, FOG_MASK)) {
70632001f49Smrg      UPDATE(state, m, FOG_MASK);
70732001f49Smrg      if (m & FOG) {
70832001f49Smrg	 glEnable(GL_FOG);
70932001f49Smrg      }
71032001f49Smrg      else {
71132001f49Smrg	 glDisable(GL_FOG);
71232001f49Smrg      }
71332001f49Smrg   }
71432001f49Smrg
71532001f49Smrg   if (CHANGED(state, m, STIPPLE_MASK)) {
71632001f49Smrg      UPDATE(state, m, STIPPLE_MASK);
71732001f49Smrg      if (m & STIPPLE) {
71832001f49Smrg	 glEnable(GL_POLYGON_STIPPLE);
71932001f49Smrg      }
72032001f49Smrg      else {
72132001f49Smrg	 glDisable(GL_POLYGON_STIPPLE);
72232001f49Smrg      }
72332001f49Smrg   }
72432001f49Smrg
72532001f49Smrg   if (CHANGED(state, m, POLYGON_MASK)) {
72632001f49Smrg      UPDATE(state, m, POLYGON_MASK);
72732001f49Smrg      if (m & POLYGON_FILL) {
72832001f49Smrg	 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
72932001f49Smrg      }
73032001f49Smrg      else if (m & POLYGON_LINE) {
73132001f49Smrg	 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
73232001f49Smrg      }
73332001f49Smrg      else {
73432001f49Smrg	 glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
73532001f49Smrg      }
73632001f49Smrg   }
73732001f49Smrg
73832001f49Smrg   if (CHANGED(state, m, (LOCK_MASK|RENDER_STYLE_MASK|PRIMITIVE_MASK)))
73932001f49Smrg   {
74032001f49Smrg      if (m & (PRIMITIVE_MASK)) {
74132001f49Smrg	 UPDATE(state, m, (PRIMITIVE_MASK));
74232001f49Smrg      }
74332001f49Smrg
74432001f49Smrg      if (m & (RENDER_STYLE_MASK)) {
74532001f49Smrg	 UPDATE(state, m, (RENDER_STYLE_MASK));
74632001f49Smrg      }
74732001f49Smrg
74832001f49Smrg      if (m & LOCK_MASK) {
74932001f49Smrg	 UPDATE(state, m, (LOCK_MASK));
75032001f49Smrg      }
75132001f49Smrg
75232001f49Smrg
75332001f49Smrg      print_flags("primitive", state & PRIMITIVE_MASK);
75432001f49Smrg      print_flags("render style", state & RENDER_STYLE_MASK);
75532001f49Smrg
75632001f49Smrg      if ((state & PRIMITIVE_MASK) != STRIPS &&
75732001f49Smrg	  ((state & RENDER_STYLE_MASK) == DRAW_ELTS ||
75832001f49Smrg	   (state & RENDER_STYLE_MASK) == ARRAY_ELT ||
75932001f49Smrg	   (state & PRIMITIVE_MASK) == POINTS))
76032001f49Smrg      {
76132001f49Smrg	 fprintf(stderr, "enabling small arrays\n");
76232001f49Smrg	 /* Rendering any primitive with draw-element/array-element
76332001f49Smrg	  *  --> Can't do strips here as ordering has been lost in
76432001f49Smrg	  *  compaction process...
76532001f49Smrg	  */
76632001f49Smrg	 glVertexPointer( 3, GL_FLOAT, sizeof(data[0]), compressed_data );
76732001f49Smrg	 glNormalPointer( GL_FLOAT, sizeof(data[0]), &compressed_data[0][3] );
76832001f49Smrg#ifdef GL_EXT_compiled_vertex_array
76932001f49Smrg	 if (allowed & LOCKED) {
77032001f49Smrg	    if (state & LOCKED) {
77132001f49Smrg	       glLockArraysEXT( 0, numuniq );
77232001f49Smrg	    } else {
77332001f49Smrg	       glUnlockArraysEXT();
77432001f49Smrg	    }
77532001f49Smrg	 }
77632001f49Smrg#endif
77732001f49Smrg      }
77832001f49Smrg      else if ((state & PRIMITIVE_MASK) == TRIANGLES &&
77932001f49Smrg	       (state & RENDER_STYLE_MASK) == DRAW_ARRAYS) {
78032001f49Smrg	 fprintf(stderr, "enabling big arrays\n");
78132001f49Smrg	 /* Only get here for TRIANGLES and drawarrays
78232001f49Smrg	  */
78332001f49Smrg	 glVertexPointer( 3, GL_FLOAT, sizeof(data[0]), expanded_data );
78432001f49Smrg	 glNormalPointer( GL_FLOAT, sizeof(data[0]), &expanded_data[0][3] );
78532001f49Smrg
78632001f49Smrg#ifdef GL_EXT_compiled_vertex_array
78732001f49Smrg	 if (allowed & LOCKED) {
78832001f49Smrg	    if (state & LOCKED) {
78932001f49Smrg	       glLockArraysEXT( 0, (numverts-2)*3 );
79032001f49Smrg	    } else {
79132001f49Smrg	       glUnlockArraysEXT();
79232001f49Smrg	    }
79332001f49Smrg	 }
79432001f49Smrg#endif
79532001f49Smrg      }
79632001f49Smrg      else {
79732001f49Smrg	 fprintf(stderr, "enabling normal arrays\n");
79832001f49Smrg	 glVertexPointer( 3, GL_FLOAT, sizeof(data[0]), data );
79932001f49Smrg	 glNormalPointer( GL_FLOAT, sizeof(data[0]), &data[0][3] );
80032001f49Smrg#ifdef GL_EXT_compiled_vertex_array
80132001f49Smrg	 if (allowed & LOCKED) {
80232001f49Smrg	    if (state & LOCKED) {
80332001f49Smrg	       glLockArraysEXT( 0, numverts );
80432001f49Smrg	    } else {
80532001f49Smrg	       glUnlockArraysEXT();
80632001f49Smrg	    }
80732001f49Smrg	 }
80832001f49Smrg#endif
80932001f49Smrg      }
81032001f49Smrg
81132001f49Smrg   }
81232001f49Smrg
81332001f49Smrg
81432001f49Smrg   if (m & DLIST_MASK) {
81532001f49Smrg      UPDATE(state, m, DLIST_MASK);
81632001f49Smrg   }
81732001f49Smrg
81832001f49Smrg   if (m & MATERIAL_MASK) {
81932001f49Smrg      UPDATE(state, m, MATERIAL_MASK);
82032001f49Smrg   }
82132001f49Smrg
82232001f49Smrg   print_flags("new flags", state);
82332001f49Smrg
82432001f49Smrg   glutPostRedisplay();
82532001f49Smrg}
82632001f49Smrg
82732001f49Smrg
82832001f49Smrg
82932001f49Smrgstatic void Init(int argc, char *argv[])
83032001f49Smrg{
83132001f49Smrg   GLfloat fogColor[4] = {0.5,1.0,0.5,1.0};
83232001f49Smrg
83332001f49Smrg   xrot = 0;
83432001f49Smrg   yrot = 0;
83532001f49Smrg   dist = -6;
83632001f49Smrg   plane[0] = 1.0;
83732001f49Smrg   plane[1] = 0.0;
83832001f49Smrg   plane[2] = -1.0;
83932001f49Smrg   plane[3] = 0.0;
84032001f49Smrg
84132001f49Smrg   glClearColor(0.0, 0.0, 1.0, 0.0);
84232001f49Smrg   glEnable( GL_DEPTH_TEST );
84332001f49Smrg   glEnableClientState( GL_VERTEX_ARRAY );
84432001f49Smrg   glEnableClientState( GL_NORMAL_ARRAY );
84532001f49Smrg
84632001f49Smrg   glMatrixMode(GL_PROJECTION);
84732001f49Smrg   glLoadIdentity();
84832001f49Smrg   glFrustum( -1.0, 1.0, -1.0, 1.0, 5, 25 );
84932001f49Smrg
85032001f49Smrg   glMatrixMode(GL_MODELVIEW);
85132001f49Smrg   glLoadIdentity();
85232001f49Smrg   glClipPlane(GL_CLIP_PLANE0, plane);
85332001f49Smrg
85432001f49Smrg   InitMaterials();
85532001f49Smrg
85632001f49Smrg   set_matrix();
85732001f49Smrg
85832001f49Smrg   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
85932001f49Smrg   glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
86032001f49Smrg
86132001f49Smrg   glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
86232001f49Smrg   glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
86332001f49Smrg
86432001f49Smrg
86532001f49Smrg   /* Green fog is easy to see */
86632001f49Smrg   glFogi(GL_FOG_MODE,GL_EXP2);
86732001f49Smrg   glFogfv(GL_FOG_COLOR,fogColor);
86832001f49Smrg   glFogf(GL_FOG_DENSITY,0.15);
86932001f49Smrg   glHint(GL_FOG_HINT,GL_DONT_CARE);
87032001f49Smrg
87132001f49Smrg   {
87232001f49Smrg      static int firsttime = 1;
87332001f49Smrg      if (firsttime) {
87432001f49Smrg	 firsttime = 0;
87532001f49Smrg	 compactify_arrays();
87632001f49Smrg	 expand_arrays();
87732001f49Smrg	 make_tri_indices();
87832001f49Smrg
87932001f49Smrg	 if (!LoadRGBMipmaps(TEXTURE_FILE, GL_RGB)) {
88032001f49Smrg	    printf("Error: couldn't load texture image\n");
88132001f49Smrg	    exit(1);
88232001f49Smrg	 }
88332001f49Smrg      }
88432001f49Smrg   }
88532001f49Smrg
88632001f49Smrg   ModeMenu(SHADE_SMOOTH|
88732001f49Smrg	    LIT|
88832001f49Smrg	    POINT_FILTER|
88932001f49Smrg	    NO_USER_CLIP|
89032001f49Smrg	    NO_MATERIALS|
89132001f49Smrg	    NO_FOG|
89232001f49Smrg	    NO_STIPPLE|
89332001f49Smrg	    IMMEDIATE|
89432001f49Smrg	    STRIPS|
89532001f49Smrg	    UNLOCKED|
89632001f49Smrg	    GLVERTEX);
89732001f49Smrg
89832001f49Smrg   if (PrintInfo) {
89932001f49Smrg      printf("GL_RENDERER   = %s\n", (char *) glGetString(GL_RENDERER));
90032001f49Smrg      printf("GL_VERSION    = %s\n", (char *) glGetString(GL_VERSION));
90132001f49Smrg      printf("GL_VENDOR     = %s\n", (char *) glGetString(GL_VENDOR));
90232001f49Smrg      printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
90332001f49Smrg   }
90432001f49Smrg}
90532001f49Smrg
90632001f49Smrg
90732001f49Smrg
90832001f49Smrgstatic void Reshape(int width, int height)
90932001f49Smrg{
91032001f49Smrg    glViewport(0, 0, (GLint)width, (GLint)height);
91132001f49Smrg}
91232001f49Smrg
91332001f49Smrg
91432001f49Smrg
91532001f49Smrgstatic void Key( unsigned char key, int x, int y )
91632001f49Smrg{
91732001f49Smrg   (void) x;
91832001f49Smrg   (void) y;
91932001f49Smrg   switch (key) {
92032001f49Smrg   case 27:
92132001f49Smrg      exit(0);
92232001f49Smrg   case 'f':
92332001f49Smrg      ModeMenu((state ^ FOG_MASK) & FOG_MASK);
92432001f49Smrg      break;
92532001f49Smrg   case 's':
92632001f49Smrg      ModeMenu((state ^ SHADE_MASK) & SHADE_MASK);
92732001f49Smrg      break;
92832001f49Smrg   case 't':
92932001f49Smrg      ModeMenu((state ^ STIPPLE_MASK) & STIPPLE_MASK);
93032001f49Smrg      break;
93132001f49Smrg   case 'l':
93232001f49Smrg      ModeMenu((state ^ LIGHT_MASK) & (LIT|UNLIT));
93332001f49Smrg      break;
93432001f49Smrg   case 'm':
93532001f49Smrg      ModeMenu((state ^ MATERIAL_MASK) & MATERIAL_MASK);
93632001f49Smrg      break;
93732001f49Smrg   case 'c':
93832001f49Smrg      ModeMenu((state ^ CLIP_MASK) & CLIP_MASK);
93932001f49Smrg      break;
94032001f49Smrg   case 'v':
94132001f49Smrg      ModeMenu((LOCKED|IMMEDIATE|DRAW_ELTS|TRIANGLES) & allowed);
94232001f49Smrg      break;
94332001f49Smrg   case 'V':
94432001f49Smrg      ModeMenu(UNLOCKED|IMMEDIATE|GLVERTEX|STRIPS);
94532001f49Smrg      break;
94632001f49Smrg   case 'b':
94732001f49Smrg      Benchmark(5.0, 0);
94832001f49Smrg      break;
94932001f49Smrg   case 'B':
95032001f49Smrg      Benchmark(0, 5.0);
95132001f49Smrg      break;
95232001f49Smrg   case 'i':
95332001f49Smrg      dist += .25;
95432001f49Smrg      set_matrix();
95532001f49Smrg      glutPostRedisplay();
95632001f49Smrg      break;
95732001f49Smrg   case 'I':
95832001f49Smrg      dist -= .25;
95932001f49Smrg      set_matrix();
96032001f49Smrg      glutPostRedisplay();
96132001f49Smrg      break;
96232001f49Smrg   case '-':
96332001f49Smrg   case '_':
96432001f49Smrg      plane[3] += 0.5;
96532001f49Smrg      glMatrixMode(GL_MODELVIEW);
96632001f49Smrg      glLoadIdentity();
96732001f49Smrg      glClipPlane(GL_CLIP_PLANE0, plane);
96832001f49Smrg      set_matrix();
96932001f49Smrg      glutPostRedisplay();
97032001f49Smrg      break;
97132001f49Smrg   case '+':
97232001f49Smrg   case '=':
97332001f49Smrg      plane[3] -= 0.5;
97432001f49Smrg      glMatrixMode(GL_MODELVIEW);
97532001f49Smrg      glLoadIdentity();
97632001f49Smrg      glClipPlane(GL_CLIP_PLANE0, plane);
97732001f49Smrg      set_matrix();
97832001f49Smrg      glutPostRedisplay();
97932001f49Smrg      break;
98032001f49Smrg   case ' ':
98132001f49Smrg      Init(0,0);
98232001f49Smrg      break;
98332001f49Smrg   }
98432001f49Smrg}
98532001f49Smrg
98632001f49Smrg
98732001f49Smrgstatic void SpecialKey( int key, int x, int y )
98832001f49Smrg{
98932001f49Smrg   (void) x;
99032001f49Smrg   (void) y;
99132001f49Smrg   switch (key) {
99232001f49Smrg   case GLUT_KEY_LEFT:
99332001f49Smrg      yrot -= 15.0;
99432001f49Smrg      break;
99532001f49Smrg   case GLUT_KEY_RIGHT:
99632001f49Smrg      yrot += 15.0;
99732001f49Smrg      break;
99832001f49Smrg   case GLUT_KEY_UP:
99932001f49Smrg      xrot += 15.0;
100032001f49Smrg      break;
100132001f49Smrg   case GLUT_KEY_DOWN:
100232001f49Smrg      xrot -= 15.0;
100332001f49Smrg      break;
100432001f49Smrg   default:
100532001f49Smrg      return;
100632001f49Smrg   }
100732001f49Smrg   set_matrix();
100832001f49Smrg   glutPostRedisplay();
100932001f49Smrg}
101032001f49Smrg
101132001f49Smrg
101232001f49Smrg
101332001f49Smrgstatic GLint Args(int argc, char **argv)
101432001f49Smrg{
101532001f49Smrg   GLint i;
101632001f49Smrg   GLint mode = 0;
101732001f49Smrg
101832001f49Smrg   for (i = 1; i < argc; i++) {
101932001f49Smrg      if (strcmp(argv[i], "-sb") == 0) {
102032001f49Smrg         doubleBuffer = GL_FALSE;
102132001f49Smrg      }
102232001f49Smrg      else if (strcmp(argv[i], "-db") == 0) {
102332001f49Smrg         doubleBuffer = GL_TRUE;
102432001f49Smrg      }
102532001f49Smrg      else if (strcmp(argv[i], "-info") == 0) {
102632001f49Smrg         PrintInfo = GL_TRUE;
102732001f49Smrg      }
102832001f49Smrg      else if (strcmp(argv[i], "-10") == 0) {
102932001f49Smrg         maxverts = 10;
103032001f49Smrg      }
103132001f49Smrg      else if (strcmp(argv[i], "-100") == 0) {
103232001f49Smrg	 maxverts = 100;
103332001f49Smrg      }
103432001f49Smrg      else if (strcmp(argv[i], "-1000") == 0) {
103532001f49Smrg	 maxverts = 1000;
103632001f49Smrg      }
103732001f49Smrg      else {
103832001f49Smrg         printf("%s (Bad option).\n", argv[i]);
103932001f49Smrg	 return QUIT;
104032001f49Smrg      }
104132001f49Smrg   }
104232001f49Smrg
104332001f49Smrg   return mode;
104432001f49Smrg}
104532001f49Smrg
104632001f49Smrgint main(int argc, char **argv)
104732001f49Smrg{
104832001f49Smrg   GLenum type;
104932001f49Smrg
105032001f49Smrg   GLuint arg_mode = Args(argc, argv);
105132001f49Smrg
105232001f49Smrg   if (arg_mode & QUIT)
105332001f49Smrg      exit(0);
105432001f49Smrg
105532001f49Smrg   read_surface(DEMOS_DATA_DIR "isosurf.dat");
105632001f49Smrg
105732001f49Smrg   glutInitWindowSize(400, 400);
105832001f49Smrg   glutInit( &argc, argv);
105932001f49Smrg
106032001f49Smrg   type = GLUT_DEPTH;
106132001f49Smrg   type |= GLUT_RGB;
106232001f49Smrg   type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
106332001f49Smrg   glutInitDisplayMode(type);
106432001f49Smrg
106532001f49Smrg   if (glutCreateWindow("Isosurface") <= 0) {
106632001f49Smrg      exit(0);
106732001f49Smrg   }
106832001f49Smrg
106932001f49Smrg   glewInit();
107032001f49Smrg
107132001f49Smrg   /* Make sure server supports vertex arrays */
107232001f49Smrg   if (!GLEW_VERSION_1_1)
107332001f49Smrg   {
107432001f49Smrg      printf("Vertex arrays not supported by this renderer\n");
107532001f49Smrg      allowed &= ~(LOCKED|DRAW_ARRAYS|DRAW_ELTS|ARRAY_ELT);
107632001f49Smrg   }
107732001f49Smrg   else if (!GLEW_EXT_compiled_vertex_array)
107832001f49Smrg   {
107932001f49Smrg      printf("Compiled vertex arrays not supported by this renderer\n");
108032001f49Smrg      allowed &= ~LOCKED;
108132001f49Smrg   }
108232001f49Smrg
108332001f49Smrg   Init(argc, argv);
108432001f49Smrg   ModeMenu(arg_mode);
108532001f49Smrg
108632001f49Smrg   glutCreateMenu(ModeMenu);
108732001f49Smrg   glutAddMenuEntry("GL info",               GLINFO);
108832001f49Smrg   glutAddMenuEntry("", 0);
108932001f49Smrg   glutAddMenuEntry("Lit",                   LIT);
109032001f49Smrg   glutAddMenuEntry("Unlit",                 UNLIT);
109132001f49Smrg   glutAddMenuEntry("Reflect",               REFLECT);
109232001f49Smrg   glutAddMenuEntry("", 0);
109332001f49Smrg   glutAddMenuEntry("Smooth",                SHADE_SMOOTH);
109432001f49Smrg   glutAddMenuEntry("Flat",                  SHADE_FLAT);
109532001f49Smrg   glutAddMenuEntry("", 0);
109632001f49Smrg   glutAddMenuEntry("Fog",                   FOG);
109732001f49Smrg   glutAddMenuEntry("No Fog",                NO_FOG);
109832001f49Smrg   glutAddMenuEntry("", 0);
109932001f49Smrg   glutAddMenuEntry("Stipple",               STIPPLE);
110032001f49Smrg   glutAddMenuEntry("No Stipple",            NO_STIPPLE);
110132001f49Smrg   glutAddMenuEntry("", 0);
110232001f49Smrg   glutAddMenuEntry("Polygon Mode Fill",     POLYGON_FILL);
110332001f49Smrg   glutAddMenuEntry("Polygon Mode Line",     POLYGON_LINE);
110432001f49Smrg   glutAddMenuEntry("Polygon Mode Points",   POLYGON_POINT);
110532001f49Smrg   glutAddMenuEntry("", 0);
110632001f49Smrg   glutAddMenuEntry("Point Filtered",        POINT_FILTER);
110732001f49Smrg   glutAddMenuEntry("Linear Filtered",       LINEAR_FILTER);
110832001f49Smrg   glutAddMenuEntry("", 0);
110932001f49Smrg   glutAddMenuEntry("GL_TRIANGLES",          TRIANGLES);
111032001f49Smrg   glutAddMenuEntry("GL_TRIANGLE_STRIPS",    STRIPS);
111132001f49Smrg   glutAddMenuEntry("GL_POINTS",             POINTS);
111232001f49Smrg   glutAddMenuEntry("", 0);
111332001f49Smrg   glutAddMenuEntry("Displaylist",           DISPLAYLIST);
111432001f49Smrg   glutAddMenuEntry("Immediate",             IMMEDIATE);
111532001f49Smrg   glutAddMenuEntry("", 0);
111632001f49Smrg   if (allowed & LOCKED) {
111732001f49Smrg      glutAddMenuEntry("Locked Arrays (CVA)", LOCKED);
111832001f49Smrg      glutAddMenuEntry("Unlocked Arrays",     UNLOCKED);
111932001f49Smrg      glutAddMenuEntry("", 0);
112032001f49Smrg   }
112132001f49Smrg   glutAddMenuEntry("glVertex",               GLVERTEX);
112232001f49Smrg   if (allowed & DRAW_ARRAYS) {
112332001f49Smrg      glutAddMenuEntry("glDrawElements",      DRAW_ELTS);
112432001f49Smrg      glutAddMenuEntry("glDrawArrays",	      DRAW_ARRAYS);
112532001f49Smrg      glutAddMenuEntry("glArrayElement",      ARRAY_ELT);
112632001f49Smrg   }
112732001f49Smrg   glutAddMenuEntry("", 0);
112832001f49Smrg   glutAddMenuEntry("Quit",                   QUIT);
112932001f49Smrg   glutAttachMenu(GLUT_RIGHT_BUTTON);
113032001f49Smrg
113132001f49Smrg   glutReshapeFunc(Reshape);
113232001f49Smrg   glutKeyboardFunc(Key);
113332001f49Smrg   glutSpecialFunc(SpecialKey);
113432001f49Smrg   glutDisplayFunc(Display);
113532001f49Smrg
113632001f49Smrg   glutMainLoop();
113732001f49Smrg   return 0;
113832001f49Smrg}
1139