/************************************************************************* * * Copyright 2008+ Mobile 1UP * All rights reserved. * *************************************************************************/ /* * @(#)application-state-cube.inc */ /************************************************************************* * Structures *************************************************************************/ typedef struct CubeRunTime { struct { int16 vertex[8][3]; int16 dx, dy, dz; } cube; } CubeRunTime; typedef struct CubeExtension { CubeRunTime *rt; } CubeExtension; /************************************************************************* * Globals + Preferences *************************************************************************/ #define GLOBALS_CUBE_DEFINE GLOBALS_ACCESS; \ CubeExtension *g_cube #define GLOBALS_CUBE_ACCESS GLOBALS_ACCESS; \ CubeExtension *g_cube = globals -> pExt[STATE_CUBE] //------------------------------------------------------------------------ // --== GLOBALS ARE FORBIDDEN! ==-- // // DAL may support the use of globals on some platforms, however, its not // guaranteed that all the destination platforms allow the use of globals // (variable or static data). use the GlobalsType structure as shown. //------------------------------------------------------------------------ /************************************************************************* * Platform Independent Implementation *************************************************************************/ void PtPerspectiveConversion(int16, int16, int16, int16 *, int16 *); void PtRotationAboutX(int16, int16, int16, int16 *, int16 *, int16 *, int16); void PtRotationAboutY(int16, int16, int16, int16 *, int16 *, int16 *, int16); void PtRotationAboutZ(int16, int16, int16, int16 *, int16 *, int16 *, int16); boolean ApplicationStateCubeInitialize() { boolean result; GLOBALS_CUBE_DEFINE; // default return value result = false; // entry requirements if (globals == NULL) goto ApplicationStateCubeInitialize_DONE; g_cube = (CubeExtension *)_MemPtrNew(sizeof(CubeExtension), false); if (g_cube != NULL) { globals -> pExt[STATE_CUBE] = (void *)g_cube; result = true; } ApplicationStateCubeInitialize_DONE:; return result; } boolean ApplicationStateCubeInit() { boolean result; uint16 w, h, size; GLOBALS_CUBE_ACCESS; // default return value result = false; // entry requirements if (g_cube == NULL) goto ApplicationStateCubeInit_DONE; // allocate the runtime g_cube -> rt = _MemPtrNew(sizeof(CubeRunTime), false); if (g_cube -> rt == NULL) goto ApplicationStateCubeInit_DONE; // get information on the display _FBGetProperties(NULL, &w, &h, NULL); // configure the cube size = w / 7; g_cube -> rt -> cube.vertex[0][0] = -size; g_cube -> rt -> cube.vertex[0][1] = size; g_cube -> rt -> cube.vertex[0][2] = -size; g_cube -> rt -> cube.vertex[1][0] = -size; g_cube -> rt -> cube.vertex[1][1] = size; g_cube -> rt -> cube.vertex[1][2] = size; g_cube -> rt -> cube.vertex[2][0] = size; g_cube -> rt -> cube.vertex[2][1] = size; g_cube -> rt -> cube.vertex[2][2] = size; g_cube -> rt -> cube.vertex[3][0] = size; g_cube -> rt -> cube.vertex[3][1] = size; g_cube -> rt -> cube.vertex[3][2] = -size; g_cube -> rt -> cube.vertex[4][0] = -size; g_cube -> rt -> cube.vertex[4][1] = -size; g_cube -> rt -> cube.vertex[4][2] = -size; g_cube -> rt -> cube.vertex[5][0] = -size; g_cube -> rt -> cube.vertex[5][1] = -size; g_cube -> rt -> cube.vertex[5][2] = size; g_cube -> rt -> cube.vertex[6][0] = size; g_cube -> rt -> cube.vertex[6][1] = -size; g_cube -> rt -> cube.vertex[6][2] = size; g_cube -> rt -> cube.vertex[7][0] = size; g_cube -> rt -> cube.vertex[7][1] = -size; g_cube -> rt -> cube.vertex[7][2] = -size; // reset the "angle" parameters g_cube -> rt -> cube.dx = g_cube -> rt -> cube.dy = g_cube -> rt -> cube.dz = 0; // configuration successful result = true; ApplicationStateCubeInit_DONE:; return result; } boolean ApplicationStateCubeHandleEvent(event *e) { boolean result; uint16 *bits, w, h, rb; uint16 *dst; int i; int16 vertex[8][3]; int16 points[8][2]; GLOBALS_CUBE_ACCESS; // default return value result = false; // entry requirements if ((g_cube == NULL) || (g_cube -> rt == NULL)) goto ApplicationStateCubeHandleEvent_DONE; switch (e -> eType) { case _nilEvent: // get a pointer to the display _FBGetProperties((void **)&bits, &w, &h, &rb); // perform the rotation for (i=0; i<8; i++) { PtRotationAboutX(g_cube -> rt -> cube.vertex[i][0], g_cube -> rt -> cube.vertex[i][1], g_cube -> rt -> cube.vertex[i][2], &vertex[i][0], &vertex[i][1], &vertex[i][2], g_cube -> rt -> cube.dx); PtRotationAboutY( vertex[i][0], vertex[i][1], vertex[i][2], &vertex[i][0], &vertex[i][1], &vertex[i][2], g_cube -> rt -> cube.dy); PtRotationAboutZ( vertex[i][0], vertex[i][1], vertex[i][2], &vertex[i][0], &vertex[i][1], &vertex[i][2], g_cube -> rt -> cube.dz); } // adjust the rotation angles g_cube -> rt -> cube.dx += 2; g_cube -> rt -> cube.dy += 1; g_cube -> rt -> cube.dz += 3; // convert the cube from 3D to 2D using perspective geometry for (i=0; i<8; i++) { PtPerspectiveConversion(vertex[i][0], vertex[i][1], vertex[i][2], &points[i][0], &points[i][1]); // center on the display points[i][0] = points[i][0] + (w >> 1); points[i][1] = (h >> 1) - points[i][1]; } // clear the canvas dst = bits; for (i=0; i> 1); } // draw the "cube" _drawline(points[0][0], points[0][1], points[1][0], points[1][1], 0); _drawline(points[0][0], points[0][1], points[3][0], points[3][1], 0); _drawline(points[0][0], points[0][1], points[4][0], points[4][1], 0); _drawline(points[2][0], points[2][1], points[1][0], points[1][1], 0); _drawline(points[2][0], points[2][1], points[3][0], points[3][1], 0); _drawline(points[2][0], points[2][1], points[6][0], points[6][1], 0); _drawline(points[5][0], points[5][1], points[1][0], points[1][1], 0); _drawline(points[5][0], points[5][1], points[4][0], points[4][1], 0); _drawline(points[5][0], points[5][1], points[6][0], points[6][1], 0); _drawline(points[7][0], points[7][1], points[3][0], points[3][1], 0); _drawline(points[7][0], points[7][1], points[4][0], points[4][1], 0); _drawline(points[7][0], points[7][1], points[6][0], points[6][1], 0); // the screen must be repainted globals -> dirty = true; result = true; break; default: break; } ApplicationStateCubeHandleEvent_DONE:; return result; } void ApplicationStateCubeQuit() { GLOBALS_CUBE_ACCESS; // entry requirements if (g_cube == NULL) goto ApplicationStateCubeQuit_DONE; if (g_cube -> rt != NULL) _MemPtrFree(g_cube -> rt); g_cube -> rt = NULL; ApplicationStateCubeQuit_DONE:; } void ApplicationStateCubeTerminate() { GLOBALS_CUBE_ACCESS; // entry requirements if (globals == NULL) goto ApplicationStateCubeTerminate_DONE; if (g_cube != NULL) _MemPtrFree(g_cube); globals -> pExt[STATE_CUBE] = (void *)NULL; ApplicationStateCubeTerminate_DONE:; } void PtPerspectiveConversion(int16 x, int16 y, int16 z, int16 *newX, int16 *newY) { fixed _x, _y, _z; // NB: 333 and 250 value combinations give a good depth of field :)) _x = itofx(x); _y = itofx(-y); _z = add_f(itofx(-z), itofx(333)); *newX = (int16)fxtoi(div_f(mul_f(itofx(250), _x), _z)); *newY = (int16)fxtoi(div_f(mul_f(itofx(250), _y), _z)); } void PtRotationAboutX(int16 x, int16 y, int16 z, int16 *newX, int16 *newY, int16 *newZ, int16 d) { *newX = x; *newY = (int16)fxtoi(add_f(mul_f( _cos(d),itofx(y)),mul_f(_sin(d),itofx(z)))); *newZ = (int16)fxtoi(add_f(mul_f(-_sin(d),itofx(y)),mul_f(_cos(d),itofx(z)))); } void PtRotationAboutY(int16 x, int16 y, int16 z, int16 *newX, int16 *newY, int16 *newZ, int16 d) { *newX = (int16)fxtoi(add_f(mul_f(_cos(d),itofx(x)),mul_f(-_sin(d),itofx(z)))); *newY = y; *newZ = (int16)fxtoi(add_f(mul_f(_sin(d),itofx(x)),mul_f( _cos(d),itofx(z)))); } void PtRotationAboutZ(int16 x, int16 y, int16 z, int16 *newX, int16 *newY, int16 *newZ, int16 d) { *newX = (int16)fxtoi(add_f(mul_f( _cos(d),itofx(x)),mul_f(_sin(d),itofx(y)))); *newY = (int16)fxtoi(add_f(mul_f(-_sin(d),itofx(x)),mul_f(_cos(d),itofx(y)))); *newZ = z; } #undef GLOBALS_CUBE_DEFINE #undef GLOBALS_CUBE_ACCESS /********************************* EOF ***********************************/