rev |
line source |
nuclear@1
|
1 #include <stdio.h>
|
nuclear@1
|
2 #include <stdlib.h>
|
nuclear@1
|
3 #include <assert.h>
|
nuclear@7
|
4 #include <unistd.h>
|
nuclear@1
|
5 #include "opengl.h"
|
nuclear@46
|
6 #include "psys/psys.h"
|
nuclear@1
|
7 #include "level.h"
|
nuclear@46
|
8 #include "texman.h"
|
nuclear@1
|
9 #include "camera.h"
|
nuclear@5
|
10 #include "datapath.h"
|
nuclear@5
|
11 #include "tileset.h"
|
nuclear@15
|
12 #include "renderer.h"
|
nuclear@41
|
13 #include "renderer_deferred.h"
|
nuclear@24
|
14 #include "cmdcon.h"
|
nuclear@18
|
15 #include "cfg.h"
|
nuclear@38
|
16 #include "timer.h"
|
nuclear@47
|
17 #include "audio.h"
|
nuclear@1
|
18
|
nuclear@17
|
19 bool init(int xsz, int ysz);
|
nuclear@5
|
20 void cleanup();
|
nuclear@7
|
21 void idle();
|
nuclear@1
|
22 void disp();
|
nuclear@15
|
23 void draw();
|
nuclear@18
|
24 void view_matrix(int eye);
|
nuclear@18
|
25 void proj_matrix(int eye);
|
nuclear@7
|
26 void update(unsigned long msec);
|
nuclear@1
|
27 void reshape(int x, int y);
|
nuclear@1
|
28 void keyb(unsigned char key, int x, int y);
|
nuclear@7
|
29 void key_release(unsigned char key, int x, int y);
|
nuclear@24
|
30 void keyb_con(unsigned char key, int x, int y);
|
nuclear@1
|
31 void mouse(int bn, int state, int x, int y);
|
nuclear@1
|
32 void motion(int x, int y);
|
nuclear@46
|
33 unsigned int load_psys_tex(const char *fname, void *cls);
|
nuclear@1
|
34
|
nuclear@5
|
35 static TileSet *tileset;
|
nuclear@1
|
36 static Level *level;
|
nuclear@7
|
37
|
nuclear@7
|
38 static FpsCamera cam;
|
nuclear@7
|
39 static bool keystate[256];
|
nuclear@1
|
40
|
nuclear@18
|
41 static float stereo_focus_dist = 0.25;
|
nuclear@18
|
42 static float stereo_eye_sep = stereo_focus_dist / 30.0;
|
nuclear@18
|
43
|
nuclear@24
|
44 static bool show_con;
|
nuclear@5
|
45
|
nuclear@1
|
46 int main(int argc, char **argv)
|
nuclear@1
|
47 {
|
nuclear@1
|
48 glutInit(&argc, argv);
|
nuclear@5
|
49
|
nuclear@18
|
50 if(!cfg.parse_args(argc, argv)) {
|
nuclear@18
|
51 return 1;
|
nuclear@5
|
52 }
|
nuclear@5
|
53
|
nuclear@18
|
54 glutInitWindowSize(cfg.width, cfg.height);
|
nuclear@18
|
55 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE | (cfg.stereo ? GLUT_STEREO : 0));
|
nuclear@18
|
56 glutCreateWindow("dungeon crawler prototype");
|
nuclear@1
|
57
|
nuclear@7
|
58 glutIdleFunc(idle);
|
nuclear@1
|
59 glutDisplayFunc(disp);
|
nuclear@1
|
60 glutReshapeFunc(reshape);
|
nuclear@1
|
61 glutKeyboardFunc(keyb);
|
nuclear@7
|
62 glutKeyboardUpFunc(key_release);
|
nuclear@1
|
63 glutMouseFunc(mouse);
|
nuclear@1
|
64 glutMotionFunc(motion);
|
nuclear@1
|
65
|
nuclear@1
|
66 glewInit();
|
nuclear@1
|
67
|
nuclear@18
|
68 if(!init(cfg.width, cfg.height)) {
|
nuclear@5
|
69 return 1;
|
nuclear@5
|
70 }
|
nuclear@39
|
71 atexit(cleanup);
|
nuclear@5
|
72
|
nuclear@5
|
73 glutMainLoop();
|
nuclear@5
|
74 }
|
nuclear@5
|
75
|
nuclear@17
|
76 bool init(int xsz, int ysz)
|
nuclear@5
|
77 {
|
nuclear@41
|
78 // backup light for the forward crappy renderer
|
nuclear@1
|
79 glEnable(GL_LIGHTING);
|
nuclear@1
|
80 glEnable(GL_LIGHT0);
|
nuclear@41
|
81
|
nuclear@41
|
82 float ldir[] = {0, 0, -0.5, 1};
|
nuclear@1
|
83 glLightfv(GL_LIGHT0, GL_POSITION, ldir);
|
nuclear@41
|
84 float lcol[] = {1, 1, 1, 1};
|
nuclear@41
|
85 glLightfv(GL_LIGHT0, GL_DIFFUSE, lcol);
|
nuclear@41
|
86 glLightfv(GL_LIGHT0, GL_SPECULAR, lcol);
|
nuclear@1
|
87
|
nuclear@1
|
88 glEnable(GL_DEPTH_TEST);
|
nuclear@1
|
89 glEnable(GL_CULL_FACE);
|
nuclear@1
|
90 glEnable(GL_MULTISAMPLE);
|
nuclear@1
|
91
|
nuclear@25
|
92 add_data_path(".");
|
nuclear@5
|
93 add_data_path("data");
|
nuclear@16
|
94 add_data_path("sdr");
|
nuclear@5
|
95
|
nuclear@41
|
96 rend = new DeferredRenderer();
|
nuclear@42
|
97 if(!cfg.use_deferred || !rend->init(xsz, ysz)) {
|
nuclear@41
|
98 printf("falling back to crappy renderer...\n");
|
nuclear@41
|
99
|
nuclear@41
|
100 rend = new FwdRenderer();
|
nuclear@41
|
101 if(!rend->init(xsz, ysz)) {
|
nuclear@41
|
102 fprintf(stderr, "failed to create renderer\n");
|
nuclear@41
|
103 return false;
|
nuclear@41
|
104 }
|
nuclear@15
|
105 }
|
nuclear@15
|
106
|
nuclear@26
|
107 if(!init_cmdcon()) {
|
nuclear@26
|
108 return false;
|
nuclear@26
|
109 }
|
nuclear@26
|
110
|
nuclear@46
|
111 psys_texture_loader(load_psys_tex, 0, 0);
|
nuclear@46
|
112
|
nuclear@5
|
113 // load a tileset
|
nuclear@5
|
114 tileset = new TileSet;
|
nuclear@18
|
115 printf("loading tileset: %s\n", cfg.tileset_file);
|
nuclear@18
|
116 if(!tileset->load(datafile_path(cfg.tileset_file))) {
|
nuclear@5
|
117 return false;
|
nuclear@5
|
118 }
|
nuclear@5
|
119 set_active_tileset(tileset);
|
nuclear@5
|
120
|
nuclear@1
|
121 level = new Level;
|
nuclear@18
|
122 printf("loading level: %s\n", cfg.level_file);
|
nuclear@18
|
123 if(!level->load(datafile_path(cfg.level_file))) {
|
nuclear@5
|
124 return false;
|
nuclear@1
|
125 }
|
nuclear@1
|
126
|
nuclear@7
|
127 cam.input_move(0, 0.5, 0);
|
nuclear@7
|
128
|
nuclear@47
|
129 if(cfg.sound && !init_audio()) {
|
nuclear@47
|
130 fprintf(stderr, "failed to initialize audio, continuing silently\n");
|
nuclear@47
|
131 cfg.sound = false;
|
nuclear@47
|
132 }
|
nuclear@47
|
133
|
nuclear@5
|
134 return true;
|
nuclear@1
|
135 }
|
nuclear@1
|
136
|
nuclear@15
|
137 void cleanup()
|
nuclear@15
|
138 {
|
nuclear@47
|
139 if(cfg.sound) {
|
nuclear@47
|
140 destroy_audio();
|
nuclear@47
|
141 }
|
nuclear@47
|
142
|
nuclear@15
|
143 delete level;
|
nuclear@15
|
144 delete tileset;
|
nuclear@41
|
145 delete rend;
|
nuclear@26
|
146
|
nuclear@26
|
147 cleanup_cmdcon();
|
nuclear@15
|
148 }
|
nuclear@15
|
149
|
nuclear@7
|
150 void idle()
|
nuclear@7
|
151 {
|
nuclear@7
|
152 glutPostRedisplay();
|
nuclear@7
|
153 }
|
nuclear@7
|
154
|
nuclear@1
|
155 void disp()
|
nuclear@1
|
156 {
|
nuclear@38
|
157 update(get_time_msec());
|
nuclear@7
|
158
|
nuclear@18
|
159 if(cfg.stereo) {
|
nuclear@18
|
160 glDrawBuffer(GL_BACK_LEFT);
|
nuclear@1
|
161
|
nuclear@18
|
162 glMatrixMode(GL_PROJECTION);
|
nuclear@18
|
163 glLoadIdentity();
|
nuclear@18
|
164 proj_matrix(-1);
|
nuclear@18
|
165 glMatrixMode(GL_MODELVIEW);
|
nuclear@18
|
166 glLoadIdentity();
|
nuclear@18
|
167 view_matrix(-1);
|
nuclear@1
|
168
|
nuclear@24
|
169 draw();
|
nuclear@18
|
170
|
nuclear@18
|
171 glDrawBuffer(GL_BACK_RIGHT);
|
nuclear@18
|
172
|
nuclear@18
|
173 glMatrixMode(GL_PROJECTION);
|
nuclear@18
|
174 glLoadIdentity();
|
nuclear@18
|
175 proj_matrix(1);
|
nuclear@18
|
176 glMatrixMode(GL_MODELVIEW);
|
nuclear@18
|
177 glLoadIdentity();
|
nuclear@18
|
178 view_matrix(1);
|
nuclear@18
|
179
|
nuclear@24
|
180 draw();
|
nuclear@18
|
181 } else {
|
nuclear@18
|
182 glMatrixMode(GL_PROJECTION);
|
nuclear@18
|
183 glLoadIdentity();
|
nuclear@18
|
184 proj_matrix(0);
|
nuclear@18
|
185 glMatrixMode(GL_MODELVIEW);
|
nuclear@18
|
186 glLoadIdentity();
|
nuclear@18
|
187 view_matrix(0);
|
nuclear@18
|
188
|
nuclear@24
|
189 draw();
|
nuclear@18
|
190 }
|
nuclear@1
|
191
|
nuclear@1
|
192 glutSwapBuffers();
|
nuclear@1
|
193 assert(glGetError() == GL_NO_ERROR);
|
nuclear@7
|
194 }
|
nuclear@7
|
195
|
nuclear@24
|
196 void draw()
|
nuclear@24
|
197 {
|
nuclear@41
|
198 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
nuclear@29
|
199
|
nuclear@41
|
200 rend->render(level);
|
nuclear@24
|
201
|
nuclear@24
|
202 if(show_con) {
|
nuclear@24
|
203 draw_cmdcon();
|
nuclear@24
|
204 }
|
nuclear@24
|
205 }
|
nuclear@24
|
206
|
nuclear@18
|
207 void view_matrix(int eye)
|
nuclear@18
|
208 {
|
nuclear@18
|
209 float offs = stereo_eye_sep * eye * 0.5;
|
nuclear@18
|
210 glTranslatef(-offs, 0, 0);
|
nuclear@18
|
211 cam.use_inverse();
|
nuclear@18
|
212 }
|
nuclear@18
|
213
|
nuclear@18
|
214 void proj_matrix(int eye)
|
nuclear@18
|
215 {
|
nuclear@18
|
216 static const float fov = M_PI / 4.0;
|
nuclear@18
|
217 static const float near_clip = 0.1;
|
nuclear@18
|
218 static const float far_clip = 100.0;
|
nuclear@18
|
219
|
nuclear@18
|
220 float top = near_clip * tan(fov * 0.5);
|
nuclear@18
|
221 float right = top * (float)cfg.width / (float)cfg.height;
|
nuclear@18
|
222
|
nuclear@18
|
223 float frust_shift = -(float)eye * (stereo_eye_sep * 0.5 * near_clip / stereo_focus_dist);
|
nuclear@18
|
224 glFrustum(-right + frust_shift, right + frust_shift, -top, top, near_clip, far_clip);
|
nuclear@18
|
225 }
|
nuclear@18
|
226
|
nuclear@18
|
227
|
nuclear@7
|
228 void update(unsigned long msec)
|
nuclear@7
|
229 {
|
nuclear@7
|
230 static unsigned long last_upd;
|
nuclear@7
|
231
|
nuclear@7
|
232 if(last_upd == 0) {
|
nuclear@7
|
233 last_upd = msec;
|
nuclear@7
|
234 }
|
nuclear@7
|
235 float dt = (float)(msec - last_upd) / 1000.0;
|
nuclear@7
|
236
|
nuclear@9
|
237 float offs = 2.5 * dt;
|
nuclear@7
|
238 float dx = 0, dy = 0;
|
nuclear@7
|
239
|
nuclear@7
|
240 // handle key input
|
nuclear@7
|
241 if(keystate['w'] || keystate['W']) {
|
nuclear@7
|
242 dy -= offs;
|
nuclear@7
|
243 }
|
nuclear@7
|
244 if(keystate['s'] || keystate['S']) {
|
nuclear@7
|
245 dy += offs;
|
nuclear@7
|
246 }
|
nuclear@7
|
247 if(keystate['d'] || keystate['D']) {
|
nuclear@7
|
248 dx += offs;
|
nuclear@7
|
249 }
|
nuclear@7
|
250 if(keystate['a'] || keystate['A']) {
|
nuclear@7
|
251 dx -= offs;
|
nuclear@7
|
252 }
|
nuclear@7
|
253
|
nuclear@7
|
254 cam.input_move(dx, 0, dy);
|
nuclear@7
|
255
|
nuclear@46
|
256 tileset->update_tiles(msec);
|
nuclear@38
|
257 level->update(msec, dt);
|
nuclear@38
|
258
|
nuclear@7
|
259 last_upd = msec;
|
nuclear@1
|
260 }
|
nuclear@1
|
261
|
nuclear@1
|
262 void reshape(int x, int y)
|
nuclear@1
|
263 {
|
nuclear@1
|
264 glViewport(0, 0, x, y);
|
nuclear@18
|
265 cfg.width = x;
|
nuclear@18
|
266 cfg.height = y;
|
nuclear@30
|
267
|
nuclear@41
|
268 rend->resize(x, y);
|
nuclear@1
|
269 }
|
nuclear@1
|
270
|
nuclear@18
|
271 static bool stereo_shift_pressed;
|
nuclear@18
|
272
|
nuclear@1
|
273 void keyb(unsigned char key, int x, int y)
|
nuclear@1
|
274 {
|
nuclear@1
|
275 switch(key) {
|
nuclear@1
|
276 case 27:
|
nuclear@1
|
277 exit(0);
|
nuclear@18
|
278
|
nuclear@24
|
279 case '`':
|
nuclear@24
|
280 show_con = true;
|
nuclear@24
|
281 glutKeyboardFunc(keyb_con);
|
nuclear@24
|
282 glutKeyboardUpFunc(0);
|
nuclear@24
|
283 glutPostRedisplay();
|
nuclear@24
|
284 break;
|
nuclear@24
|
285
|
nuclear@18
|
286 case 'z':
|
nuclear@18
|
287 stereo_shift_pressed = true;
|
nuclear@18
|
288 break;
|
nuclear@18
|
289
|
nuclear@18
|
290 case '\n':
|
nuclear@18
|
291 case '\r':
|
nuclear@18
|
292 {
|
nuclear@18
|
293 static bool fullscr;
|
nuclear@18
|
294 if(glutGetModifiers() & GLUT_ACTIVE_ALT) {
|
nuclear@18
|
295 fullscr = !fullscr;
|
nuclear@18
|
296 if(fullscr) {
|
nuclear@18
|
297 glutFullScreen();
|
nuclear@18
|
298 } else {
|
nuclear@18
|
299 glutPositionWindow(20, 20);
|
nuclear@18
|
300 }
|
nuclear@18
|
301 }
|
nuclear@18
|
302 }
|
nuclear@18
|
303 break;
|
nuclear@18
|
304
|
nuclear@18
|
305 default:
|
nuclear@18
|
306 break;
|
nuclear@1
|
307 }
|
nuclear@7
|
308
|
nuclear@7
|
309 keystate[key] = true;
|
nuclear@7
|
310 }
|
nuclear@7
|
311
|
nuclear@7
|
312 void key_release(unsigned char key, int x, int y)
|
nuclear@7
|
313 {
|
nuclear@18
|
314 switch(key) {
|
nuclear@18
|
315 case 'z':
|
nuclear@18
|
316 stereo_shift_pressed = false;
|
nuclear@18
|
317 break;
|
nuclear@18
|
318
|
nuclear@18
|
319 default:
|
nuclear@18
|
320 break;
|
nuclear@18
|
321 }
|
nuclear@18
|
322
|
nuclear@7
|
323 keystate[key] = false;
|
nuclear@1
|
324 }
|
nuclear@1
|
325
|
nuclear@24
|
326 void keyb_con(unsigned char key, int x, int y)
|
nuclear@24
|
327 {
|
nuclear@24
|
328 if(key == '`' || key == 27) {
|
nuclear@24
|
329 show_con = false;
|
nuclear@24
|
330 glutKeyboardFunc(keyb);
|
nuclear@24
|
331 glutKeyboardUpFunc(key_release);
|
nuclear@24
|
332 glutPostRedisplay();
|
nuclear@24
|
333 } else {
|
nuclear@24
|
334 cmdcon_keypress(key);
|
nuclear@24
|
335 }
|
nuclear@24
|
336 }
|
nuclear@24
|
337
|
nuclear@1
|
338 static int prev_x, prev_y;
|
nuclear@1
|
339 static bool bnstate[32];
|
nuclear@1
|
340
|
nuclear@1
|
341 void mouse(int bn, int state, int x, int y)
|
nuclear@1
|
342 {
|
nuclear@1
|
343 prev_x = x;
|
nuclear@1
|
344 prev_y = y;
|
nuclear@1
|
345 bnstate[bn - GLUT_LEFT_BUTTON] = state == GLUT_DOWN;
|
nuclear@1
|
346 }
|
nuclear@1
|
347
|
nuclear@1
|
348 void motion(int x, int y)
|
nuclear@1
|
349 {
|
nuclear@1
|
350 int dx = x - prev_x;
|
nuclear@1
|
351 int dy = y - prev_y;
|
nuclear@1
|
352 prev_x = x;
|
nuclear@1
|
353 prev_y = y;
|
nuclear@1
|
354
|
nuclear@18
|
355 if(stereo_shift_pressed) {
|
nuclear@18
|
356 if(dy != 0) {
|
nuclear@18
|
357 stereo_focus_dist += dy * 0.01;
|
nuclear@18
|
358 stereo_eye_sep = stereo_focus_dist / 30.0;
|
nuclear@18
|
359 printf("foc: %f, sep: %f\n", stereo_focus_dist, stereo_eye_sep);
|
nuclear@18
|
360 glutPostRedisplay();
|
nuclear@18
|
361 }
|
nuclear@18
|
362 return;
|
nuclear@18
|
363 }
|
nuclear@18
|
364
|
nuclear@1
|
365 if(bnstate[0]) {
|
nuclear@7
|
366 cam.input_rotate(dy * 0.01, dx * 0.01, 0);
|
nuclear@1
|
367 glutPostRedisplay();
|
nuclear@1
|
368 }
|
nuclear@1
|
369 if(bnstate[2]) {
|
nuclear@1
|
370 cam.input_zoom(dy * 0.1);
|
nuclear@1
|
371 glutPostRedisplay();
|
nuclear@1
|
372 }
|
nuclear@1
|
373 }
|
nuclear@46
|
374
|
nuclear@46
|
375 unsigned int load_psys_tex(const char *fname, void *cls)
|
nuclear@46
|
376 {
|
nuclear@46
|
377 TextureSet *texset = tileset->get_textures();
|
nuclear@46
|
378 return texset->get_texture(fname);
|
nuclear@46
|
379 }
|