head motion
[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
14 #define MAX_NUM_SPAWNS 4
15 #define THRESH 0.5
16
17 static bool init();
18 static void cleanup();
19 static void display();
20 static void reshape(int x, int y);
21 static void keydown(unsigned char key, int x, int y);
22 static void keyup(unsigned char key, int x, int y);
23 static void mouse(int bn, int st, int x, int y);
24 static void motion(int x, int y);
25 static void idle();
26
27 static std::vector<Mesh*> meshes;
28 static Mesh *mesh_head;
29 static Hair hair;
30
31 static int win_width, win_height;
32 static float cam_theta, cam_phi = 25, cam_dist = 8;
33 static float head_rz, head_rx; /* rot angles x, z axis */
34 static Mat4 head_xform;
35
36 int main(int argc, char **argv)
37 {
38         glutInit(&argc, argv);
39         glutInitWindowSize(800, 600);
40         glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
41         glutCreateWindow("hair test");
42
43         /* for the keydown, keyup functions to work */
44         glutSetKeyRepeat(GLUT_KEY_REPEAT_OFF);
45
46         glutDisplayFunc(display);
47         glutReshapeFunc(reshape);
48         glutKeyboardFunc(keydown);
49         glutKeyboardUpFunc(keyup);
50         glutMouseFunc(mouse);
51         glutMotionFunc(motion);
52         glutIdleFunc(idle);
53
54         if(!init()) {
55                 return 1;
56         }
57         atexit(cleanup);
58
59         glutMainLoop();
60         return 0;
61 }
62
63 static bool init()
64 {
65         glewInit();
66
67         glEnable(GL_DEPTH_TEST);
68         glEnable(GL_CULL_FACE);
69         glEnable(GL_COLOR_MATERIAL);
70
71         glEnable(GL_LIGHTING);
72         glEnable(GL_LIGHT0);
73
74         glClearColor(0.5, 0.5, 0.5, 1);
75         meshes = load_meshes("data/head.fbx");
76         if (meshes.empty()) {
77                 fprintf(stderr, "Failed to load mesh.\n");
78                 return false;
79         }
80
81         for(size_t i=0; i<meshes.size(); i++) {
82                 meshes[i]->calc_bbox();
83 /*
84                 Vec3 v0 = meshes[i]->bbox.v0;
85                 Vec3 v1 = meshes[i]->bbox.v1;
86
87                 printf("mesh: %s\n", meshes[i]->name.c_str());
88                 printf("AABB mesh %d: v0: (%f, %f, %f) v1: (%f, %f, %f)\n",
89                                 (int)i, v0.x, v0.y, v0.z, v1.x, v1.y, v1.z);
90 */
91                 meshes[i]->update_vbo(MESH_ALL);
92 /*
93                 printf("num vertices: %d num triangles: %d\n",
94                                 (int)meshes[i]->vertices.size(),
95                                 (int)meshes[i]->indices.size() / 3);
96 */
97                 if(meshes[i]->name == "head") {
98                         mesh_head = meshes[i];
99                 }
100         }
101         if(!mesh_head) {
102                 fprintf(stderr, "Failed to find the head mesh.\n");
103                 return false;
104         }
105
106         if(!hair.init(mesh_head, MAX_NUM_SPAWNS, THRESH)) {
107                 fprintf(stderr, "Failed to initialize hair\n");
108                 return false;
109         }
110
111         return true;
112 }
113
114 static void cleanup()
115 {
116         for(size_t i=0; i<meshes.size(); i++) {
117                 delete meshes[i];
118         }
119 }
120
121 static void display()
122 {
123         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
124
125         head_xform = Mat4::identity;
126         head_xform.rotate_x(gph::deg_to_rad(head_rx));
127         head_xform.rotate_z(-gph::deg_to_rad(head_rz));
128
129         glMatrixMode(GL_MODELVIEW);
130         glLoadIdentity();
131         glTranslatef(0, 0, -cam_dist);
132         glRotatef(cam_phi, 1, 0, 0);
133         glRotatef(cam_theta, 0, 1, 0);
134
135         glMultMatrixf(head_xform[0]);
136
137         for(size_t i=0; i<meshes.size(); i++) {
138                 meshes[i]->draw();
139         }
140
141         hair.draw();
142
143         glutSwapBuffers();
144         assert(glGetError() == GL_NO_ERROR);
145 }
146
147 static void reshape(int x, int y)
148 {
149         glViewport(0, 0, x, y);
150         win_width = x;
151         win_height = y;
152
153         glMatrixMode(GL_PROJECTION);
154         glLoadIdentity();
155         gluPerspective(50.0, (float)x / (float)y, 0.5, 500.0);
156 }
157
158 static bool hpressed;
159 static void keydown(unsigned char key, int /*x*/, int /*y*/)
160 {
161         switch(key) {
162         case 'h':
163         case 'H':
164                 hpressed = true;
165                 break;
166         case 27:
167                 exit(0);
168         default:
169                 break;
170         }
171 }
172
173 static void keyup(unsigned char key, int /*x*/, int /*y*/)
174 {
175         switch(key) {
176         case 'h':
177         case 'H':
178                 hpressed = false;
179                 break;
180         default:
181                 break;
182         }
183 }
184
185 bool bnstate[8];
186 int prev_x, prev_y;
187
188 static void mouse(int bn, int st, int x, int y)
189 {
190         bnstate[bn] = st == GLUT_DOWN;
191         prev_x = x;
192         prev_y = y;
193 }
194
195 static void motion(int x, int y)
196 {
197         int dx = x - prev_x;
198         int dy = y - prev_y;
199         prev_x = x;
200         prev_y = y;
201
202         if(!dx && !dy) return;
203
204         if(hpressed) {
205                 if(bnstate[0]) {
206                         head_rz += dx * 0.5;
207                         head_rx += dy * 0.5;
208
209                         if(head_rx < -45) head_rx = -45;
210                         if(head_rx > 45) head_rx = 45;
211
212                         if(head_rz < -90) head_rz = -90;
213                         if(head_rz > 90) head_rx = 90;
214                 }
215         }
216         else {
217                 if(bnstate[0]) {
218                         cam_theta += dx * 0.5;
219                         cam_phi += dy * 0.5;
220
221                         if(cam_phi < -90) cam_phi = -90;
222                         if(cam_phi > 90) cam_phi = 90;
223                 }
224                 if(bnstate[2]) {
225                         cam_dist += dy * 0.1;
226                         if(cam_dist < 0) cam_dist = 0;
227                 }
228         }
229 }
230
231 static void idle()
232 {
233         glutPostRedisplay();
234 }