blob: 2b96f31d060048d0a9830a5fe914b1fff6e3f2be [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
Jon TURNEYa15d9ca2009-07-24 20:33:25 +010019#ifndef M_PI
20#define M_PI 3.1415926535
21#endif
Brian Paulaab429c2008-11-04 16:56:59 -070022
23static char *FragProgFile = "skinning.frag";
24static char *VertProgFile = "skinning.vert";
25
26/* program/shader objects */
27static GLuint fragShader;
28static GLuint vertShader;
29static GLuint program;
30
31
32static GLint win = 0;
33static GLboolean Anim = GL_TRUE;
34static GLboolean WireFrame = GL_TRUE;
35static GLfloat xRot = 0.0f, yRot = 90.0f, zRot = 0.0f;
36
37#define NUM_MATS 2
38
39static GLfloat Matrices[NUM_MATS][16];
40static GLint uMat0, uMat1;
41static GLint WeightAttr;
42
43
44static void
45Idle(void)
46{
47 yRot = 90 + glutGet(GLUT_ELAPSED_TIME) * 0.005;
48 glutPostRedisplay();
49}
50
51
52static void
53Cylinder(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);
Brian Paulee0b1bc2009-07-17 13:23:11 -060068 glVertexAttrib1f(WeightAttr, w0);
Brian Paulaab429c2008-11-04 16:56:59 -070069 glNormal3f(x, y, 0.0);
70 glVertex3f(x, y, z0);
71
Brian Paulee0b1bc2009-07-17 13:23:11 -060072 glVertexAttrib1f(WeightAttr, w0 + dw);
Brian Paulaab429c2008-11-04 16:56:59 -070073 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 */
84static void
85UpdateMatrices(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
105static void
106Redisplay(void)
107{
108 UpdateMatrices();
109
Brian Paulee0b1bc2009-07-17 13:23:11 -0600110 glUniformMatrix4fv(uMat0, 1, GL_FALSE, Matrices[0]);
111 glUniformMatrix4fv(uMat1, 1, GL_FALSE, Matrices[1]);
Brian Paulaab429c2008-11-04 16:56:59 -0700112
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
136static void
137Reshape(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
149static void
150CleanUp(void)
151{
Brian Paulee0b1bc2009-07-17 13:23:11 -0600152 glDeleteShader(fragShader);
153 glDeleteShader(vertShader);
154 glDeleteProgram(program);
Brian Paulaab429c2008-11-04 16:56:59 -0700155 glutDestroyWindow(win);
156}
157
158
159static void
160Key(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
192static void
193SpecialKey(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
219static void
220Init(void)
221{
222 if (!ShadersSupported())
223 exit(1);
224
Brian Paulaab429c2008-11-04 16:56:59 -0700225 vertShader = CompileShaderFile(GL_VERTEX_SHADER, VertProgFile);
226 fragShader = CompileShaderFile(GL_FRAGMENT_SHADER, FragProgFile);
227 program = LinkShaders(vertShader, fragShader);
228
Brian Paulee0b1bc2009-07-17 13:23:11 -0600229 glUseProgram(program);
Brian Paulaab429c2008-11-04 16:56:59 -0700230
Brian Paulee0b1bc2009-07-17 13:23:11 -0600231 uMat0 = glGetUniformLocation(program, "mat0");
232 uMat1 = glGetUniformLocation(program, "mat1");
Brian Paulaab429c2008-11-04 16:56:59 -0700233
Brian Paulee0b1bc2009-07-17 13:23:11 -0600234 WeightAttr = glGetAttribLocation(program, "weight");
Brian Paulaab429c2008-11-04 16:56:59 -0700235
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
246static void
247ParseOptions(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
261int
262main(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]);
Keith Whitwellb799af92009-06-29 14:13:58 +0100268 glewInit();
Brian Paulaab429c2008-11-04 16:56:59 -0700269 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