deepstone

view src/test.c @ 3:0e781cc43178

adding textures
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 21 Nov 2011 10:16:09 +0200
parents 0b7f840afe4a
children c3e0bccd673e
line source
1 /*
2 256-color 3D graphics hack for real-mode DOS.
3 Copyright (C) 2011 John Tsiombikas <nuclear@member.fsf.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <signal.h>
22 #include <conio.h>
23 #include "vga.h"
24 #include "mingl.h"
25 #include "timer.h"
26 #include "mouse.h"
27 #include "palman.h"
28 #include "texture.h"
30 static int init(void);
31 static void shutdown(void);
32 static void redraw(void);
33 static void draw_cursor(unsigned char *fb, int xsz, int ysz, int mx, int my, int cidx);
34 static int keyb(char key);
35 static void mouse_button(int bn, int x, int y);
36 static void mouse_motion(int x, int y);
37 static void sighandler(int s);
38 static int parse_args(int argc, char **argv);
39 static void print_perf(void);
41 static unsigned char *fbuf;
43 static struct texture *tex;
45 static int white_base, red_base, green_base, blue_base;
46 static int grad_range;
48 static int use_vsync = 1;
49 static int under_windows = 0;
50 static unsigned long num_frm;
52 enum { CUBE, SPHERE, TORUS, NUM_PRIMS };
53 static int prim = SPHERE;
54 static int auto_rotate = 1;
55 static float cam_theta, cam_phi;
57 static int mx, my;
59 int main(int argc, char **argv)
60 {
61 int mbn, prev_mx = -1, prev_my = -1, prev_mbn = 0;
63 if(parse_args(argc, argv) == -1) {
64 return 1;
65 }
67 if(init() == -1) {
68 return 1;
69 }
71 reset_timer();
73 for(;;) {
74 if(kbhit()) {
75 if(keyb(getch()) == 0) {
76 break;
77 }
78 }
80 mbn = read_mouse(&mx, &my);
81 if(mbn != prev_mbn) {
82 mouse_button(mbn, mx, my);
83 prev_mbn = mbn;
84 }
85 if(mx != prev_mx || my != prev_my) {
86 if(mbn) {
87 mouse_motion(mx, my);
88 }
89 prev_mx = mx;
90 prev_my = my;
91 }
93 redraw();
94 }
96 shutdown();
97 print_perf();
98 return 0;
99 }
101 static int init(void)
102 {
103 int i;
104 struct palm_color *pal;
106 init_timer(under_windows ? 0 : 100);
108 set_video_mode(0x13);
110 signal(SIGINT, sighandler);
111 signal(SIGSEGV, sighandler);
112 signal(SIGFPE, sighandler);
113 signal(SIGILL, sighandler);
114 signal(SIGABRT, sighandler);
116 palm_add_color(255, 255, 255);
117 palm_add_color(255, 0, 0);
118 palm_add_color(0, 255, 0);
119 palm_add_color(0, 0, 255);
120 palm_build();
122 white_base = palm_color_base(255, 255, 255);
123 red_base = palm_color_base(255, 0, 0);
124 green_base = palm_color_base(0, 255, 0);
125 blue_base = palm_color_base(0, 0, 255);
126 grad_range = palm_color_range();
128 pal = palm_palette();
129 for(i=0; i<palm_palette_size(); i++) {
130 set_palette(i, pal[i].r, pal[i].g, pal[i].b);
131 }
133 if(mgl_init(320, 200) == -1) {
134 fprintf(stderr, "mgl init failed\n");
135 return -1;
136 }
137 fbuf = mgl_framebuffer();
139 mgl_enable(MGL_CULL_FACE);
140 mgl_enable(MGL_SMOOTH);
141 mgl_color_range(grad_range - 1); /* gradient range */
143 mgl_enable(MGL_LIGHTING);
144 mgl_light_intensity(0, 1.0);
145 mgl_light_direction(0, -0.5, 0.5, 1);
147 mgl_matrix_mode(MGL_PROJECTION);
148 mgl_load_identity();
149 mgl_perspective(45.0, 320.0 / 200.0, 0.5, 100.0);
151 if(!(tex = tex_gen_checker(64, 64, 3, 3, red_base, blue_base))) {
152 fprintf(stderr, "failed to generate texture\n");
153 return -1;
154 }
155 mgl_teximage(tex->width, tex->height, tex->pixels);
157 return 0;
158 }
160 static void shutdown(void)
161 {
162 mgl_free();
163 set_video_mode(3);
164 }
166 static void redraw(void)
167 {
168 float angle = get_msec() / 10.0;
169 mgl_clear(0);
171 mgl_matrix_mode(MGL_MODELVIEW);
172 mgl_load_identity();
173 if(auto_rotate) {
174 mgl_rotate(angle, 0, 0, 1);
175 mgl_rotate(angle * 0.5, 1, 0, 0);
176 } else {
177 mgl_rotate(cam_theta, 0, 1, 0);
178 mgl_rotate(cam_phi, 1, 0, 0);
179 }
180 mgl_translate(0, 0, -4);
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 ' ':
274 auto_rotate = !auto_rotate;
275 break;
277 case 'p':
278 prim = (prim + 1) % NUM_PRIMS;
279 break;
281 default:
282 break;
283 }
284 return 1;
285 }
287 static int bnstate;
288 static int prev_x, prev_y;
290 static void mouse_button(int bn, int x, int y)
291 {
292 bnstate = bn;
293 prev_x = x;
294 prev_y = y;
295 }
297 static void mouse_motion(int x, int y)
298 {
299 int dx, dy;
301 dx = x - prev_x;
302 dy = y - prev_y;
303 prev_x = x;
304 prev_y = y;
306 if(bnstate) {
307 cam_theta += dx;
308 cam_phi += dy;
310 if(cam_phi > 90) cam_phi = 90;
311 if(cam_phi < -90) cam_phi = -90;
312 }
313 }
315 static void sighandler(int s)
316 {
317 set_video_mode(3);
319 switch(s) {
320 case SIGABRT:
321 fprintf(stderr, "abort\n");
322 break;
324 case SIGILL:
325 fprintf(stderr, "illegal operation\n");
326 break;
328 case SIGSEGV:
329 fprintf(stderr, "segmentation fault\n");
330 break;
332 case SIGINT:
333 fprintf(stderr, "interrupted\n");
334 break;
336 case SIGFPE:
337 fprintf(stderr, "floating point exception\n");
338 break;
340 default:
341 fprintf(stderr, "unexpected signal\n");
342 }
344 exit(1);
345 }
347 static int parse_args(int argc, char **argv)
348 {
349 int i;
351 for(i=1; i<argc; i++) {
352 if(argv[i][0] == '-') {
353 if(argv[i][2] != 0) {
354 goto invalid;
355 }
356 switch(argv[i][1]) {
357 case 'a':
358 auto_rotate = !auto_rotate;
359 break;
361 case 'v':
362 use_vsync = !use_vsync;
363 break;
365 case 'p':
366 if(strcmp(argv[++i], "cube") == 0) {
367 prim = CUBE;
368 } else if(strcmp(argv[i], "sphere") == 0) {
369 prim = SPHERE;
370 } else if(strcmp(argv[i], "torus") == 0) {
371 prim = TORUS;
372 } else {
373 goto invalid;
374 }
375 break;
377 case 'w':
378 under_windows = 1;
379 break;
381 case 'h':
382 printf("Usage %s [options]\n", argv[0]);
383 printf("options:\n");
384 printf(" -p select one of (cube|sphere|torus)\n");
385 printf(" -v use vsync\n");
386 printf(" -w run under windows\n");
387 printf(" -h print usage information and exit\n");
388 exit(0);
390 default:
391 goto invalid;
392 }
393 } else {
394 goto invalid;
395 }
396 }
398 return 0;
400 invalid:
401 fprintf(stderr, "invalid argument: %s\n", argv[i]);
402 return -1;
403 }
406 static void print_perf(void)
407 {
408 unsigned long msec, avg_frame_time;
409 float sec, fps;
411 msec = get_msec();
412 if(!num_frm || msec < 1000) {
413 printf("leaving so soon? (%lu ms)\n", msec);
414 return;
415 }
417 sec = msec / 1000.0f;
418 fps = (float)num_frm / sec;
419 avg_frame_time = msec / num_frm;
421 printf("%lu frames in %.2f seconds\n", num_frm, sec);
422 printf(" avg. frame time: %lu ms\n", avg_frame_time);
423 printf(" avg. framerate: %.2f fps\n", fps);
424 }