skinning.c revision 32001f49
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 "glut_wrap.h" 17#include "shaderutil.h" 18 19#ifndef M_PI 20#define M_PI 3.1415926535 21#endif 22 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); 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 */ 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 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 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{ 152 glDeleteShader(fragShader); 153 glDeleteShader(vertShader); 154 glDeleteProgram(program); 155 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 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 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]); 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 281