dungeon_crawler

view prototype/src/main.cc @ 72:a27528035e20

- re-organized the renderer classes a bit wrt final render-target - implemented identity color-grading palette for now - broke particle systems.... - removed multipass renderer
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 19 Oct 2012 02:45:57 +0300
parents 45172d087ebe
children 5981917093ff
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <assert.h>
4 #include "opengl.h"
5 #include "psys/psys.h"
6 #include "level.h"
7 #include "texture.h"
8 #include "camera.h"
9 #include "datapath.h"
10 #include "tileset.h"
11 #include "renderer.h"
12 #include "renderer_deferred.h"
13 #include "cmdcon.h"
14 #include "cfg.h"
15 #include "timer.h"
16 #include "audio/audio.h"
17 #include "audio/source.h"
18 #include "audio/ovstream.h"
20 bool init(int xsz, int ysz);
21 void cleanup();
22 void idle();
23 void disp();
24 void draw();
25 void view_matrix(int eye);
26 void proj_matrix(int eye);
27 void update(unsigned long msec);
28 void reshape(int x, int y);
29 void keyb(unsigned char key, int x, int y);
30 void key_release(unsigned char key, int x, int y);
31 void keyb_con(unsigned char key, int x, int y);
32 void mouse(int bn, int state, int x, int y);
33 void motion(int x, int y);
34 unsigned int load_psys_tex(const char *fname, void *cls);
36 static TileSet *tileset;
37 static Level *level;
39 static FpsCamera cam;
40 static bool keystate[256];
42 static float stereo_focus_dist = 0.25;
43 static float stereo_eye_sep = stereo_focus_dist / 30.0;
45 static bool show_con;
47 static AudioSource *move_sound;
48 static OggVorbisStream *music;
50 int main(int argc, char **argv)
51 {
52 glutInit(&argc, argv);
54 if(!cfg.parse_args(argc, argv)) {
55 return 1;
56 }
58 glutInitWindowSize(cfg.width, cfg.height);
59 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE | (cfg.stereo ? GLUT_STEREO : 0));
60 glutCreateWindow("dungeon crawler prototype");
62 glutIdleFunc(idle);
63 glutDisplayFunc(disp);
64 glutReshapeFunc(reshape);
65 glutKeyboardFunc(keyb);
66 glutKeyboardUpFunc(key_release);
67 glutMouseFunc(mouse);
68 glutMotionFunc(motion);
70 glewInit();
72 if(!init(cfg.width, cfg.height)) {
73 return 1;
74 }
75 atexit(cleanup);
77 glutMainLoop();
78 }
80 bool init(int xsz, int ysz)
81 {
82 // backup light for the forward crappy renderer
83 glEnable(GL_LIGHTING);
84 glEnable(GL_LIGHT0);
86 float ldir[] = {0, 0, -0.5, 1};
87 glLightfv(GL_LIGHT0, GL_POSITION, ldir);
88 float lcol[] = {1, 1, 1, 1};
89 glLightfv(GL_LIGHT0, GL_DIFFUSE, lcol);
90 glLightfv(GL_LIGHT0, GL_SPECULAR, lcol);
92 glEnable(GL_DEPTH_TEST);
93 glEnable(GL_CULL_FACE);
94 glEnable(GL_MULTISAMPLE);
96 add_data_path(".");
97 add_data_path("data");
98 add_data_path("data/audio");
99 add_data_path("sdr");
101 if(cfg.sound && !init_audio()) {
102 fprintf(stderr, "failed to initialize audio, continuing silently\n");
103 cfg.sound = false;
104 }
105 if(cfg.sound) {
106 move_sound = new AudioSource;
107 move_sound->set_volume(0.4);
109 music = new OggVorbisStream;
110 if(music->open(datafile_path("bgtrack.ogg").c_str())) {
111 music->set_volume(0.6);
112 music->play(PlayMode::loop);
113 } else {
114 delete music;
115 music = 0;
116 }
117 }
119 switch(cfg.rend) {
120 case Config::Renderer::mrt:
121 rend = new DeferredRenderer;
122 if(!rend->init(xsz, ysz)) {
123 fprintf(stderr, "failed to initialize deferred mrt renderer\n");
124 delete rend;
125 return false;
126 }
127 break;
129 case Config::Renderer::fwd:
130 rend = new FwdRenderer;
131 if(!rend->init(xsz, ysz)) {
132 fprintf(stderr, "failed to initialize forward renderer\n");
133 delete rend;
134 return false;
135 }
136 break;
138 default:
139 // try each in turn falling back to progressively worse renderers
140 rend = new DeferredRenderer;
141 if(!rend->init(xsz, ysz)) {
142 printf("falling back to multipass renderer...\n");
144 delete rend;
145 rend = new FwdRenderer();
146 if(!rend->init(xsz, ysz)) {
147 fprintf(stderr, "failed to create renderer\n");
148 return false;
149 }
150 }
151 }
153 if(!init_cmdcon()) {
154 return false;
155 }
157 psys_texture_loader(load_psys_tex, 0, 0);
159 // load a tileset
160 tileset = new TileSet;
161 printf("loading tileset: %s\n", cfg.tileset_file);
162 if(!tileset->load(datafile_path(cfg.tileset_file).c_str())) {
163 return false;
164 }
165 set_active_tileset(tileset);
167 level = new Level;
168 printf("loading level: %s\n", cfg.level_file);
169 if(!level->load(datafile_path(cfg.level_file).c_str())) {
170 return false;
171 }
173 cam.input_move(0, 0.5, 0);
175 return true;
176 }
178 void cleanup()
179 {
180 delete level;
181 delete tileset;
182 delete rend;
184 cleanup_cmdcon();
186 if(cfg.sound) {
187 delete music;
188 delete move_sound;
189 destroy_audio();
190 }
191 }
193 void idle()
194 {
195 glutPostRedisplay();
196 }
198 void disp()
199 {
200 update(get_time_msec());
202 if(cfg.stereo) {
203 glDrawBuffer(GL_BACK_LEFT);
205 glMatrixMode(GL_PROJECTION);
206 glLoadIdentity();
207 proj_matrix(-1);
208 glMatrixMode(GL_MODELVIEW);
209 glLoadIdentity();
210 view_matrix(-1);
212 draw();
214 glDrawBuffer(GL_BACK_RIGHT);
216 glMatrixMode(GL_PROJECTION);
217 glLoadIdentity();
218 proj_matrix(1);
219 glMatrixMode(GL_MODELVIEW);
220 glLoadIdentity();
221 view_matrix(1);
223 draw();
224 } else {
225 glMatrixMode(GL_PROJECTION);
226 glLoadIdentity();
227 proj_matrix(0);
228 glMatrixMode(GL_MODELVIEW);
229 glLoadIdentity();
230 view_matrix(0);
232 draw();
233 }
235 glutSwapBuffers();
236 assert(glGetError() == GL_NO_ERROR);
237 }
239 void draw()
240 {
241 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
243 rend->render(level);
245 if(show_con) {
246 draw_cmdcon();
247 }
248 }
250 void view_matrix(int eye)
251 {
252 float offs = stereo_eye_sep * eye * 0.5;
253 glTranslatef(-offs, 0, 0);
254 cam.use_inverse();
255 }
257 void proj_matrix(int eye)
258 {
259 static const float fov = M_PI / 4.0;
260 static const float near_clip = 0.1;
261 static const float far_clip = 100.0;
263 float top = near_clip * tan(fov * 0.5);
264 float right = top * (float)cfg.width / (float)cfg.height;
266 float frust_shift = -(float)eye * (stereo_eye_sep * 0.5 * near_clip / stereo_focus_dist);
267 glFrustum(-right + frust_shift, right + frust_shift, -top, top, near_clip, far_clip);
268 }
271 void update(unsigned long msec)
272 {
273 static unsigned long last_upd;
275 if(last_upd == 0) {
276 last_upd = msec;
277 }
278 float dt = (float)(msec - last_upd) / 1000.0;
280 float offs = 2.0 * dt;
281 float dx = 0, dy = 0;
283 // handle key input
284 bool did_move = false;
285 if(keystate['w'] || keystate['W']) {
286 dy -= offs;
287 did_move = true;
288 }
289 if(keystate['s'] || keystate['S']) {
290 dy += offs;
291 did_move = true;
292 }
293 if(keystate['d'] || keystate['D']) {
294 dx += offs;
295 did_move = true;
296 }
297 if(keystate['a'] || keystate['A']) {
298 dx -= offs;
299 did_move = true;
300 }
302 cam.input_move(dx, 0, dy);
304 tileset->update_tiles(msec);
306 level->set_player_position(cam.get_position());
307 level->update(msec, dt);
309 if(cfg.sound) {
310 // set the listener matrix
311 set_audio_listener(cam.matrix());
313 // play the walking sound if we're walking
314 int cellx, celly;
315 level->get_cell_coords_at(cam.get_position(), &cellx, &celly);
317 const AudioSample *move_sample;
318 if(did_move && (move_sample = level->get_sample(cellx, celly, TILE_SAMPLE_WALK))) {
319 if(move_sample != move_sound->get_sample()) {
320 move_sound->stop();
321 move_sound->set_sample(move_sample);
322 move_sound->play();
323 }
324 } else {
325 if(move_sound->get_sample()) {
326 move_sound->stop();
327 move_sound->set_sample(0);
328 }
329 }
330 }
332 last_upd = msec;
333 }
335 void reshape(int x, int y)
336 {
337 glViewport(0, 0, x, y);
338 cfg.width = x;
339 cfg.height = y;
341 rend->resize(x, y);
342 }
344 static bool stereo_shift_pressed;
346 void keyb(unsigned char key, int x, int y)
347 {
348 switch(key) {
349 case 27:
350 exit(0);
352 case '`':
353 show_con = true;
354 glutKeyboardFunc(keyb_con);
355 glutKeyboardUpFunc(0);
356 glutPostRedisplay();
357 break;
359 case 'z':
360 stereo_shift_pressed = true;
361 break;
363 case 'p':
364 {
365 Vector3 pos = cam.get_position();
366 int cell_x, cell_y;
367 level->get_cell_coords_at(pos, &cell_x, &cell_y);
368 printf("Current position: [%.2f %.2f %.2f] cell: [%d %d]\n", pos.x, pos.y, pos.z,
369 cell_x, cell_y);
370 }
371 break;
373 case 'P':
374 {
375 Vector3 pos = cam.get_position();
376 int cell_x, cell_y;
377 level->get_cell_coords_at(pos, &cell_x, &cell_y);
378 AudioSample *sample = level->get_sample(cell_x, cell_y, TILE_SAMPLE_WALK);
379 printf("walk sample: %p\n", (void*)sample);
380 }
381 break;
384 case '\n':
385 case '\r':
386 {
387 static bool fullscr;
388 if(glutGetModifiers() & GLUT_ACTIVE_ALT) {
389 fullscr = !fullscr;
390 if(fullscr) {
391 glutFullScreen();
392 } else {
393 glutPositionWindow(20, 20);
394 }
395 }
396 }
397 break;
399 default:
400 break;
401 }
403 keystate[key] = true;
404 }
406 void key_release(unsigned char key, int x, int y)
407 {
408 switch(key) {
409 case 'z':
410 stereo_shift_pressed = false;
411 break;
413 default:
414 break;
415 }
417 keystate[key] = false;
418 }
420 void keyb_con(unsigned char key, int x, int y)
421 {
422 if(key == '`' || key == 27) {
423 show_con = false;
424 glutKeyboardFunc(keyb);
425 glutKeyboardUpFunc(key_release);
426 glutPostRedisplay();
427 } else {
428 cmdcon_keypress(key);
429 }
430 }
432 static int prev_x, prev_y;
433 static bool bnstate[32];
435 void mouse(int bn, int state, int x, int y)
436 {
437 prev_x = x;
438 prev_y = y;
439 bnstate[bn - GLUT_LEFT_BUTTON] = state == GLUT_DOWN;
440 }
442 void motion(int x, int y)
443 {
444 int dx = x - prev_x;
445 int dy = y - prev_y;
446 prev_x = x;
447 prev_y = y;
449 if(stereo_shift_pressed) {
450 if(dy != 0) {
451 stereo_focus_dist += dy * 0.01;
452 stereo_eye_sep = stereo_focus_dist / 30.0;
453 printf("foc: %f, sep: %f\n", stereo_focus_dist, stereo_eye_sep);
454 glutPostRedisplay();
455 }
456 return;
457 }
459 if(bnstate[0]) {
460 cam.input_rotate(dy * 0.0075, dx * 0.0075, 0);
461 glutPostRedisplay();
462 }
463 if(bnstate[2]) {
464 cam.input_zoom(dy * 0.1);
465 glutPostRedisplay();
466 }
467 }
469 unsigned int load_psys_tex(const char *fname, void *cls)
470 {
471 TextureSet *texset = tileset->get_textures();
472 return texset->get(fname);
473 }