Replaced the collision detection with a check of the angle
[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 /*
150         glPushAttrib(GL_LINE_BIT);
151         glLineWidth(1);
152         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
153 */
154         for(size_t i=0; i<meshes.size(); i++) {
155                 meshes[i]->draw();
156         }
157 /*
158         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
159         glPopAttrib();
160 */
161
162         glPopMatrix();
163
164         hair.set_transform(head_xform);
165         hair.update(dt);
166         hair.draw();
167
168 /*
169         glPushAttrib(GL_ENABLE_BIT);
170         glDisable(GL_DEPTH_TEST);
171         glDisable(GL_LIGHTING);
172         glBegin(GL_POINTS);
173         for (int i=0; i<500; i++) {
174                 Vec3 p;
175                 p.x = (float)rand() / RAND_MAX * 8 - 4;
176                 p.y = (float)rand() / RAND_MAX * 4;
177                 p.z = 0;
178
179                 Vec3 tmp = inverse(head_xform) * p;
180                 if(coll_sphere.contains(tmp)) {
181                         glColor3f(1, 0, 0);
182                 }
183                 else glColor3f(0, 1, 0);
184
185                 glVertex3f(p.x, p.y, p.z);
186         }
187         glEnd();
188         glPopAttrib();
189 */
190
191         glutSwapBuffers();
192         assert(glGetError() == GL_NO_ERROR);
193 }
194
195 static void reshape(int x, int y)
196 {
197         glViewport(0, 0, x, y);
198         win_width = x;
199         win_height = y;
200
201         glMatrixMode(GL_PROJECTION);
202         glLoadIdentity();
203         gluPerspective(50.0, (float)x / (float)y, 0.5, 500.0);
204 }
205
206 static bool hpressed;
207 static void keydown(unsigned char key, int /*x*/, int /*y*/)
208 {
209         switch(key) {
210         case 'h':
211         case 'H':
212                 hpressed = true;
213                 break;
214         case 27:
215                 exit(0);
216         default:
217                 break;
218         }
219 }
220
221 static void keyup(unsigned char key, int /*x*/, int /*y*/)
222 {
223         switch(key) {
224         case 'h':
225         case 'H':
226                 hpressed = false;
227                 break;
228         default:
229                 break;
230         }
231 }
232
233 bool bnstate[8];
234 int prev_x, prev_y;
235
236 static void mouse(int bn, int st, int x, int y)
237 {
238         bnstate[bn] = st == GLUT_DOWN;
239         prev_x = x;
240         prev_y = y;
241 }
242
243 static void motion(int x, int y)
244 {
245         int dx = x - prev_x;
246         int dy = y - prev_y;
247         prev_x = x;
248         prev_y = y;
249
250         if(!dx && !dy) return;
251
252         if(hpressed) {
253                 if(bnstate[0]) {
254                         head_rz += dx * 0.5;
255                         head_rx += dy * 0.5;
256
257                         if(head_rx < -45) head_rx = -45;
258                         if(head_rx > 45) head_rx = 45;
259
260                         if(head_rz < -90) head_rz = -90;
261                         if(head_rz > 90) head_rz = 30;
262                 }
263         }
264         else {
265                 if(bnstate[0]) {
266                         cam_theta += dx * 0.5;
267                         cam_phi += dy * 0.5;
268
269                         if(cam_phi < -90) cam_phi = -90;
270                         if(cam_phi > 90) cam_phi = 90;
271                 }
272                 if(bnstate[2]) {
273                         cam_dist += dy * 0.1;
274                         if(cam_dist < 0) cam_dist = 0;
275                 }
276         }
277 }
278
279 static void idle()
280 {
281         glutPostRedisplay();
282 }