Updated our source code header to explicitly mention that we are GPL v2 or
[Rockbox.git] / apps / plugins / cube.c
blob55721fb6c2ce3dc746be29c94c1f5c113657c011
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 Damien Teney
11 * modified to use int instead of float math by Andreas Zwirtes
12 * heavily extended by Jens Arnold
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ***************************************************************************/
23 #include "plugin.h"
24 #include "grey.h"
25 #include "playergfx.h"
26 #include "xlcd.h"
27 #include "fixedpoint.h"
29 PLUGIN_HEADER
31 /* Loops that the values are displayed */
32 #define DISP_TIME 30
34 /* variable button definitions */
35 #if CONFIG_KEYPAD == RECORDER_PAD
36 #define CUBE_QUIT BUTTON_OFF
37 #define CUBE_X_INC BUTTON_RIGHT
38 #define CUBE_X_DEC BUTTON_LEFT
39 #define CUBE_Y_INC BUTTON_UP
40 #define CUBE_Y_DEC BUTTON_DOWN
41 #define CUBE_Z_INC BUTTON_F2
42 #define CUBE_Z_DEC BUTTON_F1
43 #define CUBE_MODE BUTTON_F3
44 #define CUBE_PAUSE BUTTON_PLAY
45 #define CUBE_HIGHSPEED BUTTON_ON
47 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
48 #define CUBE_QUIT BUTTON_OFF
49 #define CUBE_X_INC BUTTON_RIGHT
50 #define CUBE_X_DEC BUTTON_LEFT
51 #define CUBE_Y_INC BUTTON_UP
52 #define CUBE_Y_DEC BUTTON_DOWN
53 #define CUBE_Z_INC BUTTON_F2
54 #define CUBE_Z_DEC BUTTON_F1
55 #define CUBE_MODE BUTTON_F3
56 #define CUBE_PAUSE BUTTON_SELECT
57 #define CUBE_HIGHSPEED BUTTON_ON
59 #elif CONFIG_KEYPAD == PLAYER_PAD
60 #define CUBE_QUIT BUTTON_STOP
61 #define CUBE_X_INC BUTTON_RIGHT
62 #define CUBE_X_DEC BUTTON_LEFT
63 #define CUBE_Y_INC (BUTTON_ON | BUTTON_RIGHT)
64 #define CUBE_Y_DEC (BUTTON_ON | BUTTON_LEFT)
65 #define CUBE_Z_INC (BUTTON_MENU | BUTTON_RIGHT)
66 #define CUBE_Z_DEC (BUTTON_MENU | BUTTON_LEFT)
67 #define CUBE_MODE_PRE BUTTON_MENU
68 #define CUBE_MODE (BUTTON_MENU | BUTTON_REL)
69 #define CUBE_PAUSE BUTTON_PLAY
70 #define CUBE_HIGHSPEED_PRE BUTTON_ON
71 #define CUBE_HIGHSPEED (BUTTON_ON | BUTTON_REL)
73 #elif CONFIG_KEYPAD == ONDIO_PAD
74 #define CUBE_QUIT BUTTON_OFF
75 #define CUBE_X_INC BUTTON_RIGHT
76 #define CUBE_X_DEC BUTTON_LEFT
77 #define CUBE_Y_INC BUTTON_UP
78 #define CUBE_Y_DEC BUTTON_DOWN
79 #define CUBE_Z_INC (BUTTON_MENU | BUTTON_UP)
80 #define CUBE_Z_DEC (BUTTON_MENU | BUTTON_DOWN)
81 #define CUBE_MODE_PRE BUTTON_MENU
82 #define CUBE_MODE (BUTTON_MENU | BUTTON_REL)
83 #define CUBE_PAUSE (BUTTON_MENU | BUTTON_LEFT)
84 #define CUBE_HIGHSPEED (BUTTON_MENU | BUTTON_RIGHT)
86 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
87 (CONFIG_KEYPAD == IRIVER_H300_PAD)
88 #define CUBE_QUIT BUTTON_OFF
89 #define CUBE_X_INC BUTTON_RIGHT
90 #define CUBE_X_DEC BUTTON_LEFT
91 #define CUBE_Y_INC BUTTON_UP
92 #define CUBE_Y_DEC BUTTON_DOWN
93 #define CUBE_Z_INC (BUTTON_ON | BUTTON_UP)
94 #define CUBE_Z_DEC (BUTTON_ON | BUTTON_DOWN)
95 #define CUBE_MODE BUTTON_MODE
96 #define CUBE_PAUSE_PRE BUTTON_ON
97 #define CUBE_PAUSE (BUTTON_ON | BUTTON_REL)
98 #define CUBE_HIGHSPEED BUTTON_SELECT
100 #define CUBE_RC_QUIT BUTTON_RC_STOP
102 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
103 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
104 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
105 #define CUBE_QUIT BUTTON_MENU
106 #define CUBE_X_INC BUTTON_RIGHT
107 #define CUBE_X_DEC BUTTON_LEFT
108 #define CUBE_Y_INC BUTTON_SCROLL_FWD
109 #define CUBE_Y_DEC BUTTON_SCROLL_BACK
110 #define CUBE_Z_INC (BUTTON_SELECT | BUTTON_RIGHT)
111 #define CUBE_Z_DEC (BUTTON_SELECT | BUTTON_LEFT)
112 #define CUBE_MODE (BUTTON_SELECT | BUTTON_MENU)
113 #define CUBE_PAUSE_PRE BUTTON_PLAY
114 #define CUBE_PAUSE (BUTTON_PLAY | BUTTON_REL)
115 #define CUBE_HIGHSPEED (BUTTON_SELECT | BUTTON_PLAY)
117 #elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
118 #define CUBE_QUIT BUTTON_PLAY
119 #define CUBE_X_INC BUTTON_RIGHT
120 #define CUBE_X_DEC BUTTON_LEFT
121 #define CUBE_Y_INC BUTTON_UP
122 #define CUBE_Y_DEC BUTTON_DOWN
123 #define CUBE_Z_INC BUTTON_MODE
124 #define CUBE_Z_DEC BUTTON_EQ
125 #define CUBE_MODE (BUTTON_SELECT | BUTTON_REPEAT)
126 #define CUBE_PAUSE (BUTTON_SELECT | BUTTON_REL)
127 #define CUBE_HIGHSPEED (BUTTON_MODE | BUTTON_EQ) /* TODO: this is impossible */
129 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
130 #define CUBE_QUIT BUTTON_POWER
131 #define CUBE_X_INC BUTTON_LEFT
132 #define CUBE_X_DEC BUTTON_RIGHT
133 #define CUBE_Y_INC BUTTON_UP
134 #define CUBE_Y_DEC BUTTON_DOWN
135 #define CUBE_Z_INC (BUTTON_PLAY | BUTTON_UP)
136 #define CUBE_Z_DEC (BUTTON_PLAY | BUTTON_DOWN)
137 #define CUBE_MODE BUTTON_SELECT
138 #define CUBE_PAUSE_PRE BUTTON_PLAY
139 #define CUBE_PAUSE (BUTTON_PLAY | BUTTON_REL)
140 #define CUBE_HIGHSPEED (BUTTON_REC | BUTTON_REL)
142 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
143 #define CUBE_QUIT BUTTON_POWER
144 #define CUBE_X_INC BUTTON_LEFT
145 #define CUBE_X_DEC BUTTON_RIGHT
146 #define CUBE_Y_INC BUTTON_UP
147 #define CUBE_Y_DEC BUTTON_DOWN
148 #define CUBE_Z_INC BUTTON_VOL_UP
149 #define CUBE_Z_DEC BUTTON_VOL_DOWN
150 #define CUBE_MODE BUTTON_MENU
151 #define CUBE_PAUSE BUTTON_SELECT
152 #define CUBE_HIGHSPEED BUTTON_A
154 #elif (CONFIG_KEYPAD == SANSA_E200_PAD)
155 #define CUBE_QUIT BUTTON_POWER
156 #define CUBE_X_INC BUTTON_LEFT
157 #define CUBE_X_DEC BUTTON_RIGHT
158 #define CUBE_Y_INC BUTTON_SCROLL_FWD
159 #define CUBE_Y_DEC BUTTON_SCROLL_BACK
160 #define CUBE_Z_INC BUTTON_UP
161 #define CUBE_Z_DEC BUTTON_DOWN
162 #define CUBE_MODE_PRE BUTTON_SELECT
163 #define CUBE_MODE (BUTTON_SELECT|BUTTON_REPEAT)
164 #define CUBE_PAUSE_PRE BUTTON_SELECT
165 #define CUBE_PAUSE (BUTTON_SELECT|BUTTON_REL)
166 #define CUBE_HIGHSPEED BUTTON_REC
168 #elif (CONFIG_KEYPAD == SANSA_C200_PAD)
169 #define CUBE_QUIT BUTTON_POWER
170 #define CUBE_X_INC BUTTON_LEFT
171 #define CUBE_X_DEC BUTTON_RIGHT
172 #define CUBE_Y_INC BUTTON_VOL_UP
173 #define CUBE_Y_DEC BUTTON_VOL_DOWN
174 #define CUBE_Z_INC BUTTON_UP
175 #define CUBE_Z_DEC BUTTON_DOWN
176 #define CUBE_MODE_PRE BUTTON_SELECT
177 #define CUBE_MODE (BUTTON_SELECT|BUTTON_REPEAT)
178 #define CUBE_PAUSE_PRE BUTTON_SELECT
179 #define CUBE_PAUSE (BUTTON_SELECT|BUTTON_REL)
180 #define CUBE_HIGHSPEED BUTTON_REC
183 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
184 #define CUBE_QUIT BUTTON_POWER
185 #define CUBE_X_INC BUTTON_LEFT
186 #define CUBE_X_DEC BUTTON_RIGHT
187 #define CUBE_Y_INC BUTTON_SCROLL_UP
188 #define CUBE_Y_DEC BUTTON_SCROLL_DOWN
189 #define CUBE_Z_INC (BUTTON_PLAY | BUTTON_SCROLL_UP)
190 #define CUBE_Z_DEC (BUTTON_PLAY | BUTTON_SCROLL_DOWN)
191 #define CUBE_MODE BUTTON_REW
192 #define CUBE_PAUSE_PRE BUTTON_PLAY
193 #define CUBE_PAUSE (BUTTON_PLAY | BUTTON_REL)
194 #define CUBE_HIGHSPEED (BUTTON_FF | BUTTON_REL)
196 #elif CONFIG_KEYPAD == MROBE500_PAD
197 #define CUBE_QUIT BUTTON_POWER
198 #define CUBE_X_INC BUTTON_LEFT
199 #define CUBE_X_DEC BUTTON_RIGHT
200 #define CUBE_Y_INC BUTTON_RC_PLAY
201 #define CUBE_Y_DEC BUTTON_RC_DOWN
202 #define CUBE_Z_INC BUTTON_RC_VOL_UP
203 #define CUBE_Z_DEC BUTTON_RC_VOL_DOWN
204 #define CUBE_MODE BUTTON_RC_MODE
205 #define CUBE_PAUSE_PRE BUTTON_RC_HEART
206 #define CUBE_PAUSE (BUTTON_RC_HEART | BUTTON_REL)
207 #define CUBE_HIGHSPEED BUTTON_RC_HEART
209 #elif CONFIG_KEYPAD == GIGABEAT_S_PAD
210 #define CUBE_QUIT BUTTON_BACK
211 #define CUBE_X_INC BUTTON_LEFT
212 #define CUBE_X_DEC BUTTON_RIGHT
213 #define CUBE_Y_INC BUTTON_UP
214 #define CUBE_Y_DEC BUTTON_DOWN
215 #define CUBE_Z_INC BUTTON_VOL_UP
216 #define CUBE_Z_DEC BUTTON_VOL_DOWN
217 #define CUBE_MODE BUTTON_PREV
218 #define CUBE_PAUSE_PRE BUTTON_PLAY
219 #define CUBE_PAUSE (BUTTON_PLAY | BUTTON_REL)
220 #define CUBE_HIGHSPEED (BUTTON_NEXT | BUTTON_REL)
222 #elif (CONFIG_KEYPAD == MROBE100_PAD)
223 #define CUBE_QUIT BUTTON_POWER
224 #define CUBE_X_INC BUTTON_LEFT
225 #define CUBE_X_DEC BUTTON_RIGHT
226 #define CUBE_Y_INC BUTTON_UP
227 #define CUBE_Y_DEC BUTTON_DOWN
228 #define CUBE_Z_INC (BUTTON_DISPLAY | BUTTON_UP)
229 #define CUBE_Z_DEC (BUTTON_DISPLAY | BUTTON_DOWN)
230 #define CUBE_MODE BUTTON_MENU
231 #define CUBE_PAUSE BUTTON_PLAY
232 #define CUBE_HIGHSPEED BUTTON_SELECT
234 #elif (CONFIG_KEYPAD == IAUDIO_M3_PAD)
235 #define CUBE_QUIT BUTTON_RC_REC
236 #define CUBE_X_INC BUTTON_RC_FF
237 #define CUBE_X_DEC BUTTON_RC_REW
238 #define CUBE_Y_INC BUTTON_RC_VOL_UP
239 #define CUBE_Y_DEC BUTTON_RC_VOL_DOWN
240 #define CUBE_Z_INC BUTTON_VOL_UP /* FIXME: quick hack */
241 #define CUBE_Z_DEC BUTTON_VOL_DOWN
242 #define CUBE_MODE BUTTON_RC_MODE
243 #define CUBE_PAUSE BUTTON_RC_PLAY
244 #define CUBE_HIGHSPEED BUTTON_RC_MENU
246 #elif CONFIG_KEYPAD == COWOND2_PAD
247 #define CUBE_QUIT BUTTON_POWER
249 #else
250 #error No keymap defined!
251 #endif
253 #ifdef HAVE_TOUCHPAD
254 // not enough touchfields, so CUBE_QUIT have to be
255 // mapped to a real button
256 //ifndef CUBE_QUIT
257 //#define CUBE_QUIT BUTTON_TOPLEFT
258 //#endif
259 #ifndef CUBE_X_INC
260 #define CUBE_X_INC BUTTON_MIDRIGHT
261 #endif
262 #ifndef CUBE_X_DEC
263 #define CUBE_X_DEC BUTTON_MIDLEFT
264 #endif
265 #ifndef CUBE_Y_INC
266 #define CUBE_Y_INC BUTTON_TOPMIDDLE
267 #endif
268 #ifndef CUBE_Y_DEC
269 #define CUBE_Y_DEC BUTTON_BOTTOMMIDDLE
270 #endif
271 #ifndef CUBE_Z_INC
272 #define CUBE_Z_INC BUTTON_BOTTOMRIGHT
273 #endif
274 #ifndef CUBE_Z_DEC
275 #define CUBE_Z_DEC BUTTON_BOTTOMLEFT
276 #endif
277 #ifndef CUBE_MODE
278 #define CUBE_MODE BUTTON_TOPRIGHT
279 #endif
280 #ifndef CUBE_PAUSE
281 #define CUBE_PAUSE (BUTTON_CENTER | BUTTON_REL)
282 #endif
283 #ifndef CUBE_HIGHSPEED
284 #define CUBE_HIGHSPEED BUTTON_TOPLEFT
285 #endif
286 #endif
289 #ifdef HAVE_LCD_BITMAP
291 #define DIST (10 * MIN(LCD_HEIGHT, LCD_WIDTH) / 16)
292 static int x_off = LCD_WIDTH/2;
293 static int y_off = LCD_HEIGHT/2;
295 #if LCD_DEPTH == 1
296 #define USE_GSLIB
297 GREY_INFO_STRUCT
298 struct my_lcd {
299 void (*update)(void);
300 void (*clear_display)(void);
301 void (*drawline)(int x1, int y1, int x2, int y2);
302 void (*putsxy)(int x, int y, const unsigned char *string);
305 static struct my_lcd greyfuncs = {
306 grey_update, grey_clear_display, grey_drawline, grey_putsxy
308 static struct my_lcd lcdfuncs; /* initialised at runtime */
309 static struct my_lcd *mylcd = &greyfuncs;
311 #define MYLCD(fn) mylcd->fn
312 #define MY_FILLTRIANGLE(x1, y1, x2, y2, x3, y3) grey_filltriangle(x1, y1, x2, y2, x3, y3)
313 #define MY_SET_FOREGROUND(fg) grey_set_foreground(fg)
314 #define MY_GET_FOREGROUND() grey_get_foreground()
316 #else
317 #define MYLCD(fn) rb->lcd_ ## fn
318 #define MY_FILLTRIANGLE(x1, y1, x2, y2, x3, y3) xlcd_filltriangle(x1, y1, x2, y2, x3, y3)
319 #define MY_SET_FOREGROUND(fg) rb->lcd_set_foreground(fg)
320 #define MY_GET_FOREGROUND() rb->lcd_get_foreground()
321 #endif
323 #if CONFIG_LCD == LCD_SSD1815
324 #define ASPECT 320 /* = 1.25 (fixed point 24.8) */
325 #else
326 #define ASPECT 256 /* = 1.00 */
327 #endif
329 #else /* !LCD_BITMAP */
331 #define MYLCD(fn) pgfx_ ## fn
332 #define DIST 9
333 static int x_off = 10;
334 static int y_off = 7;
335 #define ASPECT 300 /* = 1.175 */
337 #endif /* !LCD_BITMAP */
339 struct point_3D {
340 long x, y, z;
343 struct point_2D {
344 long x, y;
347 struct line {
348 int start, end;
351 struct face {
352 int corner[4];
353 int line[4];
356 /* initial, unrotated cube corners */
357 static const struct point_3D sommet[8] =
359 {-DIST, -DIST, -DIST},
360 { DIST, -DIST, -DIST},
361 { DIST, DIST, -DIST},
362 {-DIST, DIST, -DIST},
363 {-DIST, -DIST, DIST},
364 { DIST, -DIST, DIST},
365 { DIST, DIST, DIST},
366 {-DIST, DIST, DIST}
369 /* The 12 lines forming the edges */
370 static const struct line lines[12] =
372 {0, 1}, {1, 2}, {2, 3}, {3, 0},
373 {4, 7}, {7, 6}, {6, 5}, {5, 4},
374 {0, 4}, {1, 5}, {2, 6}, {3, 7}
377 static bool lines_drawn[12];
379 /* The 6 faces of the cube; points are in clockwise order when viewed
380 from the outside */
381 static const struct face faces[6] =
383 {{0, 1, 2, 3}, {0, 1, 2, 3}},
384 {{4, 7, 6, 5}, {4, 5, 6, 7}},
385 {{0, 4, 5, 1}, {8, 7, 9, 0}},
386 {{2, 6, 7, 3}, {10, 5, 11, 2}},
387 {{0, 3, 7, 4}, {3, 11, 4, 8}},
388 {{1, 5, 6, 2}, {9, 6, 10, 1}}
391 #if LCD_DEPTH > 1 || defined(USE_GSLIB)
392 static const unsigned face_colors[6] =
394 #ifdef HAVE_LCD_COLOR
395 LCD_RGBPACK(255, 0, 0), LCD_RGBPACK(255, 0, 0), LCD_RGBPACK(0, 255, 0),
396 LCD_RGBPACK(0, 255, 0), LCD_RGBPACK(0, 0, 255), LCD_RGBPACK(0, 0, 255)
397 #elif defined(USE_GSLIB)
398 #ifdef MROBE_100
399 GREY_LIGHTGRAY, GREY_LIGHTGRAY, GREY_DARKGRAY,
400 GREY_DARKGRAY, GREY_WHITE, GREY_WHITE
401 #else
402 GREY_LIGHTGRAY, GREY_LIGHTGRAY, GREY_DARKGRAY,
403 GREY_DARKGRAY, GREY_BLACK, GREY_BLACK
404 #endif
405 #else
406 LCD_LIGHTGRAY, LCD_LIGHTGRAY, LCD_DARKGRAY,
407 LCD_DARKGRAY, LCD_BLACK, LCD_BLACK
408 #endif
410 #endif
412 enum {
413 #if LCD_DEPTH > 1 || defined(USE_GSLIB)
414 SOLID,
415 #endif
416 HIDDEN_LINES,
417 WIREFRAME,
418 NUM_MODES
421 static int mode = 0;
423 static struct point_3D point3D[8];
424 static struct point_2D point2D[8];
425 static long matrice[3][3];
427 static const int nb_points = 8;
428 static long z_off = 600;
430 static const struct plugin_api* rb;
432 static void cube_rotate(int xa, int ya, int za)
434 int i;
435 /* Just to prevent unnecessary lookups */
436 long sxa, cxa, sya, cya, sza, cza;
438 sxa = sin_int(xa);
439 cxa = cos_int(xa);
440 sya = sin_int(ya);
441 cya = cos_int(ya);
442 sza = sin_int(za);
443 cza = cos_int(za);
445 /* calculate overall translation matrix */
446 matrice[0][0] = (cza * cya) >> 14;
447 matrice[1][0] = (sza * cya) >> 14;
448 matrice[2][0] = -sya;
450 matrice[0][1] = (((cza * sya) >> 14) * sxa - sza * cxa) >> 14;
451 matrice[1][1] = (((sza * sya) >> 14) * sxa + cxa * cza) >> 14;
452 matrice[2][1] = (sxa * cya) >> 14;
454 matrice[0][2] = (((cza * sya) >> 14) * cxa + sza * sxa) >> 14;
455 matrice[1][2] = (((sza * sya) >> 14) * cxa - cza * sxa) >> 14;
456 matrice[2][2] = (cxa * cya) >> 14;
458 /* apply translation matrix to all points */
459 for (i = 0; i < nb_points; i++)
461 point3D[i].x = matrice[0][0] * sommet[i].x + matrice[1][0] * sommet[i].y
462 + matrice[2][0] * sommet[i].z;
464 point3D[i].y = matrice[0][1] * sommet[i].x + matrice[1][1] * sommet[i].y
465 + matrice[2][1] * sommet[i].z;
467 point3D[i].z = matrice[0][2] * sommet[i].x + matrice[1][2] * sommet[i].y
468 + matrice[2][2] * sommet[i].z;
472 static void cube_viewport(void)
474 int i;
476 /* Do viewport transformation for all points */
477 for (i = 0; i < nb_points; i++)
479 #if ASPECT != 256
480 point2D[i].x = (point3D[i].x * ASPECT) / (point3D[i].z + (z_off << 14))
481 + x_off;
482 #else
483 point2D[i].x = (point3D[i].x << 8) / (point3D[i].z + (z_off << 14))
484 + x_off;
485 #endif
486 point2D[i].y = (point3D[i].y << 8) / (point3D[i].z + (z_off << 14))
487 + y_off;
491 static void cube_draw(void)
493 int i, j, line;
494 #if LCD_DEPTH > 1 || defined(USE_GSLIB)
495 unsigned old_foreground;
496 #endif
498 switch (mode)
500 #if LCD_DEPTH > 1 || defined(USE_GSLIB)
501 case SOLID:
503 old_foreground = MY_GET_FOREGROUND();
504 for (i = 0; i < 6; i++)
506 /* backface culling; if the shape winds counter-clockwise, we are
507 * looking at the backface, and the (simplified) cross product
508 * is < 0. Do not draw it. */
509 if (0 >= (point2D[faces[i].corner[1]].x - point2D[faces[i].corner[0]].x)
510 * (point2D[faces[i].corner[2]].y - point2D[faces[i].corner[1]].y)
511 - (point2D[faces[i].corner[1]].y - point2D[faces[i].corner[0]].y)
512 * (point2D[faces[i].corner[2]].x - point2D[faces[i].corner[1]].x))
513 continue;
515 MY_SET_FOREGROUND(face_colors[i]);
516 MY_FILLTRIANGLE(point2D[faces[i].corner[0]].x,
517 point2D[faces[i].corner[0]].y,
518 point2D[faces[i].corner[1]].x,
519 point2D[faces[i].corner[1]].y,
520 point2D[faces[i].corner[2]].x,
521 point2D[faces[i].corner[2]].y);
522 MY_FILLTRIANGLE(point2D[faces[i].corner[0]].x,
523 point2D[faces[i].corner[0]].y,
524 point2D[faces[i].corner[2]].x,
525 point2D[faces[i].corner[2]].y,
526 point2D[faces[i].corner[3]].x,
527 point2D[faces[i].corner[3]].y);
530 MY_SET_FOREGROUND(old_foreground);
531 break;
532 #endif /* (LCD_DEPTH > 1) || GSLIB */
534 case HIDDEN_LINES:
536 rb->memset(lines_drawn, 0, sizeof(lines_drawn));
537 for (i = 0; i < 6; i++)
539 /* backface culling; if the shape winds counter-clockwise, we are
540 * looking at the backface, and the (simplified) cross product
541 * is < 0. Do not draw it. */
542 if (0 >= (point2D[faces[i].corner[1]].x - point2D[faces[i].corner[0]].x)
543 * (point2D[faces[i].corner[2]].y - point2D[faces[i].corner[1]].y)
544 - (point2D[faces[i].corner[1]].y - point2D[faces[i].corner[0]].y)
545 * (point2D[faces[i].corner[2]].x - point2D[faces[i].corner[1]].x))
546 continue;
548 for (j = 0; j < 4; j++)
550 line = faces[i].line[j];
551 if (!lines_drawn[line])
553 lines_drawn[line] = true;
554 MYLCD(drawline)(point2D[lines[line].start].x,
555 point2D[lines[line].start].y,
556 point2D[lines[line].end].x,
557 point2D[lines[line].end].y);
561 break;
563 case WIREFRAME:
565 for (i = 0; i < 12; i++)
566 MYLCD(drawline)(point2D[lines[i].start].x,
567 point2D[lines[i].start].y,
568 point2D[lines[i].end].x,
569 point2D[lines[i].end].y);
570 break;
574 void cleanup(void *parameter)
576 (void)parameter;
578 #ifdef USE_GSLIB
579 grey_release();
580 #elif defined HAVE_LCD_CHARCELLS
581 pgfx_release();
582 #endif
585 enum plugin_status plugin_start(const struct plugin_api* api, const void* parameter)
587 char buffer[30];
588 int t_disp = 0;
589 #ifdef USE_GSLIB
590 unsigned char *gbuf;
591 size_t gbuf_size = 0;
592 bool mode_switch = true;
593 #endif
595 int button;
596 int lastbutton = BUTTON_NONE;
597 int xa = 0;
598 int ya = 0;
599 int za = 0;
600 int xs = 1;
601 int ys = 3;
602 int zs = 1;
603 bool highspeed = false;
604 bool paused = false;
605 bool redraw = true;
606 bool exit = false;
608 (void)(parameter);
609 rb = api;
611 #ifdef HAVE_LCD_BITMAP
612 #if LCD_DEPTH > 1
613 xlcd_init(rb);
614 #elif defined(USE_GSLIB)
615 gbuf = (unsigned char *)rb->plugin_get_buffer(&gbuf_size);
616 if (!grey_init(rb, gbuf, gbuf_size, GREY_BUFFERED,
617 LCD_WIDTH, LCD_HEIGHT, NULL))
619 rb->splash(HZ, "Couldn't init greyscale display");
620 return PLUGIN_ERROR;
622 /* init lcd_ function pointers */
623 lcdfuncs.update = rb->lcd_update;
624 lcdfuncs.clear_display = rb->lcd_clear_display;
625 lcdfuncs.drawline = rb->lcd_drawline;
626 lcdfuncs.putsxy = rb->lcd_putsxy;
628 #ifdef MROBE_100
629 grey_set_background(GREY_BLACK);
630 #endif
632 grey_setfont(FONT_SYSFIXED);
633 #endif
634 rb->lcd_setfont(FONT_SYSFIXED);
635 #else /* LCD_CHARCELLS */
636 if (!pgfx_init(rb, 4, 2))
638 rb->splash(HZ*2, "Old LCD :(");
639 return PLUGIN_OK;
641 pgfx_display(3, 0);
642 #endif
644 while(!exit)
646 if (highspeed)
647 rb->yield();
648 else
649 rb->sleep(4);
651 if (redraw)
653 MYLCD(clear_display)();
654 cube_rotate(xa, ya, za);
655 cube_viewport();
656 cube_draw();
657 redraw = false;
660 #ifdef HAVE_LCD_BITMAP
661 if (t_disp > 0)
663 t_disp--;
664 rb->snprintf(buffer, sizeof(buffer), "x:%d y:%d z:%d h:%d",
665 xs, ys, zs, highspeed);
666 MYLCD(putsxy)(0, LCD_HEIGHT-8, buffer);
667 if (t_disp == 0)
668 redraw = true;
670 #else
671 if (t_disp > 0)
673 if (t_disp == DISP_TIME)
675 rb->snprintf(buffer, sizeof(buffer), "x%d", xs);
676 rb->lcd_puts(0, 0, buffer);
677 rb->snprintf(buffer, sizeof(buffer), "y%d", ys);
678 rb->lcd_puts(0, 1, buffer);
679 pgfx_display(3, 0);
680 rb->snprintf(buffer, sizeof(buffer), "z%d", zs);
681 rb->lcd_puts(8, 0, buffer);
682 rb->snprintf(buffer, sizeof(buffer), "h%d", highspeed);
683 rb->lcd_puts(8, 1, buffer);
685 t_disp--;
686 if (t_disp == 0)
688 rb->lcd_clear_display();
689 pgfx_display(3, 0);
692 #endif
693 #ifdef USE_GSLIB
694 if (mode_switch)
696 grey_show(mode == SOLID);
697 mode_switch = false;
699 #endif
700 MYLCD(update)();
702 if (!paused)
704 xa += xs;
705 if (xa > 359)
706 xa -= 360;
707 else if (xa < 0)
708 xa += 360;
710 ya += ys;
711 if (ya > 359)
712 ya -= 360;
713 else if (ya < 0)
714 ya += 360;
716 za += zs;
717 if (za > 359)
718 za -= 360;
719 else if (za < 0)
720 za += 360;
721 redraw = true;
724 button = rb->button_get(false);
725 switch (button)
727 case CUBE_X_INC:
728 case (CUBE_X_INC|BUTTON_REPEAT):
729 if( !paused )
731 if( xs < 10)
732 xs++;
734 else
736 xa++;
737 if( xa > 359 )
738 xa -= 360;
740 t_disp = DISP_TIME;
741 redraw = true;
742 break;
744 case CUBE_X_DEC:
745 case (CUBE_X_DEC|BUTTON_REPEAT):
746 if( !paused )
748 if (xs > -10)
749 xs--;
751 else
753 xa--;
754 if( xa < 0 )
755 xa += 360;
757 t_disp = DISP_TIME;
758 redraw = true;
759 break;
761 case CUBE_Y_INC:
762 case (CUBE_Y_INC|BUTTON_REPEAT):
763 if( !paused )
765 if (ys < 10)
766 ys++;
768 else
770 ya++;
771 if( ya > 359 )
772 ya -= 360;
774 t_disp = DISP_TIME;
775 redraw = true;
776 break;
778 case CUBE_Y_DEC:
779 case (CUBE_Y_DEC|BUTTON_REPEAT):
780 if( !paused )
782 if (ys > -10)
783 ys--;
785 else
787 ya--;
788 if( ya < 0 )
789 ya += 360;
791 t_disp = DISP_TIME;
792 redraw = true;
793 break;
795 case CUBE_Z_INC:
796 case (CUBE_Z_INC|BUTTON_REPEAT):
797 if( !paused )
799 if (zs < 10)
800 zs++;
802 else
804 za++;
805 if( za > 359 )
806 za -= 360;
808 t_disp = DISP_TIME;
809 redraw = true;
810 break;
812 case CUBE_Z_DEC:
813 case (CUBE_Z_DEC|BUTTON_REPEAT):
814 if( !paused )
816 if (zs > -10)
817 zs--;
819 else
821 za--;
822 if( za < 0 )
823 za += 360;
825 t_disp = DISP_TIME;
826 redraw = true;
827 break;
829 case CUBE_MODE:
830 #ifdef CUBE_MODE_PRE
831 if (lastbutton != CUBE_MODE_PRE)
832 break;
833 #endif
834 if (++mode >= NUM_MODES)
835 mode = 0;
836 #ifdef USE_GSLIB
837 mylcd = (mode == SOLID) ? &greyfuncs : &lcdfuncs;
838 mode_switch = true;
839 #endif
840 redraw = true;
841 break;
843 case CUBE_PAUSE:
844 #ifdef CUBE_PAUSE_PRE
845 if (lastbutton != CUBE_PAUSE_PRE)
846 break;
847 #endif
848 paused = !paused;
849 break;
851 case CUBE_HIGHSPEED:
852 #ifdef CUBE_HIGHSPEED_PRE
853 if (lastbutton != CUBE_HIGHSPEED_PRE)
854 break;
855 #endif
856 highspeed = !highspeed;
857 t_disp = DISP_TIME;
858 break;
860 #ifdef CUBE_RC_QUIT
861 case CUBE_RC_QUIT:
862 #endif
863 case CUBE_QUIT:
864 exit = true;
865 break;
867 default:
868 if (rb->default_event_handler_ex(button, cleanup, NULL)
869 == SYS_USB_CONNECTED)
870 return PLUGIN_USB_CONNECTED;
871 break;
873 if (button != BUTTON_NONE)
874 lastbutton = button;
877 #ifdef USE_GSLIB
878 grey_release();
879 #elif defined(HAVE_LCD_CHARCELLS)
880 pgfx_release();
881 #endif
882 return PLUGIN_OK;