rayzor

view src/main.cc @ 7:75bc89c2abc4

fixed the mouse handling problem
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 07 Apr 2014 08:05:06 +0300
parents a68dbf80d547
children 70e332156d02
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <math.h>
5 #include <signal.h>
6 #include "inttypes.h"
7 #include "gfx.h"
8 #include "keyb.h"
9 #include "mouse.h"
10 #include "logger.h"
11 #include "min3d.h"
12 #include "scene.h"
14 static bool init();
15 static void cleanup();
16 static void display();
17 static void swap_buffers();
18 static void draw_cursor(unsigned char *buf, int mx, int my);
19 static void handle_keyboard();
20 static void handle_mouse();
21 static void mouse_button(int bn, int x, int y);
22 static void mouse_motion(int x, int y);
23 static bool parse_args(int argc, char **argv);
24 static void sig(int s);
26 static int xsz = 640;
27 static int ysz = 480;
28 static int bpp = 24;
29 static int bytespp;
30 static bool novideo;
31 static unsigned char *fb;
32 static unsigned char *backbuf;
33 static int rbits, gbits, bbits;
34 static int rshift, gshift, bshift;
35 static unsigned int rmask, gmask, bmask;
37 static int mx, my; // mouse cursor
38 static float cam_theta, cam_phi = 25, cam_dist = 8;
40 static bool use_mouse;
41 static bool quit;
43 struct m3d_image rbuf;
44 static Scene *scn;
46 int main(int argc, char **argv)
47 {
48 if(!parse_args(argc, argv)) {
49 return 1;
50 }
51 if(!init()) {
52 return 1;
53 }
55 // main loop
56 for(;;) {
57 handle_keyboard();
58 handle_mouse();
59 if(quit) break;
61 display();
63 if(novideo) break;
64 }
66 cleanup();
67 printf("Thank you for using Rayzor!\n");
68 return 0;
69 }
71 static bool init()
72 {
73 signal(SIGINT, sig);
74 signal(SIGSEGV, sig);
75 signal(SIGILL, sig);
76 signal(SIGFPE, sig);
78 if(!novideo) {
79 if(kb_init(32) == -1) {
80 fprintf(stderr, "failed to initialize keyboard driver\n");
81 return false;
82 }
84 if(!(fb = (unsigned char*)set_video_mode(xsz, ysz, bpp))) {
85 set_text_mode();
86 fprintf(stderr, "failed to set video mode: %dx%d %dbpp\n", xsz, ysz, bpp);
87 return false;
88 }
89 bpp = get_color_depth();
90 get_color_bits(&rbits, &gbits, &bbits);
91 get_color_shift(&rshift, &gshift, &bshift);
92 get_color_mask(&rmask, &gmask, &bmask);
93 bytespp = (int)ceil(bpp / 8.0);
95 printlog("bpp: %d (%d %d %d)\n", bpp, rbits, gbits, bbits);
96 printlog("shift: %d %d %d\n", rshift, gshift, bshift);
97 printlog("mask: %x %x %x\n", rmask, gmask, bmask);
99 if(have_mouse()) {
100 use_mouse = true;
101 set_mouse_limits(0, 0, xsz - 1, ysz - 1);
102 }
103 } else {
104 logger_output(stdout);
105 printlog("novideo (debug) mode\n");
106 bpp = 24;
107 rbits = gbits = bbits = 8;
108 bytespp = 3;
109 }
111 backbuf = new unsigned char[xsz * ysz * 3];
112 if(!backbuf) {
113 return false;
114 }
116 m3d_init();
117 rbuf.pixels = backbuf;
118 rbuf.xsz = xsz;
119 rbuf.ysz = ysz;
120 m3d_set_buffers(&rbuf, 0);
122 m3d_matrix_mode(M3D_PROJECTION);
123 m3d_load_identity();
124 m3d_perspective(50.0, (float)xsz / (float)ysz, 0.5, 500.0);
126 scn = new Scene;
128 Sphere *sph = new Sphere;
129 scn->add_object(sph);
131 return true;
132 }
134 static void cleanup()
135 {
136 delete scn;
138 m3d_shutdown();
139 delete [] backbuf;
141 if(!novideo) {
142 set_text_mode();
143 kb_shutdown();
144 }
145 }
148 static void display()
149 {
150 m3d_clear(M3D_COLOR_BUFFER_BIT);
152 m3d_matrix_mode(M3D_MODELVIEW);
153 m3d_load_identity();
154 m3d_translate(0, 0, -cam_dist);
155 m3d_rotate(cam_phi, 1, 0, 0);
156 m3d_rotate(cam_theta, 0, 1, 0);
158 scn->draw();
160 // draw the mouse cursor
161 if(use_mouse) {
162 draw_cursor(backbuf, mx, my);
163 }
165 if(!novideo) {
166 swap_buffers();
167 wait_vsync();
168 }
169 }
171 #define PACK_RGB(r, g, b) \
172 ((((r) << rshift) & rmask) | \
173 (((g) << gshift) & gmask) | \
174 (((b) << bshift) & bmask))
176 static void swap_buffers()
177 {
178 unsigned char *src = backbuf;
179 int num_pixels = xsz * ysz;
181 switch(bpp) {
182 case 32:
183 {
184 uint32_t *dest = (uint32_t*)fb;
185 for(int i=0; i<num_pixels; i++) {
186 *dest++ = PACK_RGB(src[0], src[1], src[2]);
187 src += 3;
188 }
189 }
190 break;
192 case 24:
193 memcpy(fb, backbuf, num_pixels * 3);
194 break;
196 case 16:
197 case 15:
198 {
199 int srs = 8 - rbits;
200 int sgs = 8 - gbits;
201 int sbs = 8 - bbits;
202 uint16_t *dest = (uint16_t*)fb;
203 for(int i=0; i<num_pixels; i++) {
204 *dest++ = PACK_RGB(src[0] >> srs, src[1] >> sgs, src[2] >> sbs);
205 src += 3;
206 }
207 }
208 break;
210 default:
211 break;
212 }
213 }
215 static void draw_cursor(unsigned char *buf, int mx, int my)
216 {
217 unsigned char *cptr = buf + (my * xsz + mx) * 3;
218 int i, cw[2] = {4, 4}, ch[2] = {4, 4};
220 if(mx < cw[0]) cw[0] = mx;
221 if(my < ch[0]) ch[0] = my;
222 if(xsz - mx < cw[1]) cw[1] = xsz - mx - 1;
223 if(ysz - my < ch[1]) ch[1] = ysz - my - 1;
225 for(i=1; i<cw[0]; i++) {
226 int idx = -i * 3;
227 cptr[idx] = 255;
228 cptr[idx + 1] = 255;
229 cptr[idx + 2] = 255;
230 }
231 for(i=1; i<cw[1]; i++) {
232 int idx = i * 3;
233 cptr[idx] = 255;
234 cptr[idx + 1] = 255;
235 cptr[idx + 2] = 255;
236 }
237 for(i=1; i<ch[0]; i++) {
238 int idx = -i * xsz * 3;
239 cptr[idx] = 255;
240 cptr[idx + 1] = 255;
241 cptr[idx + 2] = 255;
242 }
243 for(i=1; i<ch[1]; i++) {
244 int idx = i * xsz * 3;
245 cptr[idx] = 255;
246 cptr[idx + 1] = 255;
247 cptr[idx + 2] = 255;
248 }
249 }
251 static void handle_keyboard()
252 {
253 int key;
255 if(novideo) return;
257 while((key = kb_getkey()) != -1) {
258 switch(key) {
259 case 27:
260 quit = true;
261 return;
262 }
263 }
264 }
266 static void handle_mouse()
267 {
268 static int prev_mx, prev_my, prev_bnmask;
269 int /*mx, my,*/ bnmask;
271 if(!use_mouse || novideo) return;
273 bnmask = read_mouse(&mx, &my);
274 if(bnmask != prev_bnmask) {
275 mouse_button(bnmask, mx, my);
276 prev_bnmask = bnmask;
277 }
278 if(mx != prev_mx || my != prev_my) {
279 mouse_motion(mx, my);
280 prev_mx = mx;
281 prev_my = my;
282 }
283 }
285 static int bnstate;
286 static int prev_x = -1, prev_y;
287 static void mouse_button(int bn, int x, int y)
288 {
289 bnstate = bn;
290 prev_x = x;
291 prev_y = y;
292 }
294 static void mouse_motion(int x, int y)
295 {
296 int dx = x - prev_x;
297 int dy = y - prev_y;
298 prev_x = x;
299 prev_y = y;
301 if(bnstate & 1) {
302 cam_theta += dx * 0.5;
303 cam_phi += dy * 0.5;
305 if(cam_phi < -90) cam_phi = -90;
306 if(cam_phi > 90) cam_phi = 90;
307 }
308 if(bnstate & 2) {
309 cam_dist += dy * 0.1;
310 if(cam_dist < 0) cam_dist = 0;
311 }
312 }
314 static struct {
315 int opt;
316 const char *lopt;
317 const char *desc;
318 } options[] = {
319 {'s', "size", "resolution <xres>x<yres>[:bpp]"},
320 {'n', "novid", "don't switch video mode (for debugging)"},
321 {'h', "help", "print usage information and exit"},
322 {-1, 0, 0}
323 };
325 static void print_usage(const char *argv0)
326 {
327 printf("%s usage\n", argv0);
328 for(int i=0; options[i].opt != -1; i++) {
329 printf(" -%c, -%s: %s\n", options[i].opt, options[i].lopt, options[i].desc);
330 }
331 exit(0);
332 }
334 static bool parse_args(int argc, char **argv)
335 {
336 for(int i=1; i<argc; i++) {
337 if(argv[i][0] == '-') {
338 int opt = -1;
340 for(int j=0; options[j].opt != -1; j++) {
341 if(argv[i][2] == 0) {
342 if(argv[i][1] == options[j].opt) {
343 opt = options[j].opt;
344 break;
345 }
346 } else {
347 if(strcmp(argv[i] + 1, options[j].lopt) == 0) {
348 opt = options[j].opt;
349 break;
350 }
351 }
352 }
354 switch(opt) {
355 case 's':
356 if(sscanf(argv[++i], "%dx%d:%d", &xsz, &ysz, &bpp) < 2) {
357 fprintf(stderr, "%s must be followed by a resolution: WxH\n", argv[i - 1]);
358 return false;
359 }
360 break;
362 case 'n':
363 novideo = true;
364 break;
366 case 'h':
367 print_usage(argv[0]); // doesn't return
368 break;
370 default:
371 fprintf(stderr, "unknown option: %s\n", argv[i]);
372 return false;
373 }
374 } else {
375 fprintf(stderr, "unexpected argument: %s\n", argv[i]);
376 return false;
377 }
378 }
379 return true;
380 }
382 static void sig(int s)
383 {
384 cleanup();
385 fprintf(stderr, "signal caught: %d\n", s);
386 }