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