Failed hack for collision detection with a sphere.
[hair] / src / main.cc
1 #include <GL/glew.h>
2 #include <GL/glut.h>
3
4 #include <assert.h>
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <string>
8
9 #include <gmath/gmath.h>
10
11 #include "mesh.h"
12 #include "hair.h"
13 #include "object.h"
14
15 #define MAX_NUM_SPAWNS 400
16 #define THRESH 0.5
17
18 static bool init();
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);
26 static void idle();
27
28 static std::vector<Mesh*> meshes;
29 static Mesh *mesh_head;
30 static Hair hair;
31
32 static int win_width, win_height;
33 static float cam_theta, cam_phi = 25, cam_dist = 8;
34 static float head_rz, head_rx; /* rot angles x, z axis */
35 static Mat4 head_xform;
36 static CollSphere coll_sphere; /* sphere used for collision detection */
37
38 int main(int argc, char **argv)
39 {
40         glutInit(&argc, argv);
41         glutInitWindowSize(800, 600);
42         glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
43         glutCreateWindow("hair test");
44
45         /* for the keydown, keyup functions to work */
46         glutSetKeyRepeat(GLUT_KEY_REPEAT_OFF);
47
48         glutDisplayFunc(display);
49         glutReshapeFunc(reshape);
50         glutKeyboardFunc(keydown);
51         glutKeyboardUpFunc(keyup);
52         glutMouseFunc(mouse);
53         glutMotionFunc(motion);
54         glutIdleFunc(idle);
55
56         if(!init()) {
57                 return 1;
58         }
59         atexit(cleanup);
60
61         glutMainLoop();
62         return 0;
63 }
64
65 static bool init()
66 {
67         glewInit();
68
69         glEnable(GL_DEPTH_TEST);
70         glEnable(GL_CULL_FACE);
71         glEnable(GL_COLOR_MATERIAL);
72
73         glEnable(GL_LIGHTING);
74         glEnable(GL_LIGHT0);
75
76         glClearColor(0.5, 0.5, 0.5, 1);
77         meshes = load_meshes("data/head.fbx");
78         if (meshes.empty()) {
79                 fprintf(stderr, "Failed to load mesh.\n");
80                 return false;
81         }
82
83         for(size_t i=0; i<meshes.size(); i++) {
84                 meshes[i]->calc_bbox();
85 /*
86                 Vec3 v0 = meshes[i]->bbox.v0;
87                 Vec3 v1 = meshes[i]->bbox.v1;
88
89                 printf("mesh: %s\n", meshes[i]->name.c_str());
90                 printf("AABB mesh %d: v0: (%f, %f, %f) v1: (%f, %f, %f)\n",
91                                 (int)i, v0.x, v0.y, v0.z, v1.x, v1.y, v1.z);
92 */
93                 meshes[i]->update_vbo(MESH_ALL);
94 /*
95                 printf("num vertices: %d num triangles: %d\n",
96                                 (int)meshes[i]->vertices.size(),
97                                 (int)meshes[i]->indices.size() / 3);
98 */
99                 if(meshes[i]->name == "head") {
100                         mesh_head = meshes[i];
101                 }
102         }
103         if(!mesh_head) {
104                 fprintf(stderr, "Failed to find the head mesh.\n");
105                 return false;
106         }
107
108         coll_sphere.radius = 1.0;
109         coll_sphere.center = Vec3(0, 0.6, 0.53);
110
111         if(!hair.init(mesh_head, MAX_NUM_SPAWNS, THRESH)) {
112                 fprintf(stderr, "Failed to initialize hair\n");
113                 return false;
114         }
115
116         hair.add_collider(&coll_sphere);
117
118         return true;
119 }
120
121 static void cleanup()
122 {
123         for(size_t i=0; i<meshes.size(); i++) {
124                 delete meshes[i];
125         }
126 }
127
128 static void display()
129 {
130         static unsigned long prev_time;
131         unsigned long msec = glutGet(GLUT_ELAPSED_TIME);
132         float dt = (float)(msec - prev_time) / 1000.0;
133         prev_time = msec;
134
135         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
136
137         head_xform = Mat4::identity;
138         head_xform.rotate_x(gph::deg_to_rad(head_rx));
139         head_xform.rotate_z(-gph::deg_to_rad(head_rz));
140
141         glMatrixMode(GL_MODELVIEW);
142         glLoadIdentity();
143         glTranslatef(0, 0, -cam_dist);
144         glRotatef(cam_phi, 1, 0, 0);
145         glRotatef(cam_theta, 0, 1, 0);
146         /* multiplying with the head rot matrix */
147         glPushMatrix();
148         glMultMatrixf(head_xform[0]);
149         glPushAttrib(GL_LINE_BIT);
150         glLineWidth(1);
151         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
152         for(size_t i=0; i<meshes.size(); i++) {
153                 meshes[i]->draw();
154         }
155         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
156         glPopAttrib();
157
158         glPopMatrix();
159
160         hair.set_transform(head_xform);
161         hair.update(dt);
162         hair.draw();
163
164 /*
165         glPushAttrib(GL_ENABLE_BIT);
166         glDisable(GL_DEPTH_TEST);
167         glDisable(GL_LIGHTING);
168         glBegin(GL_POINTS);
169         for (int i=0; i<500; i++) {
170                 Vec3 p;
171                 p.x = (float)rand() / RAND_MAX * 8 - 4;
172                 p.y = (float)rand() / RAND_MAX * 4;
173                 p.z = 0;
174
175                 Vec3 tmp = inverse(head_xform) * p;
176                 if(coll_sphere.contains(tmp)) {
177                         glColor3f(1, 0, 0);
178                 }
179                 else glColor3f(0, 1, 0);
180
181                 glVertex3f(p.x, p.y, p.z);
182         }
183         glEnd();
184         glPopAttrib();
185         */
186
187         glutSwapBuffers();
188         assert(glGetError() == GL_NO_ERROR);
189 }
190
191 static void reshape(int x, int y)
192 {
193         glViewport(0, 0, x, y);
194         win_width = x;
195         win_height = y;
196
197         glMatrixMode(GL_PROJECTION);
198         glLoadIdentity();
199         gluPerspective(50.0, (float)x / (float)y, 0.5, 500.0);
200 }
201
202 static bool hpressed;
203 static void keydown(unsigned char key, int /*x*/, int /*y*/)
204 {
205         switch(key) {
206         case 'h':
207         case 'H':
208                 hpressed = true;
209                 break;
210         case 27:
211                 exit(0);
212         default:
213                 break;
214         }
215 }
216
217 static void keyup(unsigned char key, int /*x*/, int /*y*/)
218 {
219         switch(key) {
220         case 'h':
221         case 'H':
222                 hpressed = false;
223                 break;
224         default:
225                 break;
226         }
227 }
228
229 bool bnstate[8];
230 int prev_x, prev_y;
231
232 static void mouse(int bn, int st, int x, int y)
233 {
234         bnstate[bn] = st == GLUT_DOWN;
235         prev_x = x;
236         prev_y = y;
237 }
238
239 static void motion(int x, int y)
240 {
241         int dx = x - prev_x;
242         int dy = y - prev_y;
243         prev_x = x;
244         prev_y = y;
245
246         if(!dx && !dy) return;
247
248         if(hpressed) {
249                 if(bnstate[0]) {
250                         head_rz += dx * 0.5;
251                         head_rx += dy * 0.5;
252
253                         if(head_rx < -45) head_rx = -45;
254                         if(head_rx > 45) head_rx = 45;
255
256                         if(head_rz < -90) head_rz = -90;
257                         if(head_rz > 90) head_rz = 30;
258                 }
259         }
260         else {
261                 if(bnstate[0]) {
262                         cam_theta += dx * 0.5;
263                         cam_phi += dy * 0.5;
264
265                         if(cam_phi < -90) cam_phi = -90;
266                         if(cam_phi > 90) cam_phi = 90;
267                 }
268                 if(bnstate[2]) {
269                         cam_dist += dy * 0.1;
270                         if(cam_dist < 0) cam_dist = 0;
271                 }
272         }
273 }
274
275 static void idle()
276 {
277         glutPostRedisplay();
278 }