132001f49Smrg/* Test glGenProgramsNV(), glIsProgramNV(), glLoadProgramNV() */
232001f49Smrg
332001f49Smrg#include <assert.h>
432001f49Smrg#include <string.h>
532001f49Smrg#include <stdio.h>
632001f49Smrg#include <stdlib.h>
732001f49Smrg#include <math.h>
832001f49Smrg
932001f49Smrg#ifndef WIN32
1032001f49Smrg#include <unistd.h>
1132001f49Smrg#include <signal.h>
1232001f49Smrg#endif
1332001f49Smrg
1432001f49Smrg#include <GL/glew.h>
1532001f49Smrg#include "glut_wrap.h"
1632001f49Smrg
1732001f49Smrgstatic const char *filename = NULL;
1832001f49Smrgstatic GLuint nr_steps = 4;
1932001f49Smrgstatic GLuint prim = GL_TRIANGLES;
2032001f49Smrgstatic GLfloat psz = 1.0;
2132001f49Smrgstatic GLboolean pointsmooth = 0;
2232001f49Smrgstatic GLboolean program_point_size = 0;
2332001f49Smrg
2432001f49Smrgstatic void usage( char *name )
2532001f49Smrg{
2632001f49Smrg   fprintf( stderr, "usage: %s [ options ] shader_filename\n", name );
2732001f49Smrg   fprintf( stderr, "\n" );
2832001f49Smrg   fprintf( stderr, "options:\n" );
2932001f49Smrg   fprintf( stderr, "    -f     flat shaded\n" );
3032001f49Smrg   fprintf( stderr, "    -nNr  subdivision steps\n" );
3132001f49Smrg   fprintf( stderr, "    -fps  show frames per second\n" );
3232001f49Smrg}
3332001f49Smrg
3432001f49Smrgunsigned show_fps = 0;
3532001f49Smrgunsigned int frame_cnt = 0;
3632001f49Smrg
3732001f49Smrg#ifndef WIN32
3832001f49Smrg
3932001f49Smrgvoid alarmhandler(int);
4032001f49Smrg
4132001f49Smrgvoid alarmhandler (int sig)
4232001f49Smrg{
4332001f49Smrg   if (sig == SIGALRM) {
4432001f49Smrg      printf("%d frames in 5.0 seconds = %.3f FPS\n", frame_cnt,
4532001f49Smrg             frame_cnt / 5.0);
4632001f49Smrg      fflush(stdout);
4732001f49Smrg
4832001f49Smrg      frame_cnt = 0;
4932001f49Smrg   }
5032001f49Smrg   signal(SIGALRM, alarmhandler);
5132001f49Smrg   alarm(5);
5232001f49Smrg}
5332001f49Smrg
5432001f49Smrg#endif
5532001f49Smrg
5632001f49Smrgstatic void args(int argc, char *argv[])
5732001f49Smrg{
5832001f49Smrg   GLint i;
5932001f49Smrg
6032001f49Smrg   for (i = 1; i < argc; i++) {
6132001f49Smrg      if (strncmp(argv[i], "-n", 2) == 0) {
6232001f49Smrg	 nr_steps = atoi((argv[i]) + 2);
6332001f49Smrg      }
6432001f49Smrg      else if (strcmp(argv[i], "-f") == 0) {
6532001f49Smrg	 glShadeModel(GL_FLAT);
6632001f49Smrg      }
6732001f49Smrg      else if (strcmp(argv[i], "-fps") == 0) {
6832001f49Smrg         show_fps = 1;
6932001f49Smrg      }
7032001f49Smrg      else if (i == argc - 1) {
7132001f49Smrg	 filename = argv[i];
7232001f49Smrg      }
7332001f49Smrg      else {
7432001f49Smrg	 usage(argv[0]);
7532001f49Smrg	 exit(1);
7632001f49Smrg      }
7732001f49Smrg   }
7832001f49Smrg
7932001f49Smrg   if (!filename) {
8032001f49Smrg      usage(argv[0]);
8132001f49Smrg      exit(1);
8232001f49Smrg   }
8332001f49Smrg}
8432001f49Smrg
8532001f49Smrg
8632001f49Smrg
8732001f49Smrgstatic void Init( void )
8832001f49Smrg{
897ec3b29aSmrg   GLint errnum;
9032001f49Smrg   GLuint prognum;
9132001f49Smrg   char buf[16 * 1024];
9232001f49Smrg   GLuint sz;
9332001f49Smrg   FILE *f;
9432001f49Smrg
9532001f49Smrg   if ((f = fopen(filename, "r")) == NULL) {
9632001f49Smrg      fprintf(stderr, "couldn't open %s\n", filename);
9732001f49Smrg      exit(1);
9832001f49Smrg   }
9932001f49Smrg
10032001f49Smrg   sz = (GLuint) fread(buf, 1, sizeof(buf) - 1, f);
10132001f49Smrg   buf[sizeof(buf) - 1] = '\0';
10232001f49Smrg   if (!feof(f)) {
10332001f49Smrg      fprintf(stderr, "file too long\n");
10432001f49Smrg      fclose(f);
10532001f49Smrg      exit(1);
10632001f49Smrg   }
10732001f49Smrg
10832001f49Smrg   fclose(f);
10932001f49Smrg   fprintf(stderr, "%.*s\n", sz, buf);
11032001f49Smrg
11132001f49Smrg   if (strncmp( buf, "!!VP", 4 ) == 0) {
11232001f49Smrg      glEnable( GL_VERTEX_PROGRAM_NV );
11332001f49Smrg      glGenProgramsNV( 1, &prognum );
11432001f49Smrg      glBindProgramNV( GL_VERTEX_PROGRAM_NV, prognum );
11532001f49Smrg      glLoadProgramNV( GL_VERTEX_PROGRAM_NV, prognum, sz, (const GLubyte *) buf );
11632001f49Smrg      assert( glIsProgramNV( prognum ) );
11732001f49Smrg   }
11832001f49Smrg   else {
11932001f49Smrg      glEnable(GL_VERTEX_PROGRAM_ARB);
12032001f49Smrg
12132001f49Smrg      glGenProgramsARB(1, &prognum);
12232001f49Smrg
12332001f49Smrg      glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prognum);
12432001f49Smrg      glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
12532001f49Smrg		        sz, (const GLubyte *) buf);
12632001f49Smrg      if (glGetError()) {
12732001f49Smrg         printf("Program failed to compile:\n%s\n", buf);
12832001f49Smrg         printf("Error: %s\n",
12932001f49Smrg                (char *) glGetString(GL_PROGRAM_ERROR_STRING_ARB));
13032001f49Smrg         exit(1);
13132001f49Smrg      }
13232001f49Smrg      assert(glIsProgramARB(prognum));
13332001f49Smrg   }
13432001f49Smrg
1357ec3b29aSmrg   errnum = glGetError();
1367ec3b29aSmrg   printf("glGetError = %d\n", errnum);
1377ec3b29aSmrg   if (errnum != GL_NO_ERROR)
13832001f49Smrg   {
13932001f49Smrg      GLint errorpos;
14032001f49Smrg
14132001f49Smrg      glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorpos);
14232001f49Smrg      printf("errorpos: %d\n", errorpos);
14332001f49Smrg      printf("%s\n", (char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB));
14432001f49Smrg   }
14532001f49Smrg
14632001f49Smrg   {
14732001f49Smrg      const float Ambient[4] = { 0.0, 1.0, 0.0, 0.0 };
14832001f49Smrg      const float Diffuse[4] = { 1.0, 0.0, 0.0, 0.0 };
14932001f49Smrg      const float Specular[4] = { 0.0, 0.0, 1.0, 0.0 };
15032001f49Smrg      const float Emission[4] = { 0.0, 0.0, 0.0, 1.0 };
15132001f49Smrg      glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, Ambient);
15232001f49Smrg      glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Diffuse);
15332001f49Smrg      glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, Specular);
15432001f49Smrg      glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Emission);
15532001f49Smrg   }
15632001f49Smrg}
15732001f49Smrg
15832001f49Smrg
15932001f49Smrgunion vert {
16032001f49Smrg   struct {
16132001f49Smrg      GLfloat color[3];
16232001f49Smrg      GLfloat pos[3];
16332001f49Smrg   } v;
16432001f49Smrg   GLfloat f[6];
16532001f49Smrg};
16632001f49Smrg
16732001f49Smrgstatic void make_midpoint( union vert *out,
16832001f49Smrg			   const union vert *v0,
16932001f49Smrg			   const union vert *v1)
17032001f49Smrg{
17132001f49Smrg   int i;
17232001f49Smrg   for (i = 0; i < 6; i++)
17332001f49Smrg      out->f[i] = v0->f[i] + .5 * (v1->f[i] - v0->f[i]);
17432001f49Smrg}
17532001f49Smrg
17632001f49Smrgstatic void subdiv( union vert *v0,
17732001f49Smrg		    union vert *v1,
17832001f49Smrg		    union vert *v2,
17932001f49Smrg		    GLuint depth )
18032001f49Smrg{
18132001f49Smrg   if (depth == 0) {
18232001f49Smrg      glColor3fv(v0->v.color);
18332001f49Smrg      glVertex3fv(v0->v.pos);
18432001f49Smrg      glColor3fv(v1->v.color);
18532001f49Smrg      glVertex3fv(v1->v.pos);
18632001f49Smrg      glColor3fv(v2->v.color);
18732001f49Smrg      glVertex3fv(v2->v.pos);
18832001f49Smrg   }
18932001f49Smrg   else {
19032001f49Smrg      union vert m[3];
19132001f49Smrg
19232001f49Smrg      make_midpoint(&m[0], v0, v1);
19332001f49Smrg      make_midpoint(&m[1], v1, v2);
19432001f49Smrg      make_midpoint(&m[2], v2, v0);
19532001f49Smrg
19632001f49Smrg      subdiv(&m[0], &m[2], v0, depth-1);
19732001f49Smrg      subdiv(&m[1], &m[0], v1, depth-1);
19832001f49Smrg      subdiv(&m[2], &m[1], v2, depth-1);
19932001f49Smrg      subdiv(&m[0], &m[1], &m[2], depth-1);
20032001f49Smrg   }
20132001f49Smrg}
20232001f49Smrg
20332001f49Smrgstatic void enable( GLenum value, GLboolean flag )
20432001f49Smrg{
20532001f49Smrg   if (flag)
20632001f49Smrg      glEnable(value);
20732001f49Smrg   else
20832001f49Smrg      glDisable(value);
20932001f49Smrg}
21032001f49Smrg
21132001f49Smrg/** Assignment */
21232001f49Smrg#define ASSIGN_3V( V, V0, V1, V2 )  \
21332001f49Smrgdo {                                \
21432001f49Smrg    V[0] = V0;                      \
21532001f49Smrg    V[1] = V1;                      \
21632001f49Smrg    V[2] = V2;                      \
21732001f49Smrg} while(0)
21832001f49Smrg
21932001f49Smrgstatic void Display( void )
22032001f49Smrg{
22132001f49Smrg   glClearColor(0.3, 0.3, 0.3, 1);
22232001f49Smrg   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
22332001f49Smrg   glPointSize(psz);
22432001f49Smrg
22532001f49Smrg   enable( GL_POINT_SMOOTH, pointsmooth );
22632001f49Smrg   enable( GL_VERTEX_PROGRAM_POINT_SIZE_ARB, program_point_size );
22732001f49Smrg
22832001f49Smrg   glBegin(prim);
22932001f49Smrg
23032001f49Smrg
23132001f49Smrg   {
23232001f49Smrg      union vert v[3];
23332001f49Smrg
23432001f49Smrg      ASSIGN_3V(v[0].v.color, 0,0,1);
23532001f49Smrg      ASSIGN_3V(v[0].v.pos,  0.9, -0.9, 0.0);
23632001f49Smrg      ASSIGN_3V(v[1].v.color, 1,0,0);
23732001f49Smrg      ASSIGN_3V(v[1].v.pos, 0.9, 0.9, 0.0);
23832001f49Smrg      ASSIGN_3V(v[2].v.color, 0,1,0);
23932001f49Smrg      ASSIGN_3V(v[2].v.pos, -0.9, 0, 0.0);
24032001f49Smrg
24132001f49Smrg      subdiv(&v[0], &v[1], &v[2], nr_steps);
24232001f49Smrg   }
24332001f49Smrg
24432001f49Smrg   glEnd();
24532001f49Smrg
24632001f49Smrg
24732001f49Smrg   glFlush();
24832001f49Smrg   if (show_fps) {
24932001f49Smrg      ++frame_cnt;
25032001f49Smrg      glutPostRedisplay();
25132001f49Smrg   }
25232001f49Smrg}
25332001f49Smrg
25432001f49Smrg
25532001f49Smrgstatic void Reshape( int width, int height )
25632001f49Smrg{
25732001f49Smrg   glViewport( 0, 0, width, height );
25832001f49Smrg   glMatrixMode( GL_PROJECTION );
25932001f49Smrg   glLoadIdentity();
26032001f49Smrg   glOrtho(-1.0, 1.0, -1.0, 1.0, -0.5, 1000.0);
26132001f49Smrg   glMatrixMode( GL_MODELVIEW );
26232001f49Smrg   glLoadIdentity();
26332001f49Smrg   /*glTranslatef( 0.0, 0.0, -15.0 );*/
26432001f49Smrg}
26532001f49Smrg
26632001f49Smrg
26732001f49Smrgstatic void Key( unsigned char key, int x, int y )
26832001f49Smrg{
26932001f49Smrg   (void) x;
27032001f49Smrg   (void) y;
27132001f49Smrg   switch (key) {
27232001f49Smrg   case 'p':
27332001f49Smrg      prim = GL_POINTS;
27432001f49Smrg      break;
27532001f49Smrg   case 't':
27632001f49Smrg      prim = GL_TRIANGLES;
27732001f49Smrg      break;
27832001f49Smrg   case 's':
27932001f49Smrg      psz += .5;
28032001f49Smrg      break;
28132001f49Smrg   case 'S':
28232001f49Smrg      if (psz > .5)
28332001f49Smrg         psz -= .5;
28432001f49Smrg      break;
28532001f49Smrg   case 'm':
28632001f49Smrg      pointsmooth = !pointsmooth;
28732001f49Smrg      break;
28832001f49Smrg   case 'z':
28932001f49Smrg      program_point_size = !program_point_size;
29032001f49Smrg      break;
29132001f49Smrg   case '+':
29232001f49Smrg      nr_steps++;
29332001f49Smrg      break;
29432001f49Smrg   case '-':
29532001f49Smrg      if (nr_steps)
29632001f49Smrg         nr_steps--;
29732001f49Smrg      break;
29832001f49Smrg   case ' ':
29932001f49Smrg      psz = 1.0;
30032001f49Smrg      prim = GL_TRIANGLES;
30132001f49Smrg      nr_steps = 4;
30232001f49Smrg      break;
30332001f49Smrg   case 27:
30432001f49Smrg      exit(0);
30532001f49Smrg      break;
30632001f49Smrg   }
30732001f49Smrg   glutPostRedisplay();
30832001f49Smrg}
30932001f49Smrg
31032001f49Smrg
31132001f49Smrg
31232001f49Smrg
31332001f49Smrgint main( int argc, char *argv[] )
31432001f49Smrg{
31532001f49Smrg   glutInit( &argc, argv );
31632001f49Smrg   glutInitWindowPosition( 0, 0 );
31732001f49Smrg   glutInitWindowSize( 250, 250 );
31832001f49Smrg   glutInitDisplayMode( GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH );
31932001f49Smrg   glutCreateWindow(argv[argc-1]);
32032001f49Smrg   glewInit();
32132001f49Smrg   glutReshapeFunc( Reshape );
32232001f49Smrg   glutKeyboardFunc( Key );
32332001f49Smrg   glutDisplayFunc( Display );
32432001f49Smrg   args( argc, argv );
32532001f49Smrg   Init();
32632001f49Smrg#ifndef WIN32
32732001f49Smrg   if (show_fps) {
32832001f49Smrg      signal(SIGALRM, alarmhandler);
32932001f49Smrg      alarm(5);
33032001f49Smrg   }
33132001f49Smrg#endif
33232001f49Smrg   glutMainLoop();
33332001f49Smrg   return 0;
33432001f49Smrg}
335