implementing build_bvh_sah
[cyberay] / src / main.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <assert.h>
4 #include <cgmath/cgmath.h>
5 #include "miniglut.h"
6 #include "game.h"
7 #include "level.h"
8 #include "rt.h"
9
10 enum {
11         KEY_F1          = GLUT_KEY_F1 | 0x100,
12         KEY_F2          = GLUT_KEY_F2 | 0x100,
13         KEY_F3          = GLUT_KEY_F3 | 0x100,
14         KEY_F4          = GLUT_KEY_F4 | 0x100,
15         KEY_F5          = GLUT_KEY_F5 | 0x100,
16         KEY_F6          = GLUT_KEY_F6 | 0x100,
17         KEY_F7          = GLUT_KEY_F7 | 0x100,
18         KEY_F8          = GLUT_KEY_F8 | 0x100,
19         KEY_F9          = GLUT_KEY_F9 | 0x100,
20         KEY_F10         = GLUT_KEY_F10 | 0x100,
21         KEY_F11         = GLUT_KEY_F11 | 0x100,
22         KEY_F12         = GLUT_KEY_F12 | 0x100,
23         KEY_LEFT        = GLUT_KEY_LEFT | 0x100,
24         KEY_UP          = GLUT_KEY_UP | 0x100,
25         KEY_RIGHT       = GLUT_KEY_RIGHT | 0x100,
26         KEY_DOWN        = GLUT_KEY_DOWN | 0x100,
27         KEY_PGUP        = GLUT_KEY_PAGE_UP | 0x100,
28         KEY_PGDN        = GLUT_KEY_PAGE_DOWN | 0x100,
29         KEY_HOME        = GLUT_KEY_HOME | 0x100,
30         KEY_END         = GLUT_KEY_END | 0x100,
31         KEY_INS         = GLUT_KEY_INSERT | 0x100
32 };
33
34 enum { INP_FWD, INP_BACK, INP_RIGHT, INP_LEFT, INP_FIRE, NUM_INPUTS };
35
36 static int init(void);
37 static void cleanup(void);
38 static void display(void);
39 static void idle(void);
40 static void reshape(int x, int y);
41 static void keydown(unsigned char key, int x, int y);
42 static void keyup(unsigned char key, int x, int y);
43 static void skeydown(int key, int x, int y);
44 static void skeyup(int key, int x, int y);
45 static void mouse(int bn, int st, int x, int y);
46 static void motion(int x, int y);
47 static unsigned int nextpow2(unsigned int x);
48
49 static float cam_theta, cam_phi;
50 static cgm_vec3 cam_pos = {0, 1.6, 0};
51
52 static int mouse_x, mouse_y;
53 static int bnstate[8];
54
55 static int inpstate[NUM_INPUTS];
56
57 static int keymap[NUM_INPUTS][2] = {
58         {'w', KEY_UP},
59         {'s', KEY_DOWN},
60         {'d', KEY_RIGHT},
61         {'a', KEY_LEFT},
62         {' ', 0}
63 };
64
65 static unsigned int tex;
66 static int tex_width, tex_height;
67 static int tex_intfmt;
68 static float tex_xform[16];
69
70 static unsigned long nframes;
71 static unsigned long start_time;
72
73
74 int main(int argc, char **argv)
75 {
76         glutInit(&argc, argv);
77
78         if(init_options(argc, argv) == -1) {
79                 return 1;
80         }
81
82         glutInitWindowSize(opt.width, opt.height);
83         glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
84         glutCreateWindow("cyberay");
85
86         glutDisplayFunc(display);
87         glutIdleFunc(idle);
88         glutReshapeFunc(reshape);
89         glutKeyboardFunc(keydown);
90         glutKeyboardUpFunc(keyup);
91         glutSpecialFunc(skeydown);
92         glutSpecialUpFunc(skeyup);
93         glutMouseFunc(mouse);
94         glutMotionFunc(motion);
95         glutPassiveMotionFunc(motion);
96
97         if(init() == -1) {
98                 return 1;
99         }
100         atexit(cleanup);
101
102         start_time = glutGet(GLUT_ELAPSED_TIME);
103
104         glutMainLoop();
105         return 0;
106 }
107
108 static int init(void)
109 {
110         if(!(tpool = tpool_create(0))) {
111                 fprintf(stderr, "failed to create thread pool\n");
112                 return -1;
113         }
114
115         glEnable(GL_CULL_FACE);
116
117
118         glGenTextures(1, &tex);
119         glBindTexture(GL_TEXTURE_2D, tex);
120         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
121         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
122
123         tex_intfmt = GL_RGB16F;
124
125         if(load_level(&lvl, "data/test.lvl") == -1) {
126                 return -1;
127         }
128         return 0;
129 }
130
131 static void cleanup(void)
132 {
133         float tsec;
134
135         tsec = (glutGet(GLUT_ELAPSED_TIME) - start_time) / 1000.0f;
136         printf("avg framerate: %.2f fps\n", (float)nframes / tsec);
137
138         destroy_level(&lvl);
139
140         glDeleteTextures(1, &tex);
141
142         tpool_destroy(tpool);
143 }
144
145 #define WALK_SPEED 3.0f
146 static void update(void)
147 {
148         static unsigned int prev_upd;
149         unsigned long msec;
150         float dt, vfwd, vright;
151
152         msec = glutGet(GLUT_ELAPSED_TIME) - start_time;
153         dt = (float)(msec - prev_upd) / 1000.0f;
154         prev_upd = msec;
155
156         vfwd = vright = 0;
157
158         if(inpstate[INP_FWD]) {
159                 vfwd -= WALK_SPEED * dt;
160         }
161         if(inpstate[INP_BACK]) {
162                 vfwd += WALK_SPEED * dt;
163         }
164         if(inpstate[INP_RIGHT]) {
165                 vright += WALK_SPEED * dt;
166         }
167         if(inpstate[INP_LEFT]) {
168                 vright -= WALK_SPEED * dt;
169         }
170
171         cam_pos.x += cos(cam_theta) * vright + sin(cam_theta) * vfwd;
172         cam_pos.z += -sin(cam_theta) * vright + cos(cam_theta) * vfwd;
173
174         cgm_midentity(view_xform);
175         cgm_mrotate_x(view_xform, cam_phi);
176         cgm_mrotate_y(view_xform, cam_theta);
177         cgm_mtranslate(view_xform, cam_pos.x, cam_pos.y, cam_pos.z);
178 }
179
180 static void display(void)
181 {
182         update();
183
184         render();
185         glBindTexture(GL_TEXTURE_2D, tex);
186         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, fb.width, fb.height, GL_RGB, GL_FLOAT, fb.pixels);
187         glEnable(GL_TEXTURE_2D);
188
189         glBegin(GL_QUADS);
190         glTexCoord2f(0, 1);
191         glVertex2f(-1, -1);
192         glTexCoord2f(1, 1);
193         glVertex2f(1, -1);
194         glTexCoord2f(1, 0);
195         glVertex2f(1, 1);
196         glTexCoord2f(0, 0);
197         glVertex2f(-1, 1);
198         glEnd();
199
200         glutSwapBuffers();
201         assert(glGetError() == GL_NO_ERROR);
202
203         nframes++;
204 }
205
206 static void idle(void)
207 {
208         glutPostRedisplay();
209 }
210
211 static void reshape(int x, int y)
212 {
213         glViewport(0, 0, x, y);
214
215         if(x > tex_width || y > tex_height) {
216                 tex_width = nextpow2(x);
217                 tex_height = nextpow2(y);
218
219                 glBindTexture(GL_TEXTURE_2D, tex);
220                 glTexImage2D(GL_TEXTURE_2D, 0, tex_intfmt, tex_width, tex_height, 0, GL_RGB, GL_FLOAT, 0);
221         }
222         fbsize(x, y);
223         cgm_mscaling(tex_xform, (float)x / tex_width, (float)y / tex_height, 1.0f);
224
225         glMatrixMode(GL_TEXTURE);
226         glLoadMatrixf(tex_xform);
227 }
228
229 static void keyb(int key, int press)
230 {
231         int i;
232
233         for(i=0; i<NUM_INPUTS; i++) {
234                 if(keymap[i][0] == key || keymap[i][1] == key) {
235                         inpstate[i] = press;
236                 }
237         }
238 }
239
240 static void keydown(unsigned char key, int x, int y)
241 {
242         if(key == 27) exit(0);
243         keyb(key, 1);
244 }
245
246 static void keyup(unsigned char key, int x, int y)
247 {
248         keyb(key, 0);
249 }
250
251 static void skeydown(int key, int x, int y)
252 {
253         keyb(key | 0x100, 1);
254 }
255
256 static void skeyup(int key, int x, int y)
257 {
258         keyb(key | 0x100, 0);
259 }
260
261 static void mouse(int bn, int st, int x, int y)
262 {
263         mouse_x = x;
264         mouse_y = y;
265         bnstate[bn - GLUT_LEFT_BUTTON] = st == GLUT_DOWN ? 1 : 0;
266 }
267
268 static void motion(int x, int y)
269 {
270         int dx = x - mouse_x;
271         int dy = y - mouse_y;
272         mouse_x = x;
273         mouse_y = y;
274
275         if(!(dx | dy)) return;
276
277         if(bnstate[0]) {
278                 cam_theta -= dx * 0.01;
279                 cam_phi -= dy * 0.01;
280
281                 if(cam_phi < -M_PI) cam_phi = -M_PI;
282                 if(cam_phi > M_PI) cam_phi = M_PI;
283         }
284 }
285
286 static unsigned int nextpow2(unsigned int x)
287 {
288         x--;
289         x |= x >> 1;
290         x |= x >> 2;
291         x |= x >> 4;
292         x |= x >> 8;
293         x |= x >> 16;
294         return x + 1;
295 }