1/*
2 * A lit, rotating torus via vertex program
3 */
4
5#include <assert.h>
6#include <string.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <math.h>
10#include <GL/glew.h>
11#include "glut_wrap.h"
12
13static float Xrot = 0.0, Yrot = 0.0, Zrot = 0.0;
14static GLboolean Anim = GL_TRUE;
15
16
17static void Idle( void )
18{
19   Xrot += .3;
20   Yrot += .4;
21   Zrot += .2;
22   glutPostRedisplay();
23}
24
25
26static void Display( void )
27{
28   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
29
30   glPushMatrix();
31      glRotatef(Xrot, 1, 0, 0);
32      glRotatef(Yrot, 0, 1, 0);
33      glRotatef(Zrot, 0, 0, 1);
34      glutSolidTorus(0.75, 2.0, 10, 20);
35   glPopMatrix();
36
37   glutSwapBuffers();
38}
39
40
41static void Reshape( int width, int height )
42{
43   glViewport( 0, 0, width, height );
44   glMatrixMode( GL_PROJECTION );
45   glLoadIdentity();
46   glFrustum( -2.0, 2.0, -2.0, 2.0, 5.0, 25.0 );
47   glMatrixMode( GL_MODELVIEW );
48   glLoadIdentity();
49   glTranslatef( 0.0, 0.0, -12.0 );
50}
51
52
53static void Key( unsigned char key, int x, int y )
54{
55   (void) x;
56   (void) y;
57   switch (key) {
58      case ' ':
59         Xrot = Yrot = Zrot = 0;
60         break;
61      case 'a':
62         Anim = !Anim;
63         if (Anim)
64            glutIdleFunc(Idle);
65         else
66            glutIdleFunc(NULL);
67         break;
68      case 'z':
69         Zrot -= 5.0;
70         break;
71      case 'Z':
72         Zrot += 5.0;
73         break;
74      case 27:
75         exit(0);
76         break;
77   }
78   glutPostRedisplay();
79}
80
81
82static void SpecialKey( int key, int x, int y )
83{
84   const GLfloat step = 3.0;
85   (void) x;
86   (void) y;
87   switch (key) {
88      case GLUT_KEY_UP:
89         Xrot -= step;
90         break;
91      case GLUT_KEY_DOWN:
92         Xrot += step;
93         break;
94      case GLUT_KEY_LEFT:
95         Yrot -= step;
96         break;
97      case GLUT_KEY_RIGHT:
98         Yrot += step;
99         break;
100   }
101   glutPostRedisplay();
102}
103
104
105static void Init( void )
106{
107   GLint errnum;
108   GLuint prognum;
109
110   /* borrowed from an nvidia demo:
111    * c[0..3] = modelview matrix
112    * c[4..7] = invtrans modelview matrix
113    * c[32] = light pos
114    * c[35] = diffuse color
115    */
116   static const char prog[] =
117      "!!ARBvp1.0\n"
118      "OPTION ARB_position_invariant ;"
119      "TEMP R0, R1; \n"
120
121      "# normal x MV-1T -> lighting normal\n"
122      "DP3   R1.x, state.matrix.modelview.invtrans.row[0], vertex.normal ;\n"
123      "DP3   R1.y, state.matrix.modelview.invtrans.row[1], vertex.normal;\n"
124      "DP3   R1.z, state.matrix.modelview.invtrans.row[2], vertex.normal;\n"
125
126      "DP3   R0, program.local[32], R1;                  # L.N\n"
127#if 0
128      "MUL   result.color.xyz, R0, program.local[35] ;   # col = L.N * diffuse\n"
129#else
130      "MUL   result.color.primary.xyz, R0, program.local[35] ;   # col = L.N * diffuse\n"
131#endif
132      "MOV   result.texcoord, vertex.texcoord;\n"
133      "END";
134
135   if (!glutExtensionSupported("GL_ARB_vertex_program")) {
136      printf("Sorry, this program requires GL_ARB_vertex_program");
137      exit(1);
138   }
139
140
141   glGenProgramsARB(1, &prognum);
142
143   glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prognum);
144   glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
145                        strlen(prog), (const GLubyte *) prog);
146
147   assert(glIsProgramARB(prognum));
148   errnum = glGetError();
149   printf("glGetError = %d\n", errnum);
150   if (errnum != GL_NO_ERROR)
151   {
152      GLint errorpos;
153
154      glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorpos);
155      printf("errorpos: %d\n", errorpos);
156      printf("%s\n", (char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB));
157   }
158
159   /* Light position */
160   glProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, 32, 2, 2, 4, 1);
161   /* Diffuse material color */
162   glProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, 35, 0.25, 0, 0.25, 1);
163
164   glEnable(GL_VERTEX_PROGRAM_ARB);
165   glEnable(GL_DEPTH_TEST);
166   glClearColor(0.3, 0.3, 0.3, 1);
167}
168
169
170int main( int argc, char *argv[] )
171{
172   glutInit( &argc, argv );
173   glutInitWindowPosition( 0, 0 );
174   glutInitWindowSize( 250, 250 );
175   glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
176   glutCreateWindow(argv[0]);
177   glewInit();
178   glutReshapeFunc( Reshape );
179   glutKeyboardFunc( Key );
180   glutSpecialFunc( SpecialKey );
181   glutDisplayFunc( Display );
182   if (Anim)
183      glutIdleFunc(Idle);
184   Init();
185   glutMainLoop();
186   return 0;
187}
188