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