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