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