1/*
2 * Test vertex arrays with GL_ARB_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_ARB);
62   else
63      glDisable(GL_VERTEX_PROGRAM_ARB);
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            glVertexAttribPointerARB( 0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), data );
74            glEnableVertexAttribArrayARB( 0 );
75            glVertexAttribPointerARB( 2, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), ((GLfloat *) data) + 3);
76            glEnableVertexAttribArrayARB( 2 );
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         glDisableVertexAttribArrayARB( 0 );
97         glDisableVertexAttribArrayARB( 2 );
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[30] = color scale
160    * c[31] = color bias
161    */
162   static const char prog[] =
163      "!!ARBvp1.0\n"
164
165      "TEMP R0, R1, R2, R3;\n"
166
167      "# RGB is proportional to XYZ \n"
168      "MUL R0, vertex.position, program.local[30]; \n"
169      "ADD result.color.primary, R0, program.local[31]; \n"
170
171      "# Continue with typical modelview/projection\n"
172      "MOV R3, vertex.position; \n"
173      "DP4   result.position.x, state.matrix.mvp.row[0], R3 ;	# object x MVP -> clip\n"
174      "DP4   result.position.y, state.matrix.mvp.row[1], R3 ;\n"
175      "DP4   result.position.z, state.matrix.mvp.row[2], R3 ;\n"
176      "DP4   result.position.w, state.matrix.mvp.row[3], R3 ;\n"
177
178      "END";
179
180   static const GLfloat scale[4] = {2.0, 2.0, 2.0, 0.0};
181   static const GLfloat bias[4] = {1.0, 1.0, 1.0, 0.0};
182
183   if (!GLEW_ARB_vertex_program) {
184      printf("Sorry, this program requires GL_ARB_vertex_program\n");
185      exit(1);
186   }
187
188   glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 1);
189   glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
190                      strlen(prog), (const GLubyte *) prog);
191   assert(glIsProgramARB(1));
192
193   if (glGetError() != GL_NO_ERROR)
194   {
195      GLint errorpos = 0;
196      glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorpos);
197      printf("errorpos: %d\n", errorpos);
198      printf("%s\n", (char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB));
199      exit(1);
200   }
201
202   /* Load the program registers */
203   glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, 30, scale);
204   glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, 31, bias);
205}
206
207
208static void init(void)
209{
210   xrot = 0;
211   yrot = 0;
212   glClearColor(0.0, 0.0, 1.0, 0.0);
213   glEnable( GL_DEPTH_TEST );
214   glEnable(GL_NORMALIZE);
215   InitMaterials();
216   read_surface(DEMOS_DATA_DIR "isosurf.dat");
217   init_program();
218}
219
220
221static void Reshape(int width, int height)
222{
223   glViewport(0, 0, (GLint)width, (GLint)height);
224   glMatrixMode(GL_PROJECTION);
225   glLoadIdentity();
226   glFrustum( -1.0, 1.0, -1.0, 1.0, 5, 25 );
227   glMatrixMode(GL_MODELVIEW);
228   glLoadIdentity();
229   glTranslatef(0, 0, -15);
230}
231
232
233
234static void Key( unsigned char key, int x, int y )
235{
236   (void) x;
237   (void) y;
238   switch (key) {
239   case 27:
240      exit(0);
241   case 'a':
242      useArrays = !useArrays;
243      printf("use arrays: %s\n", useArrays ? "yes" : "no");
244      break;
245   case 'l':
246      useList = !useList;
247      printf("use list: %s\n", useList ? "yes" : "no");
248      break;
249   case 'p':
250      useProgram = !useProgram;
251      printf("use program: %s\n", useProgram ? "yes" : "no");
252      break;
253   }
254   glutPostRedisplay();
255}
256
257
258static void SpecialKey( int key, int x, int y )
259{
260   (void) x;
261   (void) y;
262   switch (key) {
263   case GLUT_KEY_LEFT:
264      yrot -= 15.0;
265      break;
266   case GLUT_KEY_RIGHT:
267      yrot += 15.0;
268      break;
269   case GLUT_KEY_UP:
270      xrot += 15.0;
271      break;
272   case GLUT_KEY_DOWN:
273      xrot -= 15.0;
274      break;
275   default:
276      return;
277   }
278   glutPostRedisplay();
279}
280
281
282
283int main(int argc, char **argv)
284{
285   glutInit(&argc, argv);
286   glutInitDisplayMode( GLUT_DEPTH | GLUT_RGB | GLUT_DOUBLE );
287   glutInitWindowPosition(0, 0);
288   glutInitWindowSize(400, 400);
289   if (glutCreateWindow("Isosurface") <= 0) {
290      exit(0);
291   }
292   glewInit();
293   glutReshapeFunc(Reshape);
294   glutKeyboardFunc(Key);
295   glutSpecialFunc(SpecialKey);
296   glutDisplayFunc(Display);
297
298   init();
299
300   glutMainLoop();
301   return 0;
302}
303