/************************************************************************* * * Copyright (c) 2002-2003 MobileWizardry * All rights reservered. * *************************************************************************/ /* * @(#)application.c * * -- Aaron Ardiri (mailto:aaron_ardiri@mobilewizardry.com) */ #include "../../common/DAL.h" /************************************************************************* * * Fixed Integer Math * *************************************************************************/ // data types typedef int32 fixed; // 32 bit --> 24:8 precision #define precision 8 // (change this, need to change sine table) // fixed mathematical operations #define Addfx(a,b) (fixed)((fixed)(a) + (fixed)(b)) #define Mulfx(a,b) (fixed)(((fixed)(a) * (fixed)(b)) >> precision) #define Divfx(a,b) (fixed)(((fixed)(a) << precision) / (fixed)(b)) // fixed mathematical conversions #define itofx(x) ((fixed)(x) << precision) #define fxtoi(x) (((fixed)(x)) >> precision) /************************************************************************* * * Global Variables * *************************************************************************/ typedef struct PreferenceType { uint32 replace_me; } PreferenceType; typedef struct GlobalsType { PreferenceType prefs; coord scr_width; coord scr_height; struct { coord vertex[8][3]; int16 dx, dy, dz; } cube; } GlobalsType; //------------------------------------------------------------------------ // --== 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. //------------------------------------------------------------------------ #define globals ((GlobalsType *)(_SysGetGlobals())) /************************************************************************* * * Local Functions * *************************************************************************/ static void PtPerspectiveConversion(coord, coord, coord, coord *, coord *); static void PtRotationAboutX(coord, coord, coord, coord *, coord *, coord *, int16); static void PtRotationAboutY(coord, coord, coord, coord *, coord *, coord *, int16); static void PtRotationAboutZ(coord, coord, coord, coord *, coord *, coord *, int16); // // cosine/sine functions // static fixed sin_table(int16 index) { // we have to encapsulate this in a function -> no global data allowed. fixed table[] = { 0x00000000, 0x00000004, 0x00000008, 0x0000000d, 0x00000011, 0x00000016, 0x0000001a, 0x0000001f, 0x00000023, 0x00000028, 0x0000002c, 0x00000030, 0x00000035, 0x00000039, 0x0000003d, 0x00000042, 0x00000046, 0x0000004a, 0x0000004f, 0x00000053, 0x00000057, 0x0000005b, 0x0000005f, 0x00000064, 0x00000068, 0x0000006c, 0x00000070, 0x00000074, 0x00000078, 0x0000007c, 0x00000080, 0x00000083, 0x00000087, 0x0000008b, 0x0000008f, 0x00000092, 0x00000096, 0x0000009a, 0x0000009d, 0x000000a1, 0x000000a4, 0x000000a7, 0x000000ab, 0x000000ae, 0x000000b1, 0x000000b5, 0x000000b8, 0x000000bb, 0x000000be, 0x000000c1, 0x000000c4, 0x000000c6, 0x000000c9, 0x000000cc, 0x000000cf, 0x000000d1, 0x000000d4, 0x000000d6, 0x000000d9, 0x000000db, 0x000000dd, 0x000000df, 0x000000e2, 0x000000e4, 0x000000e6, 0x000000e8, 0x000000e9, 0x000000eb, 0x000000ed, 0x000000ee, 0x000000f0, 0x000000f2, 0x000000f3, 0x000000f4, 0x000000f6, 0x000000f7, 0x000000f8, 0x000000f9, 0x000000fa, 0x000000fb, 0x000000fc, 0x000000fc, 0x000000fd, 0x000000fe, 0x000000fe, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x00000100, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000fe, 0x000000fe, 0x000000fd, 0x000000fc, 0x000000fc, 0x000000fb, 0x000000fa, 0x000000f9, 0x000000f8, 0x000000f7, 0x000000f6, 0x000000f4, 0x000000f3, 0x000000f2, 0x000000f0, 0x000000ee, 0x000000ed, 0x000000eb, 0x000000e9, 0x000000e8, 0x000000e6, 0x000000e4, 0x000000e2, 0x000000df, 0x000000dd, 0x000000db, 0x000000d9, 0x000000d6, 0x000000d4, 0x000000d1, 0x000000cf, 0x000000cc, 0x000000c9, 0x000000c6, 0x000000c4, 0x000000c1, 0x000000be, 0x000000bb, 0x000000b8, 0x000000b5, 0x000000b1, 0x000000ae, 0x000000ab, 0x000000a7, 0x000000a4, 0x000000a1, 0x0000009d, 0x0000009a, 0x00000096, 0x00000092, 0x0000008f, 0x0000008b, 0x00000087, 0x00000083, 0x0000007f, 0x0000007c, 0x00000078, 0x00000074, 0x00000070, 0x0000006c, 0x00000068, 0x00000064, 0x0000005f, 0x0000005b, 0x00000057, 0x00000053, 0x0000004f, 0x0000004a, 0x00000046, 0x00000042, 0x0000003d, 0x00000039, 0x00000035, 0x00000030, 0x0000002c, 0x00000028, 0x00000023, 0x0000001f, 0x0000001a, 0x00000016, 0x00000011, 0x0000000d, 0x00000008, 0x00000004, 0x00000000, 0xfffffffc, 0xfffffff8, 0xfffffff3, 0xffffffef, 0xffffffea, 0xffffffe6, 0xffffffe1, 0xffffffdd, 0xffffffd8, 0xffffffd4, 0xffffffd0, 0xffffffcb, 0xffffffc7, 0xffffffc3, 0xffffffbe, 0xffffffba, 0xffffffb6, 0xffffffb1, 0xffffffad, 0xffffffa9, 0xffffffa5, 0xffffffa1, 0xffffff9c, 0xffffff98, 0xffffff94, 0xffffff90, 0xffffff8c, 0xffffff88, 0xffffff84, 0xffffff80, 0xffffff7d, 0xffffff79, 0xffffff75, 0xffffff71, 0xffffff6e, 0xffffff6a, 0xffffff66, 0xffffff63, 0xffffff5f, 0xffffff5c, 0xffffff59, 0xffffff55, 0xffffff52, 0xffffff4f, 0xffffff4b, 0xffffff48, 0xffffff45, 0xffffff42, 0xffffff3f, 0xffffff3c, 0xffffff3a, 0xffffff37, 0xffffff34, 0xffffff31, 0xffffff2f, 0xffffff2c, 0xffffff2a, 0xffffff27, 0xffffff25, 0xffffff23, 0xffffff21, 0xffffff1e, 0xffffff1c, 0xffffff1a, 0xffffff18, 0xffffff17, 0xffffff15, 0xffffff13, 0xffffff12, 0xffffff10, 0xffffff0e, 0xffffff0d, 0xffffff0c, 0xffffff0a, 0xffffff09, 0xffffff08, 0xffffff07, 0xffffff06, 0xffffff05, 0xffffff04, 0xffffff04, 0xffffff03, 0xffffff02, 0xffffff02, 0xffffff01, 0xffffff01, 0xffffff01, 0xffffff01, 0xffffff01, 0xffffff00, 0xffffff01, 0xffffff01, 0xffffff01, 0xffffff01, 0xffffff01, 0xffffff02, 0xffffff02, 0xffffff03, 0xffffff04, 0xffffff04, 0xffffff05, 0xffffff06, 0xffffff07, 0xffffff08, 0xffffff09, 0xffffff0a, 0xffffff0c, 0xffffff0d, 0xffffff0e, 0xffffff10, 0xffffff12, 0xffffff13, 0xffffff15, 0xffffff17, 0xffffff18, 0xffffff1a, 0xffffff1c, 0xffffff1e, 0xffffff21, 0xffffff23, 0xffffff25, 0xffffff27, 0xffffff2a, 0xffffff2c, 0xffffff2f, 0xffffff31, 0xffffff34, 0xffffff37, 0xffffff3a, 0xffffff3c, 0xffffff3f, 0xffffff42, 0xffffff45, 0xffffff48, 0xffffff4b, 0xffffff4f, 0xffffff52, 0xffffff55, 0xffffff59, 0xffffff5c, 0xffffff5f, 0xffffff63, 0xffffff66, 0xffffff6a, 0xffffff6e, 0xffffff71, 0xffffff75, 0xffffff79, 0xffffff7d, 0xffffff81, 0xffffff84, 0xffffff88, 0xffffff8c, 0xffffff90, 0xffffff94, 0xffffff98, 0xffffff9c, 0xffffffa1, 0xffffffa5, 0xffffffa9, 0xffffffad, 0xffffffb1, 0xffffffb6, 0xffffffba, 0xffffffbe, 0xffffffc3, 0xffffffc7, 0xffffffcb, 0xffffffd0, 0xffffffd4, 0xffffffd8, 0xffffffdd, 0xffffffe1, 0xffffffe6, 0xffffffea, 0xffffffef, 0xfffffff3, 0xfffffff8, 0xfffffffc, }; return (fixed)table[index]; } #define ABS(a) (((a) > 0) ? (a) : -(a)) static fixed cos_fx(int16 deg) { return sin_table((int16)ABS((deg+90)%360)); } static fixed sin_fx(int16 deg) { return sin_table((int16)ABS(deg%360)); } /************************************************************************* * * Public Functions * *************************************************************************/ uint32 ApplicationGetUniqueID() { return 0x43554245; // 0x43554245 = 'CUBE'; } uint8 * ApplicationGetName() { return (uint8 *)"Cube 3D\0"; } uint32 ApplicationGetVersion() { return 0; } void * ApplicationGetPreferences() { return &globals->prefs; } uint16 ApplicationGetPreferencesSize() { //return (uint16)sizeof(globals->prefs); // we have no preferences in this demonstration :) return 0; } boolean ApplicationInitialize() { // allocate and initialize globals GlobalsType *gbls = _MemPtrNew(sizeof(GlobalsType), false); _MemSet(gbls, sizeof(GlobalsType), 0); _SysSetGlobals(gbls); // get information about the display _GfxDisplayInfo(&globals->scr_width, &globals->scr_height); _GfxClearWindow(); // initialize a few things _SysRandom(_SysGetTime()); _SysSetFPS(300); // 30 fps (reasonable) #define size (globals->scr_width / 5) // setup our cube (hardcoded sizes here :P) globals->cube.vertex[0][0] = -size; globals->cube.vertex[0][1] = size; globals->cube.vertex[0][2] = -size; globals->cube.vertex[1][0] = -size; globals->cube.vertex[1][1] = size; globals->cube.vertex[1][2] = size; globals->cube.vertex[2][0] = size; globals->cube.vertex[2][1] = size; globals->cube.vertex[2][2] = size; globals->cube.vertex[3][0] = size; globals->cube.vertex[3][1] = size; globals->cube.vertex[3][2] = -size; globals->cube.vertex[4][0] = -size; globals->cube.vertex[4][1] = -size; globals->cube.vertex[4][2] = -size; globals->cube.vertex[5][0] = -size; globals->cube.vertex[5][1] = -size; globals->cube.vertex[5][2] = size; globals->cube.vertex[6][0] = size; globals->cube.vertex[6][1] = -size; globals->cube.vertex[6][2] = size; globals->cube.vertex[7][0] = size; globals->cube.vertex[7][1] = -size; globals->cube.vertex[7][2] = -size; // reset the "angle" parameters globals->cube.dx = globals->cube.dy = globals->cube.dz = 0; return true; } boolean ApplicationHandleEvent(event *e) { boolean processed = false; coord vertex[8][3]; coord points[8][2]; int i; switch (e->eType) { case _keyEvent: processed = true; break; case _penEvent: processed = true; break; case _nilEvent: // perform the "rotation" of the cube for (i=0; i<8; i++) { PtRotationAboutX(globals->cube.vertex[i][0], globals->cube.vertex[i][1], globals->cube.vertex[i][2], &vertex[i][0], &vertex[i][1], &vertex[i][2], globals->cube.dx); PtRotationAboutY(vertex[i][0], vertex[i][1], vertex[i][2], &vertex[i][0], &vertex[i][1], &vertex[i][2], globals->cube.dy); PtRotationAboutZ(vertex[i][0], vertex[i][1], vertex[i][2], &vertex[i][0], &vertex[i][1], &vertex[i][2], globals->cube.dz); } // adjust the rotation angles globals->cube.dx += 2; globals->cube.dy += 1; globals->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]); points[i][0] = points[i][0] + (globals->scr_width >> 1); points[i][1] = (globals->scr_height >> 1) - points[i][1]; } _GfxClearWindow(); // draw the "cube" _GfxDrawLine(points[0][0], points[0][1], points[1][0], points[1][1], 255); _GfxDrawLine(points[0][0], points[0][1], points[3][0], points[3][1], 255); _GfxDrawLine(points[0][0], points[0][1], points[4][0], points[4][1], 255); _GfxDrawLine(points[2][0], points[2][1], points[1][0], points[1][1], 255); _GfxDrawLine(points[2][0], points[2][1], points[3][0], points[3][1], 255); _GfxDrawLine(points[2][0], points[2][1], points[6][0], points[6][1], 255); _GfxDrawLine(points[5][0], points[5][1], points[1][0], points[1][1], 255); _GfxDrawLine(points[5][0], points[5][1], points[4][0], points[4][1], 255); _GfxDrawLine(points[5][0], points[5][1], points[6][0], points[6][1], 255); _GfxDrawLine(points[7][0], points[7][1], points[3][0], points[3][1], 255); _GfxDrawLine(points[7][0], points[7][1], points[4][0], points[4][1], 255); _GfxDrawLine(points[7][0], points[7][1], points[6][0], points[6][1], 255); // update the screen _GfxRepaint(); processed = true; break; default: break; } return processed; } void ApplicationTerminate() { _MemPtrFree(globals); } static void PtPerspectiveConversion(coord x, coord y, coord z, coord *newX, coord *newY) { fixed _x, _y, _z; // NB: 333 and 250 value combinations give a good depth of field :)) _x = itofx(x); _y = itofx(-y); _z = Addfx(itofx(-z), itofx(333)); *newX = (coord)fxtoi(Divfx(Mulfx(itofx(250), _x), _z)); *newY = (coord)fxtoi(Divfx(Mulfx(itofx(250), _y), _z)); } static void PtRotationAboutX(coord x, coord y, coord z, coord *newX, coord *newY, coord *newZ, int16 d) { *newX = x; *newY = (coord)fxtoi(Addfx(Mulfx( cos_fx(d),itofx(y)),Mulfx( sin_fx(d),itofx(z)))); *newZ = (coord)fxtoi(Addfx(Mulfx(-sin_fx(d),itofx(y)),Mulfx( cos_fx(d),itofx(z)))); } static void PtRotationAboutY(coord x, coord y, coord z, coord *newX, coord *newY, coord *newZ, int16 d) { *newX = (coord)fxtoi(Addfx(Mulfx( cos_fx(d),itofx(x)),Mulfx(-sin_fx(d),itofx(z)))); *newY = y; *newZ = (coord)fxtoi(Addfx(Mulfx( sin_fx(d),itofx(x)),Mulfx( cos_fx(d),itofx(z)))); } static void PtRotationAboutZ(coord x, coord y, coord z, coord *newX, coord *newY, coord *newZ, int16 d) { *newX = (coord)fxtoi(Addfx(Mulfx( cos_fx(d),itofx(x)),Mulfx( sin_fx(d),itofx(y)))); *newY = (coord)fxtoi(Addfx(Mulfx(-sin_fx(d),itofx(x)),Mulfx( cos_fx(d),itofx(y)))); *newZ = z; } /********************************* EOF ***********************************/