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