132001f49Smrg/*
232001f49Smrg * Test vertex arrays with GL_NV_vertex_program
332001f49Smrg *
432001f49Smrg * Based on a stripped-down version of the isosurf demo.
532001f49Smrg * The vertex program is trivial: compute the resulting
632001f49Smrg * RGB color as a linear function of vertex XYZ.
732001f49Smrg */
832001f49Smrg
932001f49Smrg#include <assert.h>
1032001f49Smrg#include <stdio.h>
1132001f49Smrg#include <stdlib.h>
1232001f49Smrg#include <string.h>
1332001f49Smrg#include <math.h>
1432001f49Smrg#include "GL/glew.h"
1532001f49Smrg#include "glut_wrap.h"
1632001f49Smrg
1732001f49Smrg#define MAXVERTS 10000
1832001f49Smrgstatic float data[MAXVERTS][6];
1932001f49Smrgstatic GLint numverts;
2032001f49Smrg
2132001f49Smrgstatic GLfloat xrot;
2232001f49Smrgstatic GLfloat yrot;
2332001f49Smrgstatic GLboolean useArrays = GL_TRUE;
2432001f49Smrgstatic GLboolean useProgram = GL_TRUE;
2532001f49Smrgstatic GLboolean useList = GL_FALSE;
2632001f49Smrg
2732001f49Smrg
2832001f49Smrgstatic void read_surface( char *filename )
2932001f49Smrg{
3032001f49Smrg   FILE *f;
3132001f49Smrg
3232001f49Smrg   f = fopen(filename,"r");
3332001f49Smrg   if (!f) {
3432001f49Smrg      printf("couldn't read %s\n", filename);
3532001f49Smrg      exit(1);
3632001f49Smrg   }
3732001f49Smrg
3832001f49Smrg   numverts = 0;
3932001f49Smrg   while (numverts < MAXVERTS) {
4032001f49Smrg      int result;
4132001f49Smrg      result = fscanf( f, "%f %f %f  %f %f %f",
4232001f49Smrg	               &data[numverts][0], &data[numverts][1], &data[numverts][2],
4332001f49Smrg	               &data[numverts][3], &data[numverts][4], &data[numverts][5] );
4432001f49Smrg      if (result == EOF) {
4532001f49Smrg         break;
4632001f49Smrg      }
4732001f49Smrg      numverts++;
4832001f49Smrg   }
4932001f49Smrg
5032001f49Smrg   printf("%d vertices, %d triangles\n", numverts, numverts-2);
5132001f49Smrg   printf("data = %p\n", (void *) data);
5232001f49Smrg   fclose(f);
5332001f49Smrg}
5432001f49Smrg
5532001f49Smrg
5632001f49Smrg
5732001f49Smrg
5832001f49Smrgstatic void Display(void)
5932001f49Smrg{
6032001f49Smrg   if (useProgram)
6132001f49Smrg      glEnable(GL_VERTEX_PROGRAM_NV);
6232001f49Smrg   else
6332001f49Smrg      glDisable(GL_VERTEX_PROGRAM_NV);
6432001f49Smrg
6532001f49Smrg   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
6632001f49Smrg
6732001f49Smrg   glPushMatrix();
6832001f49Smrg      glRotatef(xrot, 1, 0, 0);
6932001f49Smrg      glRotatef(yrot, 0, 1, 0);
7032001f49Smrg      glScalef(2, 2, 2);
7132001f49Smrg      if (useArrays) {
7232001f49Smrg         if (useProgram) {
7332001f49Smrg            glVertexAttribPointerNV( 0, 3, GL_FLOAT, 6 * sizeof(GLfloat), data );
7432001f49Smrg            glEnableClientState( GL_VERTEX_ATTRIB_ARRAY0_NV );
7532001f49Smrg            glVertexAttribPointerNV( 2, 3, GL_FLOAT, 6 * sizeof(GLfloat), ((GLfloat *) data) + 3);
7632001f49Smrg            glEnableClientState( GL_VERTEX_ATTRIB_ARRAY2_NV);
7732001f49Smrg         }
7832001f49Smrg         else {
7932001f49Smrg            glVertexPointer( 3, GL_FLOAT, 6 * sizeof(GLfloat), data );
8032001f49Smrg            glEnableClientState( GL_VERTEX_ARRAY );
8132001f49Smrg            glNormalPointer( GL_FLOAT, 6 * sizeof(GLfloat), ((GLfloat *) data) + 3);
8232001f49Smrg            glEnableClientState( GL_NORMAL_ARRAY );
8332001f49Smrg         }
8432001f49Smrg
8532001f49Smrg         if (useList) {
8632001f49Smrg            /* dumb, but a good test */
8732001f49Smrg            glNewList(1, GL_COMPILE);
8832001f49Smrg            glDrawArrays(GL_TRIANGLE_STRIP, 0, numverts);
8932001f49Smrg            glEndList();
9032001f49Smrg            glCallList(1);
9132001f49Smrg         }
9232001f49Smrg         else {
9332001f49Smrg            glDrawArrays(GL_TRIANGLE_STRIP, 0, numverts);
9432001f49Smrg         }
9532001f49Smrg
9632001f49Smrg         glDisableClientState( GL_VERTEX_ATTRIB_ARRAY0_NV );
9732001f49Smrg         glDisableClientState( GL_VERTEX_ATTRIB_ARRAY2_NV);
9832001f49Smrg         glDisableClientState( GL_VERTEX_ARRAY );
9932001f49Smrg         glDisableClientState( GL_NORMAL_ARRAY );
10032001f49Smrg      }
10132001f49Smrg      else {
10232001f49Smrg         int i;
10332001f49Smrg         glBegin(GL_TRIANGLE_STRIP);
10432001f49Smrg         for (i = 0; i < numverts; i++) {
10532001f49Smrg            glNormal3fv( data[i] + 3 );
10632001f49Smrg            glVertex3fv( data[i] + 0 );
10732001f49Smrg         }
10832001f49Smrg         glEnd();
10932001f49Smrg      }
11032001f49Smrg   glPopMatrix();
11132001f49Smrg
11232001f49Smrg   if (glGetError())
11332001f49Smrg      printf("Error!\n");
11432001f49Smrg
11532001f49Smrg   glutSwapBuffers();
11632001f49Smrg}
11732001f49Smrg
11832001f49Smrg
11932001f49Smrgstatic void InitMaterials(void)
12032001f49Smrg{
12132001f49Smrg    static float ambient[] = {0.1, 0.1, 0.1, 1.0};
12232001f49Smrg    static float diffuse[] = {0.5, 1.0, 1.0, 1.0};
12332001f49Smrg    static float position0[] = {0.0, 0.0, 20.0, 0.0};
12432001f49Smrg    static float position1[] = {0.0, 0.0, -20.0, 0.0};
12532001f49Smrg    static float front_mat_shininess[] = {60.0};
12632001f49Smrg    static float front_mat_specular[] = {0.2, 0.2, 0.2, 1.0};
12732001f49Smrg    static float front_mat_diffuse[] = {0.5, 0.28, 0.38, 1.0};
12832001f49Smrg    /*
12932001f49Smrg    static float back_mat_shininess[] = {60.0};
13032001f49Smrg    static float back_mat_specular[] = {0.5, 0.5, 0.2, 1.0};
13132001f49Smrg    static float back_mat_diffuse[] = {1.0, 1.0, 0.2, 1.0};
13232001f49Smrg    */
13332001f49Smrg    static float lmodel_ambient[] = {1.0, 1.0, 1.0, 1.0};
13432001f49Smrg    static float lmodel_twoside[] = {GL_FALSE};
13532001f49Smrg
13632001f49Smrg    glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
13732001f49Smrg    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
13832001f49Smrg    glLightfv(GL_LIGHT0, GL_POSITION, position0);
13932001f49Smrg    glEnable(GL_LIGHT0);
14032001f49Smrg
14132001f49Smrg    glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
14232001f49Smrg    glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
14332001f49Smrg    glLightfv(GL_LIGHT1, GL_POSITION, position1);
14432001f49Smrg    glEnable(GL_LIGHT1);
14532001f49Smrg
14632001f49Smrg    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
14732001f49Smrg    glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
14832001f49Smrg
14932001f49Smrg    glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_mat_shininess);
15032001f49Smrg    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_mat_specular);
15132001f49Smrg    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, front_mat_diffuse);
15232001f49Smrg    glEnable(GL_LIGHTING);
15332001f49Smrg}
15432001f49Smrg
15532001f49Smrg
15632001f49Smrgstatic void init_program(void)
15732001f49Smrg{
15832001f49Smrg   /*
15932001f49Smrg    * c[0..3] = modelview matrix
16032001f49Smrg    * c[4..7] = inverse modelview matrix
16132001f49Smrg    * c[30] = color scale
16232001f49Smrg    * c[31] = color bias
16332001f49Smrg    */
16432001f49Smrg   static const char prog[] =
16532001f49Smrg      "!!VP1.0\n"
16632001f49Smrg
16732001f49Smrg      "# RGB is proportional to XYZ \n"
16832001f49Smrg
16932001f49Smrg      "MUL R0, v[OPOS], c[30]; \n"
17032001f49Smrg      "ADD o[COL0], R0, c[31]; \n"
17132001f49Smrg
17232001f49Smrg      "# Continue with typical modelview/projection\n"
17332001f49Smrg      "MOV R3, v[OPOS]; \n"
17432001f49Smrg      "DP4   o[HPOS].x, c[0], R3 ;	# object x MVP -> clip\n"
17532001f49Smrg      "DP4   o[HPOS].y, c[1], R3 ;\n"
17632001f49Smrg      "DP4   o[HPOS].z, c[2], R3 ;\n"
17732001f49Smrg      "DP4   o[HPOS].w, c[3], R3 ;\n"
17832001f49Smrg
17932001f49Smrg      "END";
18032001f49Smrg
18132001f49Smrg   static const GLfloat scale[4] = {2.0, 2.0, 2.0, 0.0};
18232001f49Smrg   static const GLfloat bias[4] = {1.0, 1.0, 1.0, 0.0};
18332001f49Smrg
18432001f49Smrg   if (!GLEW_NV_vertex_program) {
18532001f49Smrg      printf("Sorry, this program requires GL_NV_vertex_program\n");
18632001f49Smrg      exit(1);
18732001f49Smrg   }
18832001f49Smrg
18932001f49Smrg   glLoadProgramNV(GL_VERTEX_PROGRAM_NV, 1,
19032001f49Smrg                   strlen(prog), (const GLubyte *) prog);
19132001f49Smrg   assert(glIsProgramNV(1));
19232001f49Smrg   glBindProgramNV(GL_VERTEX_PROGRAM_NV, 1);
19332001f49Smrg
19432001f49Smrg   /* Load the program registers */
19532001f49Smrg   glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 0, GL_MODELVIEW_PROJECTION_NV, GL_IDENTITY_NV);
19632001f49Smrg   glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 4, GL_MODELVIEW, GL_INVERSE_TRANSPOSE_NV);
19732001f49Smrg
19832001f49Smrg   glProgramParameter4fvNV(GL_VERTEX_PROGRAM_NV, 30, scale);
19932001f49Smrg   glProgramParameter4fvNV(GL_VERTEX_PROGRAM_NV, 31, bias);
20032001f49Smrg}
20132001f49Smrg
20232001f49Smrg
20332001f49Smrgstatic void init(void)
20432001f49Smrg{
20532001f49Smrg   xrot = 0;
20632001f49Smrg   yrot = 0;
20732001f49Smrg   glClearColor(0.0, 0.0, 1.0, 0.0);
20832001f49Smrg   glEnable( GL_DEPTH_TEST );
20932001f49Smrg   glEnable(GL_NORMALIZE);
21032001f49Smrg   InitMaterials();
21132001f49Smrg   read_surface(DEMOS_DATA_DIR "isosurf.dat");
21232001f49Smrg   init_program();
21332001f49Smrg}
21432001f49Smrg
21532001f49Smrg
21632001f49Smrgstatic void Reshape(int width, int height)
21732001f49Smrg{
21832001f49Smrg   glViewport(0, 0, (GLint)width, (GLint)height);
21932001f49Smrg   glMatrixMode(GL_PROJECTION);
22032001f49Smrg   glLoadIdentity();
22132001f49Smrg   glFrustum( -1.0, 1.0, -1.0, 1.0, 5, 25 );
22232001f49Smrg   glMatrixMode(GL_MODELVIEW);
22332001f49Smrg   glLoadIdentity();
22432001f49Smrg   glTranslatef(0, 0, -15);
22532001f49Smrg}
22632001f49Smrg
22732001f49Smrg
22832001f49Smrg
22932001f49Smrgstatic void Key( unsigned char key, int x, int y )
23032001f49Smrg{
23132001f49Smrg   (void) x;
23232001f49Smrg   (void) y;
23332001f49Smrg   switch (key) {
23432001f49Smrg   case 27:
23532001f49Smrg      exit(0);
23632001f49Smrg   case 'a':
23732001f49Smrg      useArrays = !useArrays;
23832001f49Smrg      printf("use arrays: %s\n", useArrays ? "yes" : "no");
23932001f49Smrg      break;
24032001f49Smrg   case 'l':
24132001f49Smrg      useList = !useList;
24232001f49Smrg      printf("use list: %s\n", useList ? "yes" : "no");
24332001f49Smrg      break;
24432001f49Smrg   case 'p':
24532001f49Smrg      useProgram = !useProgram;
24632001f49Smrg      printf("use program: %s\n", useProgram ? "yes" : "no");
24732001f49Smrg      break;
24832001f49Smrg   }
24932001f49Smrg   glutPostRedisplay();
25032001f49Smrg}
25132001f49Smrg
25232001f49Smrg
25332001f49Smrgstatic void SpecialKey( int key, int x, int y )
25432001f49Smrg{
25532001f49Smrg   (void) x;
25632001f49Smrg   (void) y;
25732001f49Smrg   switch (key) {
25832001f49Smrg   case GLUT_KEY_LEFT:
25932001f49Smrg      yrot -= 15.0;
26032001f49Smrg      break;
26132001f49Smrg   case GLUT_KEY_RIGHT:
26232001f49Smrg      yrot += 15.0;
26332001f49Smrg      break;
26432001f49Smrg   case GLUT_KEY_UP:
26532001f49Smrg      xrot += 15.0;
26632001f49Smrg      break;
26732001f49Smrg   case GLUT_KEY_DOWN:
26832001f49Smrg      xrot -= 15.0;
26932001f49Smrg      break;
27032001f49Smrg   default:
27132001f49Smrg      return;
27232001f49Smrg   }
27332001f49Smrg   glutPostRedisplay();
27432001f49Smrg}
27532001f49Smrg
27632001f49Smrg
27732001f49Smrg
27832001f49Smrgint main(int argc, char **argv)
27932001f49Smrg{
28032001f49Smrg   glutInit(&argc, argv);
28132001f49Smrg   glutInitDisplayMode( GLUT_DEPTH | GLUT_RGB | GLUT_DOUBLE );
28232001f49Smrg   glutInitWindowPosition(0, 0);
28332001f49Smrg   glutInitWindowSize(400, 400);
28432001f49Smrg   if (glutCreateWindow("Isosurface") <= 0) {
28532001f49Smrg      exit(0);
28632001f49Smrg   }
28732001f49Smrg   glewInit();
28832001f49Smrg   glutReshapeFunc(Reshape);
28932001f49Smrg   glutKeyboardFunc(Key);
29032001f49Smrg   glutSpecialFunc(SpecialKey);
29132001f49Smrg   glutDisplayFunc(Display);
29232001f49Smrg
29332001f49Smrg   init();
29432001f49Smrg
29532001f49Smrg   glutMainLoop();
29632001f49Smrg   return 0;
29732001f49Smrg}
298