home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / System / Mesa-3.1 / demos / isosurf.c < prev    next >
C/C++ Source or Header  |  2000-01-07  |  23KB  |  934 lines

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