1/*
2 * Warp a triangle mesh with a 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 = -60.0, Yrot = 0.0, Zrot = 0.0;
14static GLboolean Anim = GL_TRUE;
15static GLfloat Phi = 0.0;
16
17
18static void Idle( void )
19{
20   Phi += 0.01;
21   glutPostRedisplay();
22}
23
24
25static void DrawMesh( int rows, int cols )
26{
27   static const GLfloat colorA[3] = { 0, 1, 0 };
28   static const GLfloat colorB[3] = { 0, 0, 1 };
29   const float dx = 2.0 / (cols - 1);
30   const float dy = 2.0 / (rows - 1);
31   float x, y;
32   int i, j;
33
34#if 1
35#define COLOR3FV(c)     glVertexAttrib3fvARB(3, c)
36#define VERTEX2F(x, y)  glVertexAttrib2fARB(0, x, y)
37#else
38#define COLOR3FV(c)     glColor3fv(c)
39#define VERTEX2F(x, y)  glVertex2f(x, y)
40#endif
41
42   y = -1.0;
43   for (i = 0; i < rows - 1; i++) {
44      glBegin(GL_QUAD_STRIP);
45      x = -1.0;
46      for (j = 0; j < cols; j++) {
47         if ((i + j) & 1)
48            COLOR3FV(colorA);
49         else
50            COLOR3FV(colorB);
51         VERTEX2F(x, y);
52         VERTEX2F(x, y + dy);
53         x += dx;
54      }
55      glEnd();
56      y += dy;
57   }
58}
59
60
61static void Display( void )
62{
63   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
64
65   glPushMatrix();
66      glRotatef(Xrot, 1, 0, 0);
67      glRotatef(Yrot, 0, 1, 0);
68      glRotatef(Zrot, 0, 0, 1);
69
70      /* Position the gravity source */
71      {
72         GLfloat x, y, z, r = 0.5;
73         x = r * cos(Phi);
74         y = r * sin(Phi);
75         z = 1.0;
76         glProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, 30, x, y, z, 1);
77         glDisable(GL_VERTEX_PROGRAM_ARB);
78         glBegin(GL_POINTS);
79         glColor3f(1,1,1);
80         glVertex3f(x, y, z);
81         glEnd();
82      }
83
84      glEnable(GL_VERTEX_PROGRAM_ARB);
85      DrawMesh(8, 8);
86   glPopMatrix();
87
88   glutSwapBuffers();
89}
90
91
92static void Reshape( int width, int height )
93{
94   float ar = (float) width / (float) height;
95   glViewport( 0, 0, width, height );
96   glMatrixMode( GL_PROJECTION );
97   glLoadIdentity();
98   glFrustum( -1.0 * ar, 1.0 * ar, -1.0, 1.0, 5.0, 25.0 );
99   glMatrixMode( GL_MODELVIEW );
100   glLoadIdentity();
101   glTranslatef( 0.0, 0.0, -12.0 );
102   glScalef(2, 2, 2);
103}
104
105
106static void Key( unsigned char key, int x, int y )
107{
108   (void) x;
109   (void) y;
110   switch (key) {
111      case 'a':
112         Anim = !Anim;
113         if (Anim)
114            glutIdleFunc(Idle);
115         else
116            glutIdleFunc(NULL);
117         break;
118      case 'p':
119         Phi += 0.2;
120         break;
121      case 'z':
122         Zrot -= 5.0;
123         break;
124      case 'Z':
125         Zrot += 5.0;
126         break;
127      case 27:
128         exit(0);
129         break;
130   }
131   glutPostRedisplay();
132}
133
134
135static void SpecialKey( int key, int x, int y )
136{
137   const GLfloat step = 3.0;
138   (void) x;
139   (void) y;
140   switch (key) {
141      case GLUT_KEY_UP:
142         Xrot -= step;
143         break;
144      case GLUT_KEY_DOWN:
145         Xrot += step;
146         break;
147      case GLUT_KEY_LEFT:
148         Yrot -= step;
149         break;
150      case GLUT_KEY_RIGHT:
151         Yrot += step;
152         break;
153   }
154   glutPostRedisplay();
155}
156
157
158static void Init( void )
159{
160   GLuint prognum;
161   GLint errnum;
162
163   /*
164    * c[0..3] = modelview matrix
165    * c[4..7] = inverse modelview matrix
166    * c[30] = gravity source location
167    * c[31] = gravity source strength
168    * c[32] = light pos
169    * c[35] = diffuse color
170    */
171   static const char prog[] =
172      "!!ARBvp1.0\n"
173      "TEMP R1, R2, R3; "
174
175      "# Compute distance from vertex to gravity source\n"
176      "ADD   R1, program.local[30], -vertex.position; # vector from vertex to gravity\n"
177      "DP3   R2, R1, R1;                              # dot product\n"
178      "RSQ   R2, R2.x;                                # square root = distance\n"
179      "MUL   R2, R2, program.local[31].xxxx;          # scale by the gravity factor\n"
180
181      "# Displace vertex by gravity factor along R1 vector\n"
182      "MAD   R3, R1, R2, vertex.position;\n"
183
184      "# Continue with typical modelview/projection\n"
185      "DP4   result.position.x, state.matrix.mvp.row[0], R3 ;	# object x MVP -> clip\n"
186      "DP4   result.position.y, state.matrix.mvp.row[1], R3 ;\n"
187      "DP4   result.position.z, state.matrix.mvp.row[2], R3 ;\n"
188      "DP4   result.position.w, state.matrix.mvp.row[3], R3 ;\n"
189
190      "MOV   result.color, vertex.attrib[3];\n       # copy input color to output color\n"
191
192      "END";
193
194   if (!glutExtensionSupported("GL_ARB_vertex_program")) {
195      printf("Sorry, this program requires GL_ARB_vertex_program\n");
196      exit(1);
197   }
198
199   glGenProgramsARB(1, &prognum);
200   glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prognum);
201   glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
202            strlen(prog), (const GLubyte *)prog);
203   errnum = glGetError();
204   printf("glGetError = %d\n", errnum);
205
206	if (errnum != GL_NO_ERROR)
207	{
208		GLint errorpos;
209
210		glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorpos);
211		printf("errorpos: %d\n", errorpos);
212		printf("%s\n", glGetString(GL_PROGRAM_ERROR_STRING_ARB));
213	}
214
215   /* Light position */
216   glProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, 32, 2, 2, 4, 1);
217   /* Diffuse material color */
218   glProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, 35, 0.25, 0, 0.25, 1);
219
220   /* Gravity strength */
221   glProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, 31, .5, 0, 0, 0);
222
223   glEnable(GL_DEPTH_TEST);
224   glClearColor(0.3, 0.3, 0.3, 1);
225   glShadeModel(GL_FLAT);
226   glPointSize(3);
227}
228
229
230int main( int argc, char *argv[] )
231{
232   glutInit( &argc, argv );
233   glutInitWindowPosition( 0, 0 );
234   glutInitWindowSize( 250, 250 );
235   glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
236   glutCreateWindow(argv[0]);
237   glewInit();
238   glutReshapeFunc( Reshape );
239   glutKeyboardFunc( Key );
240   glutSpecialFunc( SpecialKey );
241   glutDisplayFunc( Display );
242   if (Anim)
243      glutIdleFunc(Idle);
244   Init();
245   glutMainLoop();
246   return 0;
247}
248