132001f49Smrg/*
232001f49Smrg * Test vertex arrays with GL_ARB_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_ARB);
6232001f49Smrg   else
6332001f49Smrg      glDisable(GL_VERTEX_PROGRAM_ARB);
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            glVertexAttribPointerARB( 0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), data );
7432001f49Smrg            glEnableVertexAttribArrayARB( 0 );
7532001f49Smrg            glVertexAttribPointerARB( 2, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), ((GLfloat *) data) + 3);
7632001f49Smrg            glEnableVertexAttribArrayARB( 2 );
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         glDisableVertexAttribArrayARB( 0 );
9732001f49Smrg         glDisableVertexAttribArrayARB( 2 );
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[30] = color scale
16032001f49Smrg    * c[31] = color bias
16132001f49Smrg    */
16232001f49Smrg   static const char prog[] =
16332001f49Smrg      "!!ARBvp1.0\n"
16432001f49Smrg
16532001f49Smrg      "TEMP R0, R1, R2, R3;\n"
16632001f49Smrg
16732001f49Smrg      "# RGB is proportional to XYZ \n"
16832001f49Smrg      "MUL R0, vertex.position, program.local[30]; \n"
16932001f49Smrg      "ADD result.color.primary, R0, program.local[31]; \n"
17032001f49Smrg
17132001f49Smrg      "# Continue with typical modelview/projection\n"
17232001f49Smrg      "MOV R3, vertex.position; \n"
17332001f49Smrg      "DP4   result.position.x, state.matrix.mvp.row[0], R3 ;	# object x MVP -> clip\n"
17432001f49Smrg      "DP4   result.position.y, state.matrix.mvp.row[1], R3 ;\n"
17532001f49Smrg      "DP4   result.position.z, state.matrix.mvp.row[2], R3 ;\n"
17632001f49Smrg      "DP4   result.position.w, state.matrix.mvp.row[3], R3 ;\n"
17732001f49Smrg
17832001f49Smrg      "END";
17932001f49Smrg
18032001f49Smrg   static const GLfloat scale[4] = {2.0, 2.0, 2.0, 0.0};
18132001f49Smrg   static const GLfloat bias[4] = {1.0, 1.0, 1.0, 0.0};
18232001f49Smrg
18332001f49Smrg   if (!GLEW_ARB_vertex_program) {
18432001f49Smrg      printf("Sorry, this program requires GL_ARB_vertex_program\n");
18532001f49Smrg      exit(1);
18632001f49Smrg   }
18732001f49Smrg
18832001f49Smrg   glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 1);
18932001f49Smrg   glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
19032001f49Smrg                      strlen(prog), (const GLubyte *) prog);
19132001f49Smrg   assert(glIsProgramARB(1));
19232001f49Smrg
19332001f49Smrg   if (glGetError() != GL_NO_ERROR)
19432001f49Smrg   {
19532001f49Smrg      GLint errorpos = 0;
19632001f49Smrg      glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorpos);
19732001f49Smrg      printf("errorpos: %d\n", errorpos);
19832001f49Smrg      printf("%s\n", (char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB));
19932001f49Smrg      exit(1);
20032001f49Smrg   }
20132001f49Smrg
20232001f49Smrg   /* Load the program registers */
20332001f49Smrg   glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, 30, scale);
20432001f49Smrg   glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, 31, bias);
20532001f49Smrg}
20632001f49Smrg
20732001f49Smrg
20832001f49Smrgstatic void init(void)
20932001f49Smrg{
21032001f49Smrg   xrot = 0;
21132001f49Smrg   yrot = 0;
21232001f49Smrg   glClearColor(0.0, 0.0, 1.0, 0.0);
21332001f49Smrg   glEnable( GL_DEPTH_TEST );
21432001f49Smrg   glEnable(GL_NORMALIZE);
21532001f49Smrg   InitMaterials();
21632001f49Smrg   read_surface(DEMOS_DATA_DIR "isosurf.dat");
21732001f49Smrg   init_program();
21832001f49Smrg}
21932001f49Smrg
22032001f49Smrg
22132001f49Smrgstatic void Reshape(int width, int height)
22232001f49Smrg{
22332001f49Smrg   glViewport(0, 0, (GLint)width, (GLint)height);
22432001f49Smrg   glMatrixMode(GL_PROJECTION);
22532001f49Smrg   glLoadIdentity();
22632001f49Smrg   glFrustum( -1.0, 1.0, -1.0, 1.0, 5, 25 );
22732001f49Smrg   glMatrixMode(GL_MODELVIEW);
22832001f49Smrg   glLoadIdentity();
22932001f49Smrg   glTranslatef(0, 0, -15);
23032001f49Smrg}
23132001f49Smrg
23232001f49Smrg
23332001f49Smrg
23432001f49Smrgstatic void Key( unsigned char key, int x, int y )
23532001f49Smrg{
23632001f49Smrg   (void) x;
23732001f49Smrg   (void) y;
23832001f49Smrg   switch (key) {
23932001f49Smrg   case 27:
24032001f49Smrg      exit(0);
24132001f49Smrg   case 'a':
24232001f49Smrg      useArrays = !useArrays;
24332001f49Smrg      printf("use arrays: %s\n", useArrays ? "yes" : "no");
24432001f49Smrg      break;
24532001f49Smrg   case 'l':
24632001f49Smrg      useList = !useList;
24732001f49Smrg      printf("use list: %s\n", useList ? "yes" : "no");
24832001f49Smrg      break;
24932001f49Smrg   case 'p':
25032001f49Smrg      useProgram = !useProgram;
25132001f49Smrg      printf("use program: %s\n", useProgram ? "yes" : "no");
25232001f49Smrg      break;
25332001f49Smrg   }
25432001f49Smrg   glutPostRedisplay();
25532001f49Smrg}
25632001f49Smrg
25732001f49Smrg
25832001f49Smrgstatic void SpecialKey( int key, int x, int y )
25932001f49Smrg{
26032001f49Smrg   (void) x;
26132001f49Smrg   (void) y;
26232001f49Smrg   switch (key) {
26332001f49Smrg   case GLUT_KEY_LEFT:
26432001f49Smrg      yrot -= 15.0;
26532001f49Smrg      break;
26632001f49Smrg   case GLUT_KEY_RIGHT:
26732001f49Smrg      yrot += 15.0;
26832001f49Smrg      break;
26932001f49Smrg   case GLUT_KEY_UP:
27032001f49Smrg      xrot += 15.0;
27132001f49Smrg      break;
27232001f49Smrg   case GLUT_KEY_DOWN:
27332001f49Smrg      xrot -= 15.0;
27432001f49Smrg      break;
27532001f49Smrg   default:
27632001f49Smrg      return;
27732001f49Smrg   }
27832001f49Smrg   glutPostRedisplay();
27932001f49Smrg}
28032001f49Smrg
28132001f49Smrg
28232001f49Smrg
28332001f49Smrgint main(int argc, char **argv)
28432001f49Smrg{
28532001f49Smrg   glutInit(&argc, argv);
28632001f49Smrg   glutInitDisplayMode( GLUT_DEPTH | GLUT_RGB | GLUT_DOUBLE );
28732001f49Smrg   glutInitWindowPosition(0, 0);
28832001f49Smrg   glutInitWindowSize(400, 400);
28932001f49Smrg   if (glutCreateWindow("Isosurface") <= 0) {
29032001f49Smrg      exit(0);
29132001f49Smrg   }
29232001f49Smrg   glewInit();
29332001f49Smrg   glutReshapeFunc(Reshape);
29432001f49Smrg   glutKeyboardFunc(Key);
29532001f49Smrg   glutSpecialFunc(SpecialKey);
29632001f49Smrg   glutDisplayFunc(Display);
29732001f49Smrg
29832001f49Smrg   init();
29932001f49Smrg
30032001f49Smrg   glutMainLoop();
30132001f49Smrg   return 0;
30232001f49Smrg}
303