deepstone

view src/test.c @ 28:11d14f688485

added clipping
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 22 Sep 2013 06:38:08 +0300
parents 5ff8ce78059a
children
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 case 'c':
290 if(mgl_isenabled(MGL_CULL_FACE)) {
291 mgl_disable(MGL_CULL_FACE);
292 } else {
293 mgl_enable(MGL_CULL_FACE);
294 }
295 break;
297 default:
298 break;
299 }
300 return 1;
301 }
303 static int bnstate;
304 static int prev_x, prev_y;
306 static void mouse_button(int bn, int x, int y)
307 {
308 bnstate = bn;
309 prev_x = x;
310 prev_y = y;
311 }
313 static void mouse_motion(int x, int y)
314 {
315 int dx, dy;
317 dx = x - prev_x;
318 dy = y - prev_y;
319 prev_x = x;
320 prev_y = y;
322 if(bnstate & MOUSE_LEFT) {
323 cam_theta += dx;
324 cam_phi += dy;
326 if(cam_phi > 90) cam_phi = 90;
327 if(cam_phi < -90) cam_phi = -90;
328 }
329 if(bnstate & MOUSE_RIGHT) {
330 cam_zoom += dy * 0.1;
331 if(cam_zoom < 0.0) {
332 cam_zoom = 0.0;
333 }
334 }
335 }
337 static void sighandler(int s)
338 {
339 set_video_mode(3);
341 switch(s) {
342 case SIGABRT:
343 fprintf(stderr, "abort\n");
344 break;
346 case SIGILL:
347 fprintf(stderr, "illegal operation\n");
348 break;
350 case SIGSEGV:
351 fprintf(stderr, "segmentation fault\n");
352 break;
354 case SIGINT:
355 fprintf(stderr, "interrupted\n");
356 break;
358 case SIGFPE:
359 fprintf(stderr, "floating point exception\n");
360 break;
362 default:
363 fprintf(stderr, "unexpected signal\n");
364 }
366 exit(1);
367 }
369 static int parse_args(int argc, char **argv)
370 {
371 int i;
373 for(i=1; i<argc; i++) {
374 if(argv[i][0] == '-') {
375 if(argv[i][2] != 0) {
376 goto invalid;
377 }
378 switch(argv[i][1]) {
379 case 'a':
380 auto_rotate = !auto_rotate;
381 break;
383 case 't':
384 texfile = argv[++i];
385 break;
387 case 'v':
388 use_vsync = !use_vsync;
389 break;
391 case 'p':
392 if(strcmp(argv[++i], "cube") == 0) {
393 prim = CUBE;
394 } else if(strcmp(argv[i], "sphere") == 0) {
395 prim = SPHERE;
396 } else if(strcmp(argv[i], "torus") == 0) {
397 prim = TORUS;
398 } else {
399 goto invalid;
400 }
401 break;
403 case 'w':
404 under_windows = 1;
405 break;
407 case 'h':
408 printf("Usage %s [options]\n", argv[0]);
409 printf("options:\n");
410 printf(" -p select one of (cube|sphere|torus)\n");
411 printf(" -v use vsync\n");
412 printf(" -w run under windows\n");
413 printf(" -h print usage information and exit\n");
414 exit(0);
416 default:
417 goto invalid;
418 }
419 } else {
420 goto invalid;
421 }
422 }
424 return 0;
426 invalid:
427 fprintf(stderr, "invalid argument: %s\n", argv[i]);
428 return -1;
429 }
432 static void print_perf(void)
433 {
434 unsigned long msec, avg_frame_time;
435 float sec, fps;
437 msec = get_msec();
438 if(!num_frm || msec < 1000) {
439 printf("leaving so soon? (%lu ms)\n", msec);
440 return;
441 }
443 sec = msec / 1000.0f;
444 fps = (float)num_frm / sec;
445 avg_frame_time = msec / num_frm;
447 printf("%lu frames in %.2f seconds\n", num_frm, sec);
448 printf(" avg. frame time: %lu ms\n", avg_frame_time);
449 printf(" avg. framerate: %.2f fps\n", fps);
450 }