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 }
|