blob: 8a65d0667ce7732eadbabfda5e602fb4c1c91c5d [file] [log] [blame]
Brian Paulaab429c2008-11-04 16:56:59 -07001/**
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
22static char *FragProgFile = "skinning.frag";
23static char *VertProgFile = "skinning.vert";
24
25/* program/shader objects */
26static GLuint fragShader;
27static GLuint vertShader;
28static GLuint program;
29
30
31static GLint win = 0;
32static GLboolean Anim = GL_TRUE;
33static GLboolean WireFrame = GL_TRUE;
34static GLfloat xRot = 0.0f, yRot = 90.0f, zRot = 0.0f;
35
36#define NUM_MATS 2
37
38static GLfloat Matrices[NUM_MATS][16];
39static GLint uMat0, uMat1;
40static GLint WeightAttr;
41
42
43static void
44Idle(void)
45{
46 yRot = 90 + glutGet(GLUT_ELAPSED_TIME) * 0.005;
47 glutPostRedisplay();
48}
49
50
51static void
52Cylinder(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 */
83static void
84UpdateMatrices(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
104static void
105Redisplay(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
135static void
136Reshape(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
148static void
149CleanUp(void)
150{
151 glDeleteShader_func(fragShader);
152 glDeleteShader_func(vertShader);
153 glDeleteProgram_func(program);
154 glutDestroyWindow(win);
155}
156
157
158static void
159Key(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
191static void
192SpecialKey(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
218static void
219Init(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
247static void
248ParseOptions(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
262int
263main(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