9 #include <gmath/gmath.h>
15 #define MAX_NUM_SPAWNS 1600
19 static void cleanup();
20 static void display();
21 static void reshape(int x, int y);
22 static void keydown(unsigned char key, int x, int y);
23 static void keyup(unsigned char key, int x, int y);
24 static void mouse(int bn, int st, int x, int y);
25 static void motion(int x, int y);
27 static void sball_motion(int x, int y, int z);
28 static void sball_rotate(int x, int y, int z);
29 static void sball_button(int bn, int st);
31 static unsigned int gen_grad_tex(int sz, const Vec3 &c0, const Vec3 &c1);
32 static void draw_text(const char *text, int x, int y, float sz, const Vec3 &color);
33 static void update_sball_matrix();
35 static std::vector<Mesh*> meshes;
36 static Mesh *mesh_head;
39 static unsigned int grad_tex;
41 static int win_width, win_height;
42 static float cam_theta, cam_phi = 25, cam_dist = 8;
43 static float head_rz, head_rx; /* rot angles x, z axis */
44 static Mat4 head_xform;
45 //static CollSphere coll_sphere; /* sphere used for collision detection */
47 // spaceball (6dof control) state
48 static Vec3 sball_pos;
49 static Quat sball_rot;
50 static Mat4 sball_xform;
51 static bool sball_update_pending;
54 int main(int argc, char **argv)
56 glutInit(&argc, argv);
57 glutInitWindowSize(800, 600);
58 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
59 glutCreateWindow("hair test");
61 /* for the keydown, keyup functions to work */
62 glutSetKeyRepeat(GLUT_KEY_REPEAT_OFF);
64 glutDisplayFunc(display);
65 glutReshapeFunc(reshape);
66 glutKeyboardFunc(keydown);
67 glutKeyboardUpFunc(keyup);
69 glutMotionFunc(motion);
71 glutSpaceballMotionFunc(sball_motion);
72 glutSpaceballRotateFunc(sball_rotate);
73 glutSpaceballButtonFunc(sball_button);
88 grad_tex = gen_grad_tex(32, Vec3(0, 0, 1), Vec3(0, 1, 0));
90 glEnable(GL_DEPTH_TEST);
91 glEnable(GL_CULL_FACE);
92 // glEnable(GL_COLOR_MATERIAL);
94 glEnable(GL_LIGHTING);
97 glClearColor(0.5, 0.5, 0.5, 1);
98 meshes = load_meshes("data/head.fbx");
100 fprintf(stderr, "Failed to load mesh.\n");
104 for(size_t i=0; i<meshes.size(); i++) {
105 meshes[i]->calc_bbox();
107 Vec3 v0 = meshes[i]->bbox.v0;
108 Vec3 v1 = meshes[i]->bbox.v1;
110 printf("mesh: %s\n", meshes[i]->name.c_str());
111 printf("AABB mesh %d: v0: (%f, %f, %f) v1: (%f, %f, %f)\n",
112 (int)i, v0.x, v0.y, v0.z, v1.x, v1.y, v1.z);
114 meshes[i]->update_vbo(MESH_ALL);
116 printf("num vertices: %d num triangles: %d\n",
117 (int)meshes[i]->vertices.size(),
118 (int)meshes[i]->indices.size() / 3);
120 if(meshes[i]->name == "head") {
121 mesh_head = meshes[i];
125 fprintf(stderr, "Failed to find the head mesh.\n");
129 // coll_sphere.radius = 1.0;
130 // coll_sphere.center = Vec3(0, 0.6, 0.53);
132 if(!hair.init(mesh_head, MAX_NUM_SPAWNS, THRESH)) {
133 fprintf(stderr, "Failed to initialize hair\n");
137 // hair.add_collider(&coll_sphere);
142 static void cleanup()
144 for(size_t i=0; i<meshes.size(); i++) {
147 glDeleteTextures(1, &grad_tex);
150 static void display()
152 static unsigned long prev_time;
153 unsigned long msec = glutGet(GLUT_ELAPSED_TIME);
154 float dt = (float)(msec - prev_time) / 1000.0;
157 if(sball_update_pending) {
158 update_sball_matrix();
159 sball_update_pending = false;
162 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
164 head_xform = Mat4::identity;
165 head_xform.rotate_x(gph::deg_to_rad(head_rx));
166 head_xform.rotate_z(-gph::deg_to_rad(head_rz));
167 head_xform *= sball_xform;
169 glMatrixMode(GL_MODELVIEW);
171 glTranslatef(0, 0, -cam_dist);
172 glRotatef(cam_phi, 1, 0, 0);
173 glRotatef(cam_theta, 0, 1, 0);
174 /* multiplying with the head rot matrix */
176 glMultMatrixf(head_xform[0]);
178 glPushAttrib(GL_LINE_BIT);
180 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
182 for(size_t i=0; i<meshes.size(); i++) {
183 if(!meshes[i]->mtl.tex || meshes[i]->mtl.tex_opaque)
186 for(size_t i=0; i<meshes.size(); i++) {
187 if(meshes[i]->mtl.tex && !meshes[i]->mtl.tex_opaque)
191 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
197 hair.set_transform(head_xform);
202 glPushAttrib(GL_ENABLE_BIT);
203 glDisable(GL_DEPTH_TEST);
204 glDisable(GL_LIGHTING);
206 for (int i=0; i<500; i++) {
208 p.x = (float)rand() / RAND_MAX * 8 - 4;
209 p.y = (float)rand() / RAND_MAX * 4;
212 Vec3 tmp = inverse(head_xform) * p;
213 if(coll_sphere.contains(tmp)) {
216 else glColor3f(0, 1, 0);
218 glVertex3f(p.x, p.y, p.z);
228 glRotatef(90, 1, 0, 0);
230 glPushAttrib(GL_ENABLE_BIT);
231 glDisable(GL_LIGHTING);
232 glEnable(GL_TEXTURE_1D);
233 glBindTexture(GL_TEXTURE_1D, grad_tex);
235 glEnable(GL_TEXTURE_GEN_S);
236 glTexGenfv(GL_S, GL_OBJECT_PLANE, plane);
237 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
242 glutSolidSphere(350, 16, 8);
243 glDisable(GL_TEXTURE_1D);
245 glColor3f(0.2, 0.2, 0.2);
246 glutWireSphere(350, 32, 16);
254 draw_text("Hold h to move the head with the mouse!", 15, 15, 0.0015 * win_width, Vec3(0, 0, 0));
255 draw_text("Hold h to move the head with the mouse!", 12, 17, 0.0015 * win_width, Vec3(0.8, 0.5, 0.7));
258 assert(glGetError() == GL_NO_ERROR);
261 static void reshape(int x, int y)
263 glViewport(0, 0, x, y);
267 glMatrixMode(GL_PROJECTION);
269 gluPerspective(50.0, (float)x / (float)y, 0.5, 500.0);
272 static bool hpressed;
273 static void keydown(unsigned char key, int /*x*/, int /*y*/)
287 static void keyup(unsigned char key, int /*x*/, int /*y*/)
302 static void mouse(int bn, int st, int x, int y)
304 bnstate[bn] = st == GLUT_DOWN;
309 static void motion(int x, int y)
316 if(!dx && !dy) return;
323 if(head_rx < -45) head_rx = -45;
324 if(head_rx > 45) head_rx = 45;
326 if(head_rz < -90) head_rz = -90;
327 if(head_rz > 90) head_rz = 30;
332 cam_theta += dx * 0.5;
335 if(cam_phi < -90) cam_phi = -90;
336 if(cam_phi > 90) cam_phi = 90;
339 cam_dist += dy * 0.1;
340 if(cam_dist < 0) cam_dist = 0;
350 static void sball_motion(int x, int y, int z)
352 sball_pos.x += (float)x * 0.001;
353 sball_pos.y += (float)y * 0.001;
354 sball_pos.z -= (float)z * 0.001;
355 sball_update_pending = true;
358 static void sball_rotate(int x, int y, int z)
360 Vec3 axis = Vec3(x, y, -z);
361 float axis_len = length(axis);
362 if(axis_len > 0.0f) {
364 q.set_rotation(axis / axis_len, axis_len * 0.001);
365 sball_rot = q * sball_rot;
366 sball_update_pending = true;
370 static void sball_button(int bn, int st)
372 if(st != GLUT_DOWN) return;
374 sball_pos = Vec3(0, 0, 0);
375 sball_rot = Quat::identity;
376 sball_xform = Mat4::identity;
379 static unsigned int gen_grad_tex(int sz, const Vec3 &c0, const Vec3 &c1)
381 unsigned char *pixels = new unsigned char[sz * 3];
382 for(int i=0; i<sz; i++) {
383 float t = (float)i / (float)(sz - 1);
384 Vec3 color = c0 + (c1 - c0) * t;
385 pixels[i * 3] = color.x * 255;
386 pixels[i * 3 + 1] = color.y * 255;
387 pixels[i * 3 + 2] = color.z * 255;
391 glGenTextures(1, &tex);
392 glBindTexture(GL_TEXTURE_1D, tex);
394 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
395 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
396 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
398 glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, sz, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels);
405 static void draw_text(const char *text, int x, int y, float sz, const Vec3 &color)
407 glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT | GL_POINT_BIT);
409 glDisable(GL_DEPTH_TEST);
410 glDisable(GL_LIGHTING);
414 glMatrixMode(GL_PROJECTION);
417 glOrtho(0, win_width, 0, win_height, -1, 1);
419 glMatrixMode(GL_MODELVIEW);
422 glTranslatef(x, y, 0);
423 glScalef(0.1 * sz, 0.1 * sz, 1);
425 glColor3f(color.x, color.y, color.z);
426 while(*text != '\0') {
427 glutStrokeCharacter(GLUT_STROKE_MONO_ROMAN, *text);
431 glMatrixMode(GL_PROJECTION);
434 glMatrixMode(GL_MODELVIEW);
440 static void update_sball_matrix()
442 Mat4 rot = sball_rot.calc_matrix();
446 trans.translation(sball_pos);
448 sball_xform = rot * trans;