multithreaded render
[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 long start_time;
50
51 static float cam_theta, cam_phi;
52 static cgm_vec3 cam_pos = {0, -1.6, 0};
53
54 static int mouse_x, mouse_y;
55 static int bnstate[8];
56
57 static int inpstate[NUM_INPUTS];
58
59 static int keymap[NUM_INPUTS][2] = {
60         {'w', KEY_UP},
61         {'s', KEY_DOWN},
62         {'d', KEY_RIGHT},
63         {'a', KEY_LEFT},
64         {' ', 0}
65 };
66
67 static unsigned int tex;
68 static int tex_width, tex_height;
69 static int tex_intfmt;
70 static float tex_xform[16];
71
72
73 int main(int argc, char **argv)
74 {
75         glutInit(&argc, argv);
76         glutInitWindowSize(1280, 800);
77         glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
78         glutCreateWindow("cyberay");
79
80         glutDisplayFunc(display);
81         glutIdleFunc(idle);
82         glutReshapeFunc(reshape);
83         glutKeyboardFunc(keydown);
84         glutKeyboardUpFunc(keyup);
85         glutSpecialFunc(skeydown);
86         glutSpecialUpFunc(skeyup);
87         glutMouseFunc(mouse);
88         glutMotionFunc(motion);
89         glutPassiveMotionFunc(motion);
90
91         if(init() == -1) {
92                 return 1;
93         }
94         atexit(cleanup);
95
96         glutMainLoop();
97         return 0;
98 }
99
100 static int init(void)
101 {
102         if(!(tpool = tpool_create(0))) {
103                 fprintf(stderr, "failed to create thread pool\n");
104                 return -1;
105         }
106
107         glEnable(GL_CULL_FACE);
108
109         /*
110         glEnable(GL_DEPTH_TEST);
111         glEnable(GL_LIGHTING);
112         glEnable(GL_LIGHT0);
113         */
114
115         glGenTextures(1, &tex);
116         glBindTexture(GL_TEXTURE_2D, tex);
117         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
118         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
119
120         tex_intfmt = GL_RGB16F;
121
122         if(load_level(&lvl, "data/test.lvl") == -1) {
123                 return -1;
124         }
125
126         start_time = glutGet(GLUT_ELAPSED_TIME);
127         return 0;
128 }
129
130 static void cleanup(void)
131 {
132         destroy_level(&lvl);
133
134         glDeleteTextures(1, &tex);
135
136         tpool_destroy(tpool);
137 }
138
139 #define WALK_SPEED 3.0f
140 static void update(void)
141 {
142         static unsigned int prev_upd;
143         unsigned int msec;
144         float dt, vfwd, vright;
145
146         msec = glutGet(GLUT_ELAPSED_TIME) - start_time;
147         dt = (float)(msec - prev_upd) / 1000.0f;
148         prev_upd = msec;
149
150         vfwd = vright = 0;
151
152         if(inpstate[INP_FWD]) {
153                 vfwd -= WALK_SPEED * dt;
154         }
155         if(inpstate[INP_BACK]) {
156                 vfwd += WALK_SPEED * dt;
157         }
158         if(inpstate[INP_RIGHT]) {
159                 vright -= WALK_SPEED * dt;
160         }
161         if(inpstate[INP_LEFT]) {
162                 vright += WALK_SPEED * dt;
163         }
164
165         cam_pos.x += cos(cam_theta) * vright + sin(cam_theta) * vfwd;
166         cam_pos.z += sin(cam_theta) * vright - cos(cam_theta) * vfwd;
167
168         cgm_midentity(view_xform);
169         cgm_mtranslate(view_xform, cam_pos.x, cam_pos.y, cam_pos.z);
170         cgm_mrotate_y(view_xform, cam_theta);
171         cgm_mrotate_x(view_xform, cam_phi);
172 }
173
174 static void display(void)
175 {
176         update();
177
178         render();
179         glBindTexture(GL_TEXTURE_2D, tex);
180         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, fb.width, fb.height, GL_RGB, GL_FLOAT, fb.pixels);
181         glEnable(GL_TEXTURE_2D);
182
183         glBegin(GL_QUADS);
184         glTexCoord2f(0, 0);
185         glVertex2f(-1, -1);
186         glTexCoord2f(1, 0);
187         glVertex2f(1, -1);
188         glTexCoord2f(1, 1);
189         glVertex2f(1, 1);
190         glTexCoord2f(0, 1);
191         glVertex2f(-1, 1);
192         glEnd();
193
194         /*
195         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
196
197         glMatrixMode(GL_MODELVIEW);
198         glLoadMatrixf(view_xform);
199
200         draw_level(&lvl);
201         */
202
203         glutSwapBuffers();
204         assert(glGetError() == GL_NO_ERROR);
205 }
206
207 static void idle(void)
208 {
209         glutPostRedisplay();
210 }
211
212 static void reshape(int x, int y)
213 {
214         glViewport(0, 0, x, y);
215         /*
216         float proj[16];
217
218         cgm_mperspective(proj, cgm_deg_to_rad(50.0f), (float)x / (float)y, 0.5, 500.0);
219
220         glMatrixMode(GL_PROJECTION);
221         glLoadMatrixf(proj);
222         */
223
224         if(x > tex_width || y > tex_height) {
225                 tex_width = nextpow2(x);
226                 tex_height = nextpow2(y);
227
228                 glBindTexture(GL_TEXTURE_2D, tex);
229                 glTexImage2D(GL_TEXTURE_2D, 0, tex_intfmt, tex_width, tex_height, 0, GL_RGB, GL_FLOAT, 0);
230         }
231         fbsize(x, y);
232         cgm_mscaling(tex_xform, (float)x / tex_width, (float)y / tex_height, 1.0f);
233
234         glMatrixMode(GL_TEXTURE);
235         glLoadMatrixf(tex_xform);
236 }
237
238 static void keyb(int key, int press)
239 {
240         int i;
241
242         for(i=0; i<NUM_INPUTS; i++) {
243                 if(keymap[i][0] == key || keymap[i][1] == key) {
244                         inpstate[i] = press;
245                 }
246         }
247 }
248
249 static void keydown(unsigned char key, int x, int y)
250 {
251         if(key == 27) exit(0);
252         keyb(key, 1);
253 }
254
255 static void keyup(unsigned char key, int x, int y)
256 {
257         keyb(key, 0);
258 }
259
260 static void skeydown(int key, int x, int y)
261 {
262         keyb(key | 0x100, 1);
263 }
264
265 static void skeyup(int key, int x, int y)
266 {
267         keyb(key | 0x100, 0);
268 }
269
270 static void mouse(int bn, int st, int x, int y)
271 {
272         mouse_x = x;
273         mouse_y = y;
274         bnstate[bn - GLUT_LEFT_BUTTON] = st == GLUT_DOWN ? 1 : 0;
275 }
276
277 static void motion(int x, int y)
278 {
279         int dx = x - mouse_x;
280         int dy = y - mouse_y;
281         mouse_x = x;
282         mouse_y = y;
283
284         if(!(dx | dy)) return;
285
286         if(bnstate[0]) {
287                 cam_theta += dx * 0.01;
288                 cam_phi += dy * 0.01;
289
290                 if(cam_phi < -M_PI) cam_phi = -M_PI;
291                 if(cam_phi > M_PI) cam_phi = M_PI;
292         }
293 }
294
295 static unsigned int nextpow2(unsigned int x)
296 {
297         x--;
298         x |= x >> 1;
299         x |= x >> 2;
300         x |= x >> 4;
301         x |= x >> 8;
302         x |= x >> 16;
303         return x + 1;
304 }