mesa: replace CC with APP_CC in progs/glsl/Makefile
[mesa.git] / progs / glsl / skinning.c
1 /**
2 * Vertex "skinning" example.
3 * The idea is there are multiple modeling matrices applied to every
4 * vertex. Weighting values in [0,1] control the influence of each
5 * matrix on each vertex.
6 *
7 * 4 Nov 2008
8 */
9
10 #include <assert.h>
11 #include <string.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <math.h>
15 #include <GL/gl.h>
16 #include <GL/glut.h>
17 #include <GL/glext.h>
18 #include "extfuncs.h"
19 #include "shaderutil.h"
20
21
22 static char *FragProgFile = "skinning.frag";
23 static char *VertProgFile = "skinning.vert";
24
25 /* program/shader objects */
26 static GLuint fragShader;
27 static GLuint vertShader;
28 static GLuint program;
29
30
31 static GLint win = 0;
32 static GLboolean Anim = GL_TRUE;
33 static GLboolean WireFrame = GL_TRUE;
34 static GLfloat xRot = 0.0f, yRot = 90.0f, zRot = 0.0f;
35
36 #define NUM_MATS 2
37
38 static GLfloat Matrices[NUM_MATS][16];
39 static GLint uMat0, uMat1;
40 static GLint WeightAttr;
41
42
43 static void
44 Idle(void)
45 {
46 yRot = 90 + glutGet(GLUT_ELAPSED_TIME) * 0.005;
47 glutPostRedisplay();
48 }
49
50
51 static void
52 Cylinder(GLfloat length, GLfloat radius, GLint slices, GLint stacks)
53 {
54 float dw = 1.0 / (stacks - 1);
55 float dz = length / stacks;
56 int i, j;
57
58 for (j = 0; j < stacks; j++) {
59 float w0 = j * dw;
60 float z0 = j * dz;
61
62 glBegin(GL_TRIANGLE_STRIP);
63 for (i = 0; i < slices; i++) {
64 float a = (float) i / (slices - 1) * M_PI * 2.0;
65 float x = radius * cos(a);
66 float y = radius * sin(a);
67 glVertexAttrib1f_func(WeightAttr, w0);
68 glNormal3f(x, y, 0.0);
69 glVertex3f(x, y, z0);
70
71 glVertexAttrib1f_func(WeightAttr, w0 + dw);
72 glNormal3f(x, y, 0.0);
73 glVertex3f(x, y, z0 + dz);
74 }
75 glEnd();
76 }
77 }
78
79
80 /**
81 * Update/animate the two matrices. One rotates, the other scales.
82 */
83 static void
84 UpdateMatrices(void)
85 {
86 GLfloat t = glutGet(GLUT_ELAPSED_TIME) * 0.0025;
87 GLfloat scale = 0.5 * (1.1 + sin(0.5 * t));
88 GLfloat rot = cos(t) * 90.0;
89
90 glPushMatrix();
91 glLoadIdentity();
92 glScalef(1.0, scale, 1.0);
93 glGetFloatv(GL_MODELVIEW_MATRIX, Matrices[0]);
94 glPopMatrix();
95
96 glPushMatrix();
97 glLoadIdentity();
98 glRotatef(rot, 0, 0, 1);
99 glGetFloatv(GL_MODELVIEW_MATRIX, Matrices[1]);
100 glPopMatrix();
101 }
102
103
104 static void
105 Redisplay(void)
106 {
107 UpdateMatrices();
108
109 glUniformMatrix4fv_func(uMat0, 1, GL_FALSE, Matrices[0]);
110 glUniformMatrix4fv_func(uMat1, 1, GL_FALSE, Matrices[1]);
111
112 if (WireFrame)
113 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
114 else
115 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
116
117 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
118
119 glPushMatrix();
120 glRotatef(xRot, 1.0f, 0.0f, 0.0f);
121 glRotatef(yRot, 0.0f, 1.0f, 0.0f);
122 glRotatef(zRot, 0.0f, 0.0f, 1.0f);
123
124 glPushMatrix();
125 glTranslatef(0, 0, -2.5);
126 Cylinder(5.0, 1.0, 10, 20);
127 glPopMatrix();
128
129 glPopMatrix();
130
131 glutSwapBuffers();
132 }
133
134
135 static void
136 Reshape(int width, int height)
137 {
138 glViewport(0, 0, width, height);
139 glMatrixMode(GL_PROJECTION);
140 glLoadIdentity();
141 glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
142 glMatrixMode(GL_MODELVIEW);
143 glLoadIdentity();
144 glTranslatef(0.0f, 0.0f, -15.0f);
145 }
146
147
148 static void
149 CleanUp(void)
150 {
151 glDeleteShader_func(fragShader);
152 glDeleteShader_func(vertShader);
153 glDeleteProgram_func(program);
154 glutDestroyWindow(win);
155 }
156
157
158 static void
159 Key(unsigned char key, int x, int y)
160 {
161 const GLfloat step = 2.0;
162 (void) x;
163 (void) y;
164
165 switch(key) {
166 case 'a':
167 Anim = !Anim;
168 if (Anim)
169 glutIdleFunc(Idle);
170 else
171 glutIdleFunc(NULL);
172 break;
173 case 'w':
174 WireFrame = !WireFrame;
175 break;
176 case 'z':
177 zRot += step;
178 break;
179 case 'Z':
180 zRot -= step;
181 break;
182 case 27:
183 CleanUp();
184 exit(0);
185 break;
186 }
187 glutPostRedisplay();
188 }
189
190
191 static void
192 SpecialKey(int key, int x, int y)
193 {
194 const GLfloat step = 2.0;
195
196 (void) x;
197 (void) y;
198
199 switch(key) {
200 case GLUT_KEY_UP:
201 xRot += step;
202 break;
203 case GLUT_KEY_DOWN:
204 xRot -= step;
205 break;
206 case GLUT_KEY_LEFT:
207 yRot -= step;
208 break;
209 case GLUT_KEY_RIGHT:
210 yRot += step;
211 break;
212 }
213 glutPostRedisplay();
214 }
215
216
217
218 static void
219 Init(void)
220 {
221 if (!ShadersSupported())
222 exit(1);
223
224 GetExtensionFuncs();
225
226 vertShader = CompileShaderFile(GL_VERTEX_SHADER, VertProgFile);
227 fragShader = CompileShaderFile(GL_FRAGMENT_SHADER, FragProgFile);
228 program = LinkShaders(vertShader, fragShader);
229
230 glUseProgram_func(program);
231
232 uMat0 = glGetUniformLocation_func(program, "mat0");
233 uMat1 = glGetUniformLocation_func(program, "mat1");
234
235 WeightAttr = glGetAttribLocation_func(program, "weight");
236
237 assert(glGetError() == 0);
238
239 glClearColor(0.4f, 0.4f, 0.8f, 0.0f);
240
241 glEnable(GL_DEPTH_TEST);
242
243 glColor3f(1, 0, 0);
244 }
245
246
247 static void
248 ParseOptions(int argc, char *argv[])
249 {
250 int i;
251 for (i = 1; i < argc; i++) {
252 if (strcmp(argv[i], "-fs") == 0) {
253 FragProgFile = argv[i+1];
254 }
255 else if (strcmp(argv[i], "-vs") == 0) {
256 VertProgFile = argv[i+1];
257 }
258 }
259 }
260
261
262 int
263 main(int argc, char *argv[])
264 {
265 glutInit(&argc, argv);
266 glutInitWindowSize(500, 500);
267 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
268 win = glutCreateWindow(argv[0]);
269 glutReshapeFunc(Reshape);
270 glutKeyboardFunc(Key);
271 glutSpecialFunc(SpecialKey);
272 glutDisplayFunc(Redisplay);
273 ParseOptions(argc, argv);
274 Init();
275 if (Anim)
276 glutIdleFunc(Idle);
277 glutMainLoop();
278 return 0;
279 }
280