deepstone

annotate src/main.c @ 38:17a5107b6fa4

- added perspective correct interpolation - added recording functionality - added video capture functionality
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 10 Mar 2014 17:24:42 +0200
parents c6406e4aa0fb
children
rev   line source
nuclear@27 1 #include <stdio.h>
nuclear@27 2 #include <stdlib.h>
nuclear@38 3 #include <string.h>
nuclear@27 4 #include <math.h>
nuclear@38 5 #include <limits.h>
nuclear@27 6 #include <signal.h>
nuclear@27 7 #include <conio.h>
nuclear@27 8 #include "wvga.h"
nuclear@27 9 #include "mingl.h"
nuclear@27 10 #include "timer.h"
nuclear@33 11 #include "keyb.h"
nuclear@27 12 #include "mouse.h"
nuclear@27 13 #include "texture.h"
nuclear@27 14 #include "palman.h"
nuclear@27 15 #include "scene.h"
nuclear@38 16 #include "record.h"
nuclear@27 17
nuclear@27 18 #define DEG2RAD(x) (M_PI * (x) / 180.0)
nuclear@27 19
nuclear@27 20 static int init(void);
nuclear@27 21 static void shutdown(void);
nuclear@38 22 static void update(unsigned long msec, unsigned long dtmsec);
nuclear@27 23 static void redraw(void);
nuclear@27 24 static int proc_events(void);
nuclear@27 25 static void mouse_button(int bn, int x, int y);
nuclear@27 26 static void mouse_motion(int x, int y);
nuclear@27 27 static void sighandler(int s);
nuclear@38 28 static int parse_args(int argc, char **argv);
nuclear@27 29
nuclear@27 30
nuclear@27 31 static float cam_x, cam_y, cam_z;
nuclear@27 32 static float cam_theta, cam_phi;
nuclear@27 33
nuclear@34 34 static float walk_speed = 6.0;
nuclear@38 35 static float look_speed = 0.3;
nuclear@33 36
nuclear@33 37 static int mouse_look = 1;
nuclear@38 38 static int use_vsync;
nuclear@27 39
nuclear@27 40 static void *fbuf;
nuclear@27 41 static struct scene scn;
nuclear@27 42
nuclear@38 43 #define REC_FNAME "game.rec"
nuclear@38 44 static int rec_playing, rec_recording;
nuclear@38 45 static unsigned long rec_start_time;
nuclear@27 46
nuclear@38 47
nuclear@38 48 int main(int argc, char **argv)
nuclear@27 49 {
nuclear@34 50 unsigned long prev_msec = 0;
nuclear@34 51
nuclear@38 52 if(parse_args(argc, argv) == -1) {
nuclear@38 53 return 1;
nuclear@38 54 }
nuclear@38 55
nuclear@27 56 if(init() == -1) {
nuclear@27 57 return 1;
nuclear@27 58 }
nuclear@27 59
nuclear@34 60 for(;;) {
nuclear@34 61 unsigned long msec = get_msec();
nuclear@34 62 unsigned long dt = msec - prev_msec;
nuclear@34 63 prev_msec = msec;
nuclear@34 64
nuclear@34 65 if(!proc_events()) {
nuclear@34 66 break;
nuclear@34 67 }
nuclear@34 68
nuclear@38 69 update(msec, dt);
nuclear@27 70 redraw();
nuclear@27 71 }
nuclear@27 72
nuclear@27 73 shutdown();
nuclear@27 74 return 0;
nuclear@27 75 }
nuclear@27 76
nuclear@27 77
nuclear@27 78 static int init(void)
nuclear@27 79 {
nuclear@34 80 float vfov, aspect;
nuclear@28 81
nuclear@28 82 aspect = 320.0 / 200.0;
nuclear@28 83 vfov = 60.0;
nuclear@28 84
nuclear@27 85 init_timer(100);
nuclear@33 86 kb_init(16); /* 16 characters input buffer */
nuclear@27 87
nuclear@27 88 set_video_mode(0x13);
nuclear@27 89
nuclear@27 90 signal(SIGINT, sighandler);
nuclear@27 91 signal(SIGSEGV, sighandler);
nuclear@27 92 signal(SIGFPE, sighandler);
nuclear@27 93 signal(SIGILL, sighandler);
nuclear@27 94 signal(SIGABRT, sighandler);
nuclear@27 95
nuclear@27 96 if(mgl_init(320, 200) == -1) {
nuclear@27 97 fprintf(stderr, "mgl init failed\n");
nuclear@27 98 return -1;
nuclear@27 99 }
nuclear@27 100 fbuf = mgl_framebuffer();
nuclear@27 101
nuclear@27 102 mgl_enable(MGL_CULL_FACE);
nuclear@27 103 mgl_enable(MGL_SMOOTH);
nuclear@27 104 mgl_enable(MGL_LIGHTING);
nuclear@27 105 mgl_enable(MGL_DEPTH_TEST);
nuclear@27 106
nuclear@27 107 mgl_matrix_mode(MGL_PROJECTION);
nuclear@27 108 mgl_load_identity();
nuclear@28 109 mgl_perspective(vfov, aspect, 0.5, 200.0);
nuclear@28 110
nuclear@28 111 #if 0
nuclear@28 112 mgl_enable(MGL_CLIP_PLANE0);
nuclear@28 113 mgl_enable(MGL_CLIP_PLANE1);
nuclear@28 114 mgl_enable(MGL_CLIP_PLANE2);
nuclear@28 115 mgl_enable(MGL_CLIP_PLANE3);
nuclear@28 116 mgl_clip_plane(MGL_CLIP_PLANE0, -1, 0, -1, 0); /* positive X */
nuclear@28 117 mgl_clip_plane(MGL_CLIP_PLANE1, 1, 0, -1, 0); /* negative X */
nuclear@28 118 mgl_clip_plane(MGL_CLIP_PLANE2, 0, -1, -0.5, 0); /* positive Y */
nuclear@28 119 mgl_clip_plane(MGL_CLIP_PLANE3, 0, 1, -0.5, 0); /* negative Y */
nuclear@28 120 #endif
nuclear@27 121
nuclear@27 122 /* setup palette */
nuclear@27 123 palm_add_color(255, 255, 255);
nuclear@27 124
nuclear@27 125 scn_init(&scn);
nuclear@27 126 if(scn_load(&scn, "data/hall.obj") == -1) {
nuclear@27 127 return -1;
nuclear@27 128 }
nuclear@27 129
nuclear@27 130 palm_build();
nuclear@27 131 {
nuclear@27 132 int i, palsz = palm_palette_size();
nuclear@27 133 struct palm_color *pal = palm_palette();
nuclear@27 134
nuclear@27 135 for(i=0; i<palsz; i++) {
nuclear@27 136 set_pal_entry(i, pal[i].r, pal[i].g, pal[i].b);
nuclear@27 137 }
nuclear@27 138 }
nuclear@27 139
nuclear@27 140 mgl_color_range(palm_color_range() - 1);
nuclear@27 141 return 0;
nuclear@27 142 }
nuclear@27 143
nuclear@27 144 static void shutdown(void)
nuclear@27 145 {
nuclear@27 146 mgl_free();
nuclear@27 147 set_video_mode(3);
nuclear@33 148 kb_shutdown();
nuclear@27 149 }
nuclear@27 150
nuclear@34 151
nuclear@34 152 #define DEG_TO_RAD(x) (M_PI * (x) / 180.0)
nuclear@34 153 void cam_move(float dx, float dy)
nuclear@34 154 {
nuclear@34 155 float angle = DEG_TO_RAD(cam_theta);
nuclear@34 156 cam_x += cos(angle) * dx + sin(angle) * dy;
nuclear@34 157 cam_z -= -sin(angle) * dx + cos(angle) * dy;
nuclear@34 158 }
nuclear@34 159
nuclear@38 160 static void update(unsigned long msec, unsigned long dtmsec)
nuclear@34 161 {
nuclear@34 162 float dt = (float)dtmsec / 1000.0f;
nuclear@34 163 float offs = walk_speed * dt;
nuclear@34 164
nuclear@34 165 if(kb_isdown('w') || kb_isdown('W'))
nuclear@34 166 cam_move(0, offs);
nuclear@34 167
nuclear@34 168 if(kb_isdown('s') || kb_isdown('S'))
nuclear@34 169 cam_move(0, -offs);
nuclear@34 170
nuclear@34 171 if(kb_isdown('a') || kb_isdown('A'))
nuclear@34 172 cam_move(-offs, 0);
nuclear@34 173
nuclear@34 174 if(kb_isdown('d') || kb_isdown('D'))
nuclear@34 175 cam_move(offs, 0);
nuclear@38 176
nuclear@38 177 if(rec_playing) {
nuclear@38 178 rec_get(msec - rec_start_time, &cam_x, &cam_y, &cam_z, &cam_theta, &cam_phi);
nuclear@38 179 } else if(rec_recording) {
nuclear@38 180 static float px, py, pz, ptheta, pphi;
nuclear@38 181
nuclear@38 182 if(cam_x != px || cam_y != py || cam_z != pz || cam_theta != ptheta || cam_phi != pphi) {
nuclear@38 183 rec_add(msec - rec_start_time, cam_x, cam_y, cam_z, cam_theta, cam_phi);
nuclear@38 184 px = cam_x;
nuclear@38 185 py = cam_y;
nuclear@38 186 pz = cam_z;
nuclear@38 187 ptheta = cam_theta;
nuclear@38 188 pphi = cam_phi;
nuclear@38 189 }
nuclear@38 190 }
nuclear@34 191 }
nuclear@34 192
nuclear@27 193 static void redraw(void)
nuclear@27 194 {
nuclear@27 195 mgl_clear(0);
nuclear@27 196 mgl_clear_depth();
nuclear@27 197
nuclear@27 198 mgl_matrix_mode(MGL_MODELVIEW);
nuclear@27 199 mgl_load_identity();
nuclear@27 200 mgl_rotate(cam_phi, 1, 0, 0);
nuclear@27 201 mgl_rotate(cam_theta, 0, 1, 0);
nuclear@27 202 mgl_translate(-cam_x, -cam_y, -cam_z);
nuclear@27 203 mgl_translate(0, -2.0, 0);
nuclear@27 204
nuclear@27 205 mgl_light_intensity(0, 1.0);
nuclear@27 206 mgl_light_position(0, 0, 5, 0, 1);
nuclear@27 207
nuclear@27 208 /*mgl_torus(0.75, 0.25, 16, 8);*/
nuclear@27 209 scn_render(&scn);
nuclear@27 210
nuclear@27 211 copy_frame(fbuf);
nuclear@38 212 if(use_vsync) {
nuclear@38 213 wait_vsync();
nuclear@38 214 }
nuclear@27 215 }
nuclear@27 216
nuclear@27 217 static int proc_events(void)
nuclear@27 218 {
nuclear@27 219 static int prev_mx, prev_my, prev_bnmask;
nuclear@34 220 int mx, my, bnmask;
nuclear@27 221
nuclear@33 222 int key;
nuclear@33 223 while((key = kb_getkey()) != -1) {
nuclear@33 224 switch(key) {
nuclear@33 225 case 27:
nuclear@33 226 return 0;
nuclear@27 227
nuclear@38 228 case '\b':
nuclear@38 229 begin_capture(1);
nuclear@38 230 break;
nuclear@38 231 case '\\':
nuclear@38 232 {
nuclear@38 233 static int capturing;
nuclear@38 234 if(capturing) {
nuclear@38 235 printf("stop video capture\n");
nuclear@38 236 end_capture();
nuclear@38 237 capturing = 0;
nuclear@38 238 } else {
nuclear@38 239 printf("start video capture\n");
nuclear@38 240 begin_capture(INT_MAX);
nuclear@38 241 capturing = 1;
nuclear@38 242 }
nuclear@38 243 }
nuclear@38 244 break;
nuclear@38 245
nuclear@33 246 case '`':
nuclear@33 247 mouse_look = !mouse_look;
nuclear@33 248 break;
nuclear@33 249
nuclear@38 250 case 'r':
nuclear@38 251 if(rec_recording) {
nuclear@38 252 /* stop recording and save it */
nuclear@38 253 rec_recording = 0;
nuclear@38 254 printf("done, saving %s\n", REC_FNAME);
nuclear@38 255 rec_save(REC_FNAME);
nuclear@38 256 } else {
nuclear@38 257 printf("recording ...\n");
nuclear@38 258 rec_recording = 1;
nuclear@38 259 rec_playing = 0;
nuclear@38 260 rec_reset();
nuclear@38 261 rec_start_time = get_msec();
nuclear@38 262 }
nuclear@38 263 break;
nuclear@38 264
nuclear@38 265 case 'l':
nuclear@38 266 printf("loading recording %s\n", REC_FNAME);
nuclear@38 267 rec_recording = 0;
nuclear@38 268 rec_playing = 0;
nuclear@38 269 rec_reset();
nuclear@38 270 rec_load(REC_FNAME);
nuclear@38 271 break;
nuclear@38 272
nuclear@38 273 case ' ':
nuclear@38 274 if(rec_recording) {
nuclear@38 275 break;
nuclear@38 276 }
nuclear@38 277
nuclear@38 278 if(rec_playing) {
nuclear@38 279 printf("stop rec playback\n");
nuclear@38 280 rec_playing = 0;
nuclear@38 281 } else {
nuclear@38 282 printf("start rec playback\n");
nuclear@38 283 rec_playing = 1;
nuclear@38 284 rec_start_time = get_msec();
nuclear@38 285 }
nuclear@38 286 break;
nuclear@38 287
nuclear@33 288 default:
nuclear@33 289 break;
nuclear@33 290 }
nuclear@33 291 }
nuclear@33 292
nuclear@34 293 bnmask = read_mouse(&mx, &my);
nuclear@34 294 if(bnmask != prev_bnmask) {
nuclear@34 295 mouse_button(bnmask, mx, my);
nuclear@34 296 prev_bnmask = bnmask;
nuclear@34 297 }
nuclear@34 298 if(mx != prev_mx || my != prev_my) {
nuclear@34 299 mouse_motion(mx, my);
nuclear@34 300 prev_mx = mx;
nuclear@34 301 prev_my = my;
nuclear@34 302 }
nuclear@27 303 return 1;
nuclear@27 304 }
nuclear@27 305
nuclear@27 306 static int bnstate;
nuclear@27 307 static void mouse_button(int bn, int x, int y)
nuclear@27 308 {
nuclear@27 309 bnstate = bn;
nuclear@27 310 }
nuclear@27 311
nuclear@27 312 static void mouse_motion(int x, int y)
nuclear@27 313 {
nuclear@33 314 static int prev_x = -1, prev_y;
nuclear@27 315 int dx = x - prev_x;
nuclear@27 316 int dy = y - prev_y;
nuclear@33 317
nuclear@33 318 if(mouse_look) {
nuclear@33 319 if(prev_x == -1) {
nuclear@33 320 dx = dy = 0;
nuclear@33 321 }
nuclear@33 322
nuclear@33 323 set_mouse(160, 100);
nuclear@33 324 prev_x = 160;
nuclear@33 325 prev_y = 100;
nuclear@33 326 } else {
nuclear@33 327 prev_x = x;
nuclear@33 328 prev_y = y;
nuclear@33 329 }
nuclear@27 330
nuclear@27 331 if(mouse_look || bnstate) {
nuclear@27 332 cam_theta += dx * look_speed;
nuclear@27 333 cam_phi += dy * look_speed;
nuclear@27 334
nuclear@27 335 if(cam_phi < -90) {
nuclear@27 336 cam_phi = -90;
nuclear@27 337 }
nuclear@27 338 if(cam_phi > 90) {
nuclear@27 339 cam_phi = 90;
nuclear@27 340 }
nuclear@27 341 }
nuclear@27 342 }
nuclear@27 343
nuclear@27 344 static void sighandler(int s)
nuclear@27 345 {
nuclear@27 346 set_video_mode(3);
nuclear@27 347
nuclear@27 348 switch(s) {
nuclear@27 349 case SIGABRT:
nuclear@27 350 fprintf(stderr, "abort\n");
nuclear@27 351 break;
nuclear@27 352
nuclear@27 353 case SIGILL:
nuclear@27 354 fprintf(stderr, "illegal operation\n");
nuclear@27 355 break;
nuclear@27 356
nuclear@27 357 case SIGSEGV:
nuclear@27 358 fprintf(stderr, "segmentation fault\n");
nuclear@27 359 break;
nuclear@27 360
nuclear@27 361 case SIGINT:
nuclear@27 362 fprintf(stderr, "interrupted\n");
nuclear@27 363 break;
nuclear@27 364
nuclear@27 365 case SIGFPE:
nuclear@27 366 fprintf(stderr, "floating point exception\n");
nuclear@27 367 break;
nuclear@27 368
nuclear@27 369 default:
nuclear@27 370 fprintf(stderr, "unexpected signal\n");
nuclear@27 371 }
nuclear@27 372
nuclear@27 373 exit(1);
nuclear@27 374 }
nuclear@38 375
nuclear@38 376 static int parse_args(int argc, char **argv)
nuclear@38 377 {
nuclear@38 378 int i;
nuclear@38 379
nuclear@38 380 for(i=1; i<argc; i++) {
nuclear@38 381 if(argv[i][0] == '-') {
nuclear@38 382 if(strcmp(argv[i], "-vsync") == 0) {
nuclear@38 383 use_vsync = 1;
nuclear@38 384 } else {
nuclear@38 385 goto invalid;
nuclear@38 386 }
nuclear@38 387 } else {
nuclear@38 388 goto invalid;
nuclear@38 389 }
nuclear@38 390 }
nuclear@38 391
nuclear@38 392 return 0;
nuclear@38 393
nuclear@38 394 invalid:
nuclear@38 395 fprintf(stderr, "invalid argument: %s\n", argv[i]);
nuclear@38 396 return -1;
nuclear@38 397 }