deepstone

view src/test.c @ 25:5ff8ce78059a

first pass at converting the rasterizer to fixed point
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 22 Sep 2013 02:21:30 +0300
parents 00d84ab1ef26
children 11d14f688485
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <signal.h>
5 #include <conio.h>
6 #include "wvga.h"
7 #include "mingl.h"
8 #include "timer.h"
9 #include "mouse.h"
10 #include "palman.h"
11 #include "texture.h"
13 static int init(void);
14 static void shutdown(void);
15 static void redraw(void);
16 static void draw_cursor(unsigned char *fb, int xsz, int ysz, int mx, int my, int cidx);
17 static int keyb(char key);
18 static void mouse_button(int bn, int x, int y);
19 static void mouse_motion(int x, int y);
20 static void sighandler(int s);
21 static int parse_args(int argc, char **argv);
22 static void print_perf(void);
24 static unsigned char *fbuf;
26 static struct texture *tex;
27 static char *texfile;
29 static int white_base, red_base, green_base, blue_base;
30 static int grad_range;
32 static int use_vsync = 1;
33 static int under_windows = 0;
34 static unsigned long num_frm;
36 enum { CUBE, SPHERE, TORUS, NUM_PRIMS };
37 static int prim = SPHERE;
38 static int auto_rotate = 1;
39 static float cam_theta, cam_phi, cam_zoom = 4.0;
41 static int mx, my;
43 int main(int argc, char **argv)
44 {
45 int mbn, prev_mx = -1, prev_my = -1, prev_mbn = 0;
47 if(parse_args(argc, argv) == -1) {
48 return 1;
49 }
51 if(init() == -1) {
52 return 1;
53 }
55 reset_timer();
57 for(;;) {
58 if(kbhit()) {
59 if(keyb(getch()) == 0) {
60 break;
61 }
62 }
64 mbn = read_mouse(&mx, &my);
65 if(mbn != prev_mbn) {
66 mouse_button(mbn, mx, my);
67 prev_mbn = mbn;
68 }
69 if(mx != prev_mx || my != prev_my) {
70 if(mbn) {
71 mouse_motion(mx, my);
72 }
73 prev_mx = mx;
74 prev_my = my;
75 }
77 redraw();
78 }
80 shutdown();
81 print_perf();
82 return 0;
83 }
85 static int init(void)
86 {
87 int i;
88 struct palm_color *pal;
90 init_timer(under_windows ? 0 : 100);
92 set_video_mode(0x13);
94 signal(SIGINT, sighandler);
95 signal(SIGSEGV, sighandler);
96 signal(SIGFPE, sighandler);
97 signal(SIGILL, sighandler);
98 signal(SIGABRT, sighandler);
100 have_mouse();
103 if(mgl_init(320, 200) == -1) {
104 fprintf(stderr, "mgl init failed\n");
105 return -1;
106 }
107 fbuf = mgl_framebuffer();
110 if(!texfile) {
111 palm_add_color(255, 255, 255);
112 palm_add_color(255, 0, 0);
113 palm_add_color(0, 255, 0);
114 palm_add_color(0, 0, 255);
115 palm_build();
117 white_base = palm_color_base(255, 255, 255);
118 red_base = palm_color_base(255, 0, 0);
119 green_base = palm_color_base(0, 255, 0);
120 blue_base = palm_color_base(0, 0, 255);
122 tex = tex_gen_checker(64, 64, 3, 3, red_base, blue_base);
123 } else {
124 if(!(tex = load_texture(texfile))) {
125 return -1;
126 }
128 palm_build();
129 get_texture_pixels(tex);
131 mgl_enable(MGL_TEXTURE_2D);
132 }
134 grad_range = palm_color_range();
136 pal = palm_palette();
137 for(i=0; i<palm_palette_size(); i++) {
138 set_pal_entry(i, pal[i].r, pal[i].g, pal[i].b);
139 }
141 mgl_enable(MGL_CULL_FACE);
142 mgl_enable(MGL_DEPTH_TEST);
143 mgl_enable(MGL_SMOOTH);
144 mgl_color_range(grad_range - 1); /* gradient range */
146 mgl_enable(MGL_LIGHTING);
147 mgl_light_intensity(0, 1.0);
148 mgl_light_position(0, -0.5, 0.5, 1, 0);
150 mgl_matrix_mode(MGL_PROJECTION);
151 mgl_load_identity();
152 mgl_perspective(45.0, 320.0 / 200.0, 0.5, 100.0);
154 mgl_teximage(tex->width, tex->height, tex->pixels);
156 return 0;
157 }
159 static void shutdown(void)
160 {
161 mgl_free();
162 set_video_mode(3);
163 }
165 static void redraw(void)
166 {
167 float angle = get_msec() / 10.0;
168 mgl_clear(0);
169 mgl_clear_depth();
171 mgl_matrix_mode(MGL_MODELVIEW);
172 mgl_load_identity();
173 mgl_translate(0, 0, -cam_zoom);
174 if(auto_rotate) {
175 mgl_rotate(angle * 0.5, 1, 0, 0);
176 mgl_rotate(angle, 0, 0, 1);
177 } else {
178 mgl_rotate(cam_phi, 1, 0, 0);
179 mgl_rotate(cam_theta, 0, 1, 0);
180 }
182 switch(prim) {
183 case TORUS:
184 mgl_index(green_base);
185 mgl_torus(1.0, 0.25, 16, 8);
186 break;
187 case SPHERE:
188 mgl_index(blue_base);
189 mgl_sphere(1.0, 16, 8);
190 break;
191 case CUBE:
192 mgl_index(red_base);
193 mgl_cube(1.0);
194 }
196 if(!auto_rotate) {
197 draw_cursor(fbuf, 320, 200, mx, my, white_base + grad_range - 1);
198 }
200 copy_frame(fbuf);
201 if(use_vsync) {
202 wait_vsync();
203 }
204 num_frm++;
205 }
207 static void draw_cursor(unsigned char *fb, int xsz, int ysz, int mx, int my, int cidx)
208 {
209 static char img[] =
210 "oo........"
211 "oxo......."
212 "oxxo......"
213 "oxxxo....."
214 "oxxxxo...."
215 "oxxxxxo..."
216 "oxxxxxxo.."
217 "oxxxxxxxo."
218 "oxxxxxxxxo"
219 "oxxxxxoooo"
220 "oxxoxxo..."
221 "oxo.oxxo.."
222 "oo..oxxo.."
223 ".....oxxo."
224 ".....oxxo."
225 "......oo..";
226 int i, j, w = 10, h = 16;
228 if(mx < 0 || my < 0) {
229 return;
230 }
231 if(mx + w >= xsz) {
232 w = xsz - mx;
233 }
234 if(my + h >= ysz) {
235 h = ysz - my;
236 }
238 fb += my * xsz + mx;
239 for(i=0; i<h; i++) {
240 for(j=0; j<w; j++) {
241 char c = img[(i << 3) + (i << 1) + j];
242 if(c != '.') {
243 fb[j] = c == 'x' ? 0 : cidx;
244 }
245 }
246 fb += xsz;
247 }
248 }
250 static int keyb(char key)
251 {
252 switch(key) {
253 case 'q':
254 case 27:
255 return 0;
257 case 's':
258 if(mgl_isenabled(MGL_SMOOTH)) {
259 mgl_disable(MGL_SMOOTH);
260 } else {
261 mgl_enable(MGL_SMOOTH);
262 }
263 break;
265 case 't':
266 if(mgl_isenabled(MGL_TEXTURE_2D)) {
267 mgl_disable(MGL_TEXTURE_2D);
268 } else {
269 mgl_enable(MGL_TEXTURE_2D);
270 }
271 break;
273 case 'z':
274 if(mgl_isenabled(MGL_DEPTH_TEST)) {
275 mgl_disable(MGL_DEPTH_TEST);
276 } else {
277 mgl_enable(MGL_DEPTH_TEST);
278 }
279 break;
281 case ' ':
282 auto_rotate = !auto_rotate;
283 break;
285 case 'p':
286 prim = (prim + 1) % NUM_PRIMS;
287 break;
289 default:
290 break;
291 }
292 return 1;
293 }
295 static int bnstate;
296 static int prev_x, prev_y;
298 static void mouse_button(int bn, int x, int y)
299 {
300 bnstate = bn;
301 prev_x = x;
302 prev_y = y;
303 }
305 static void mouse_motion(int x, int y)
306 {
307 int dx, dy;
309 dx = x - prev_x;
310 dy = y - prev_y;
311 prev_x = x;
312 prev_y = y;
314 if(bnstate & MOUSE_LEFT) {
315 cam_theta += dx;
316 cam_phi += dy;
318 if(cam_phi > 90) cam_phi = 90;
319 if(cam_phi < -90) cam_phi = -90;
320 }
321 if(bnstate & MOUSE_RIGHT) {
322 cam_zoom += dy * 0.1;
323 if(cam_zoom < 0.0) {
324 cam_zoom = 0.0;
325 }
326 }
327 }
329 static void sighandler(int s)
330 {
331 set_video_mode(3);
333 switch(s) {
334 case SIGABRT:
335 fprintf(stderr, "abort\n");
336 break;
338 case SIGILL:
339 fprintf(stderr, "illegal operation\n");
340 break;
342 case SIGSEGV:
343 fprintf(stderr, "segmentation fault\n");
344 break;
346 case SIGINT:
347 fprintf(stderr, "interrupted\n");
348 break;
350 case SIGFPE:
351 fprintf(stderr, "floating point exception\n");
352 break;
354 default:
355 fprintf(stderr, "unexpected signal\n");
356 }
358 exit(1);
359 }
361 static int parse_args(int argc, char **argv)
362 {
363 int i;
365 for(i=1; i<argc; i++) {
366 if(argv[i][0] == '-') {
367 if(argv[i][2] != 0) {
368 goto invalid;
369 }
370 switch(argv[i][1]) {
371 case 'a':
372 auto_rotate = !auto_rotate;
373 break;
375 case 't':
376 texfile = argv[++i];
377 break;
379 case 'v':
380 use_vsync = !use_vsync;
381 break;
383 case 'p':
384 if(strcmp(argv[++i], "cube") == 0) {
385 prim = CUBE;
386 } else if(strcmp(argv[i], "sphere") == 0) {
387 prim = SPHERE;
388 } else if(strcmp(argv[i], "torus") == 0) {
389 prim = TORUS;
390 } else {
391 goto invalid;
392 }
393 break;
395 case 'w':
396 under_windows = 1;
397 break;
399 case 'h':
400 printf("Usage %s [options]\n", argv[0]);
401 printf("options:\n");
402 printf(" -p select one of (cube|sphere|torus)\n");
403 printf(" -v use vsync\n");
404 printf(" -w run under windows\n");
405 printf(" -h print usage information and exit\n");
406 exit(0);
408 default:
409 goto invalid;
410 }
411 } else {
412 goto invalid;
413 }
414 }
416 return 0;
418 invalid:
419 fprintf(stderr, "invalid argument: %s\n", argv[i]);
420 return -1;
421 }
424 static void print_perf(void)
425 {
426 unsigned long msec, avg_frame_time;
427 float sec, fps;
429 msec = get_msec();
430 if(!num_frm || msec < 1000) {
431 printf("leaving so soon? (%lu ms)\n", msec);
432 return;
433 }
435 sec = msec / 1000.0f;
436 fps = (float)num_frm / sec;
437 avg_frame_time = msec / num_frm;
439 printf("%lu frames in %.2f seconds\n", num_frm, sec);
440 printf(" avg. frame time: %lu ms\n", avg_frame_time);
441 printf(" avg. framerate: %.2f fps\n", fps);
442 }