1/* 2 * Test vertex arrays with GL_NV_vertex_program 3 * 4 * Based on a stripped-down version of the isosurf demo. 5 * The vertex program is trivial: compute the resulting 6 * RGB color as a linear function of vertex XYZ. 7 */ 8 9#include <assert.h> 10#include <stdio.h> 11#include <stdlib.h> 12#include <string.h> 13#include <math.h> 14#include "GL/glew.h" 15#include "glut_wrap.h" 16 17#define MAXVERTS 10000 18static float data[MAXVERTS][6]; 19static GLint numverts; 20 21static GLfloat xrot; 22static GLfloat yrot; 23static GLboolean useArrays = GL_TRUE; 24static GLboolean useProgram = GL_TRUE; 25static GLboolean useList = GL_FALSE; 26 27 28static void read_surface( char *filename ) 29{ 30 FILE *f; 31 32 f = fopen(filename,"r"); 33 if (!f) { 34 printf("couldn't read %s\n", filename); 35 exit(1); 36 } 37 38 numverts = 0; 39 while (numverts < MAXVERTS) { 40 int result; 41 result = fscanf( f, "%f %f %f %f %f %f", 42 &data[numverts][0], &data[numverts][1], &data[numverts][2], 43 &data[numverts][3], &data[numverts][4], &data[numverts][5] ); 44 if (result == EOF) { 45 break; 46 } 47 numverts++; 48 } 49 50 printf("%d vertices, %d triangles\n", numverts, numverts-2); 51 printf("data = %p\n", (void *) data); 52 fclose(f); 53} 54 55 56 57 58static void Display(void) 59{ 60 if (useProgram) 61 glEnable(GL_VERTEX_PROGRAM_NV); 62 else 63 glDisable(GL_VERTEX_PROGRAM_NV); 64 65 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); 66 67 glPushMatrix(); 68 glRotatef(xrot, 1, 0, 0); 69 glRotatef(yrot, 0, 1, 0); 70 glScalef(2, 2, 2); 71 if (useArrays) { 72 if (useProgram) { 73 glVertexAttribPointerNV( 0, 3, GL_FLOAT, 6 * sizeof(GLfloat), data ); 74 glEnableClientState( GL_VERTEX_ATTRIB_ARRAY0_NV ); 75 glVertexAttribPointerNV( 2, 3, GL_FLOAT, 6 * sizeof(GLfloat), ((GLfloat *) data) + 3); 76 glEnableClientState( GL_VERTEX_ATTRIB_ARRAY2_NV); 77 } 78 else { 79 glVertexPointer( 3, GL_FLOAT, 6 * sizeof(GLfloat), data ); 80 glEnableClientState( GL_VERTEX_ARRAY ); 81 glNormalPointer( GL_FLOAT, 6 * sizeof(GLfloat), ((GLfloat *) data) + 3); 82 glEnableClientState( GL_NORMAL_ARRAY ); 83 } 84 85 if (useList) { 86 /* dumb, but a good test */ 87 glNewList(1, GL_COMPILE); 88 glDrawArrays(GL_TRIANGLE_STRIP, 0, numverts); 89 glEndList(); 90 glCallList(1); 91 } 92 else { 93 glDrawArrays(GL_TRIANGLE_STRIP, 0, numverts); 94 } 95 96 glDisableClientState( GL_VERTEX_ATTRIB_ARRAY0_NV ); 97 glDisableClientState( GL_VERTEX_ATTRIB_ARRAY2_NV); 98 glDisableClientState( GL_VERTEX_ARRAY ); 99 glDisableClientState( GL_NORMAL_ARRAY ); 100 } 101 else { 102 int i; 103 glBegin(GL_TRIANGLE_STRIP); 104 for (i = 0; i < numverts; i++) { 105 glNormal3fv( data[i] + 3 ); 106 glVertex3fv( data[i] + 0 ); 107 } 108 glEnd(); 109 } 110 glPopMatrix(); 111 112 if (glGetError()) 113 printf("Error!\n"); 114 115 glutSwapBuffers(); 116} 117 118 119static void InitMaterials(void) 120{ 121 static float ambient[] = {0.1, 0.1, 0.1, 1.0}; 122 static float diffuse[] = {0.5, 1.0, 1.0, 1.0}; 123 static float position0[] = {0.0, 0.0, 20.0, 0.0}; 124 static float position1[] = {0.0, 0.0, -20.0, 0.0}; 125 static float front_mat_shininess[] = {60.0}; 126 static float front_mat_specular[] = {0.2, 0.2, 0.2, 1.0}; 127 static float front_mat_diffuse[] = {0.5, 0.28, 0.38, 1.0}; 128 /* 129 static float back_mat_shininess[] = {60.0}; 130 static float back_mat_specular[] = {0.5, 0.5, 0.2, 1.0}; 131 static float back_mat_diffuse[] = {1.0, 1.0, 0.2, 1.0}; 132 */ 133 static float lmodel_ambient[] = {1.0, 1.0, 1.0, 1.0}; 134 static float lmodel_twoside[] = {GL_FALSE}; 135 136 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); 137 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); 138 glLightfv(GL_LIGHT0, GL_POSITION, position0); 139 glEnable(GL_LIGHT0); 140 141 glLightfv(GL_LIGHT1, GL_AMBIENT, ambient); 142 glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse); 143 glLightfv(GL_LIGHT1, GL_POSITION, position1); 144 glEnable(GL_LIGHT1); 145 146 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); 147 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside); 148 149 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_mat_shininess); 150 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_mat_specular); 151 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, front_mat_diffuse); 152 glEnable(GL_LIGHTING); 153} 154 155 156static void init_program(void) 157{ 158 /* 159 * c[0..3] = modelview matrix 160 * c[4..7] = inverse modelview matrix 161 * c[30] = color scale 162 * c[31] = color bias 163 */ 164 static const char prog[] = 165 "!!VP1.0\n" 166 167 "# RGB is proportional to XYZ \n" 168 169 "MUL R0, v[OPOS], c[30]; \n" 170 "ADD o[COL0], R0, c[31]; \n" 171 172 "# Continue with typical modelview/projection\n" 173 "MOV R3, v[OPOS]; \n" 174 "DP4 o[HPOS].x, c[0], R3 ; # object x MVP -> clip\n" 175 "DP4 o[HPOS].y, c[1], R3 ;\n" 176 "DP4 o[HPOS].z, c[2], R3 ;\n" 177 "DP4 o[HPOS].w, c[3], R3 ;\n" 178 179 "END"; 180 181 static const GLfloat scale[4] = {2.0, 2.0, 2.0, 0.0}; 182 static const GLfloat bias[4] = {1.0, 1.0, 1.0, 0.0}; 183 184 if (!GLEW_NV_vertex_program) { 185 printf("Sorry, this program requires GL_NV_vertex_program\n"); 186 exit(1); 187 } 188 189 glLoadProgramNV(GL_VERTEX_PROGRAM_NV, 1, 190 strlen(prog), (const GLubyte *) prog); 191 assert(glIsProgramNV(1)); 192 glBindProgramNV(GL_VERTEX_PROGRAM_NV, 1); 193 194 /* Load the program registers */ 195 glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 0, GL_MODELVIEW_PROJECTION_NV, GL_IDENTITY_NV); 196 glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 4, GL_MODELVIEW, GL_INVERSE_TRANSPOSE_NV); 197 198 glProgramParameter4fvNV(GL_VERTEX_PROGRAM_NV, 30, scale); 199 glProgramParameter4fvNV(GL_VERTEX_PROGRAM_NV, 31, bias); 200} 201 202 203static void init(void) 204{ 205 xrot = 0; 206 yrot = 0; 207 glClearColor(0.0, 0.0, 1.0, 0.0); 208 glEnable( GL_DEPTH_TEST ); 209 glEnable(GL_NORMALIZE); 210 InitMaterials(); 211 read_surface(DEMOS_DATA_DIR "isosurf.dat"); 212 init_program(); 213} 214 215 216static void Reshape(int width, int height) 217{ 218 glViewport(0, 0, (GLint)width, (GLint)height); 219 glMatrixMode(GL_PROJECTION); 220 glLoadIdentity(); 221 glFrustum( -1.0, 1.0, -1.0, 1.0, 5, 25 ); 222 glMatrixMode(GL_MODELVIEW); 223 glLoadIdentity(); 224 glTranslatef(0, 0, -15); 225} 226 227 228 229static void Key( unsigned char key, int x, int y ) 230{ 231 (void) x; 232 (void) y; 233 switch (key) { 234 case 27: 235 exit(0); 236 case 'a': 237 useArrays = !useArrays; 238 printf("use arrays: %s\n", useArrays ? "yes" : "no"); 239 break; 240 case 'l': 241 useList = !useList; 242 printf("use list: %s\n", useList ? "yes" : "no"); 243 break; 244 case 'p': 245 useProgram = !useProgram; 246 printf("use program: %s\n", useProgram ? "yes" : "no"); 247 break; 248 } 249 glutPostRedisplay(); 250} 251 252 253static void SpecialKey( int key, int x, int y ) 254{ 255 (void) x; 256 (void) y; 257 switch (key) { 258 case GLUT_KEY_LEFT: 259 yrot -= 15.0; 260 break; 261 case GLUT_KEY_RIGHT: 262 yrot += 15.0; 263 break; 264 case GLUT_KEY_UP: 265 xrot += 15.0; 266 break; 267 case GLUT_KEY_DOWN: 268 xrot -= 15.0; 269 break; 270 default: 271 return; 272 } 273 glutPostRedisplay(); 274} 275 276 277 278int main(int argc, char **argv) 279{ 280 glutInit(&argc, argv); 281 glutInitDisplayMode( GLUT_DEPTH | GLUT_RGB | GLUT_DOUBLE ); 282 glutInitWindowPosition(0, 0); 283 glutInitWindowSize(400, 400); 284 if (glutCreateWindow("Isosurface") <= 0) { 285 exit(0); 286 } 287 glewInit(); 288 glutReshapeFunc(Reshape); 289 glutKeyboardFunc(Key); 290 glutSpecialFunc(SpecialKey); 291 glutDisplayFunc(Display); 292 293 init(); 294 295 glutMainLoop(); 296 return 0; 297} 298