1/* Test glGenProgramsNV(), glIsProgramNV(), glLoadProgramNV() */
2
3#include <assert.h>
4#include <string.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <math.h>
8
9#ifndef WIN32
10#include <unistd.h>
11#include <signal.h>
12#endif
13
14#include <GL/glew.h>
15#include "glut_wrap.h"
16
17static const char *filename = NULL;
18static GLuint nr_steps = 4;
19static GLuint prim = GL_TRIANGLES;
20static GLfloat psz = 1.0;
21static GLboolean pointsmooth = 0;
22static GLboolean program_point_size = 0;
23
24static void usage( char *name )
25{
26   fprintf( stderr, "usage: %s [ options ] shader_filename\n", name );
27   fprintf( stderr, "\n" );
28   fprintf( stderr, "options:\n" );
29   fprintf( stderr, "    -f     flat shaded\n" );
30   fprintf( stderr, "    -nNr  subdivision steps\n" );
31   fprintf( stderr, "    -fps  show frames per second\n" );
32}
33
34unsigned show_fps = 0;
35unsigned int frame_cnt = 0;
36
37#ifndef WIN32
38
39void alarmhandler(int);
40
41void alarmhandler (int sig)
42{
43   if (sig == SIGALRM) {
44      printf("%d frames in 5.0 seconds = %.3f FPS\n", frame_cnt,
45             frame_cnt / 5.0);
46      fflush(stdout);
47
48      frame_cnt = 0;
49   }
50   signal(SIGALRM, alarmhandler);
51   alarm(5);
52}
53
54#endif
55
56static void args(int argc, char *argv[])
57{
58   GLint i;
59
60   for (i = 1; i < argc; i++) {
61      if (strncmp(argv[i], "-n", 2) == 0) {
62	 nr_steps = atoi((argv[i]) + 2);
63      }
64      else if (strcmp(argv[i], "-f") == 0) {
65	 glShadeModel(GL_FLAT);
66      }
67      else if (strcmp(argv[i], "-fps") == 0) {
68         show_fps = 1;
69      }
70      else if (i == argc - 1) {
71	 filename = argv[i];
72      }
73      else {
74	 usage(argv[0]);
75	 exit(1);
76      }
77   }
78
79   if (!filename) {
80      usage(argv[0]);
81      exit(1);
82   }
83}
84
85
86
87static void Init( void )
88{
89   GLint errnum;
90   GLuint prognum;
91   char buf[16 * 1024];
92   GLuint sz;
93   FILE *f;
94
95   if ((f = fopen(filename, "r")) == NULL) {
96      fprintf(stderr, "couldn't open %s\n", filename);
97      exit(1);
98   }
99
100   sz = (GLuint) fread(buf, 1, sizeof(buf) - 1, f);
101   buf[sizeof(buf) - 1] = '\0';
102   if (!feof(f)) {
103      fprintf(stderr, "file too long\n");
104      fclose(f);
105      exit(1);
106   }
107
108   fclose(f);
109   fprintf(stderr, "%.*s\n", sz, buf);
110
111   if (strncmp( buf, "!!VP", 4 ) == 0) {
112      glEnable( GL_VERTEX_PROGRAM_NV );
113      glGenProgramsNV( 1, &prognum );
114      glBindProgramNV( GL_VERTEX_PROGRAM_NV, prognum );
115      glLoadProgramNV( GL_VERTEX_PROGRAM_NV, prognum, sz, (const GLubyte *) buf );
116      assert( glIsProgramNV( prognum ) );
117   }
118   else {
119      glEnable(GL_VERTEX_PROGRAM_ARB);
120
121      glGenProgramsARB(1, &prognum);
122
123      glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prognum);
124      glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
125		        sz, (const GLubyte *) buf);
126      if (glGetError()) {
127         printf("Program failed to compile:\n%s\n", buf);
128         printf("Error: %s\n",
129                (char *) glGetString(GL_PROGRAM_ERROR_STRING_ARB));
130         exit(1);
131      }
132      assert(glIsProgramARB(prognum));
133   }
134
135   errnum = glGetError();
136   printf("glGetError = %d\n", errnum);
137   if (errnum != GL_NO_ERROR)
138   {
139      GLint errorpos;
140
141      glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorpos);
142      printf("errorpos: %d\n", errorpos);
143      printf("%s\n", (char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB));
144   }
145
146   {
147      const float Ambient[4] = { 0.0, 1.0, 0.0, 0.0 };
148      const float Diffuse[4] = { 1.0, 0.0, 0.0, 0.0 };
149      const float Specular[4] = { 0.0, 0.0, 1.0, 0.0 };
150      const float Emission[4] = { 0.0, 0.0, 0.0, 1.0 };
151      glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, Ambient);
152      glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Diffuse);
153      glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, Specular);
154      glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Emission);
155   }
156}
157
158
159union vert {
160   struct {
161      GLfloat color[3];
162      GLfloat pos[3];
163   } v;
164   GLfloat f[6];
165};
166
167static void make_midpoint( union vert *out,
168			   const union vert *v0,
169			   const union vert *v1)
170{
171   int i;
172   for (i = 0; i < 6; i++)
173      out->f[i] = v0->f[i] + .5 * (v1->f[i] - v0->f[i]);
174}
175
176static void subdiv( union vert *v0,
177		    union vert *v1,
178		    union vert *v2,
179		    GLuint depth )
180{
181   if (depth == 0) {
182      glColor3fv(v0->v.color);
183      glVertex3fv(v0->v.pos);
184      glColor3fv(v1->v.color);
185      glVertex3fv(v1->v.pos);
186      glColor3fv(v2->v.color);
187      glVertex3fv(v2->v.pos);
188   }
189   else {
190      union vert m[3];
191
192      make_midpoint(&m[0], v0, v1);
193      make_midpoint(&m[1], v1, v2);
194      make_midpoint(&m[2], v2, v0);
195
196      subdiv(&m[0], &m[2], v0, depth-1);
197      subdiv(&m[1], &m[0], v1, depth-1);
198      subdiv(&m[2], &m[1], v2, depth-1);
199      subdiv(&m[0], &m[1], &m[2], depth-1);
200   }
201}
202
203static void enable( GLenum value, GLboolean flag )
204{
205   if (flag)
206      glEnable(value);
207   else
208      glDisable(value);
209}
210
211/** Assignment */
212#define ASSIGN_3V( V, V0, V1, V2 )  \
213do {                                \
214    V[0] = V0;                      \
215    V[1] = V1;                      \
216    V[2] = V2;                      \
217} while(0)
218
219static void Display( void )
220{
221   glClearColor(0.3, 0.3, 0.3, 1);
222   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
223   glPointSize(psz);
224
225   enable( GL_POINT_SMOOTH, pointsmooth );
226   enable( GL_VERTEX_PROGRAM_POINT_SIZE_ARB, program_point_size );
227
228   glBegin(prim);
229
230
231   {
232      union vert v[3];
233
234      ASSIGN_3V(v[0].v.color, 0,0,1);
235      ASSIGN_3V(v[0].v.pos,  0.9, -0.9, 0.0);
236      ASSIGN_3V(v[1].v.color, 1,0,0);
237      ASSIGN_3V(v[1].v.pos, 0.9, 0.9, 0.0);
238      ASSIGN_3V(v[2].v.color, 0,1,0);
239      ASSIGN_3V(v[2].v.pos, -0.9, 0, 0.0);
240
241      subdiv(&v[0], &v[1], &v[2], nr_steps);
242   }
243
244   glEnd();
245
246
247   glFlush();
248   if (show_fps) {
249      ++frame_cnt;
250      glutPostRedisplay();
251   }
252}
253
254
255static void Reshape( int width, int height )
256{
257   glViewport( 0, 0, width, height );
258   glMatrixMode( GL_PROJECTION );
259   glLoadIdentity();
260   glOrtho(-1.0, 1.0, -1.0, 1.0, -0.5, 1000.0);
261   glMatrixMode( GL_MODELVIEW );
262   glLoadIdentity();
263   /*glTranslatef( 0.0, 0.0, -15.0 );*/
264}
265
266
267static void Key( unsigned char key, int x, int y )
268{
269   (void) x;
270   (void) y;
271   switch (key) {
272   case 'p':
273      prim = GL_POINTS;
274      break;
275   case 't':
276      prim = GL_TRIANGLES;
277      break;
278   case 's':
279      psz += .5;
280      break;
281   case 'S':
282      if (psz > .5)
283         psz -= .5;
284      break;
285   case 'm':
286      pointsmooth = !pointsmooth;
287      break;
288   case 'z':
289      program_point_size = !program_point_size;
290      break;
291   case '+':
292      nr_steps++;
293      break;
294   case '-':
295      if (nr_steps)
296         nr_steps--;
297      break;
298   case ' ':
299      psz = 1.0;
300      prim = GL_TRIANGLES;
301      nr_steps = 4;
302      break;
303   case 27:
304      exit(0);
305      break;
306   }
307   glutPostRedisplay();
308}
309
310
311
312
313int main( int argc, char *argv[] )
314{
315   glutInit( &argc, argv );
316   glutInitWindowPosition( 0, 0 );
317   glutInitWindowSize( 250, 250 );
318   glutInitDisplayMode( GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH );
319   glutCreateWindow(argv[argc-1]);
320   glewInit();
321   glutReshapeFunc( Reshape );
322   glutKeyboardFunc( Key );
323   glutDisplayFunc( Display );
324   args( argc, argv );
325   Init();
326#ifndef WIN32
327   if (show_fps) {
328      signal(SIGALRM, alarmhandler);
329      alarm(5);
330   }
331#endif
332   glutMainLoop();
333   return 0;
334}
335