1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin/Revolution gx demo
3   File:     frb-bound-box.c
4 
5   Copyright 1998-2006 Nintendo.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12  *---------------------------------------------------------------------------*/
13 /*---------------------------------------------------------------------------*
14     frb-bound-box
15         bounding box feature demo
16  *---------------------------------------------------------------------------*/
17 
18 
19 /*---------------------------------------------------------------------------*
20    Header files
21  *---------------------------------------------------------------------------*/
22 #include <demo.h>
23 #include <math.h>
24 
25 /*---------------------------------------------------------------------------*
26    Macro definitions
27  *---------------------------------------------------------------------------*/
28 #define PI          3.14159265F
29 
30 #define MAX_Z       0x00ffffff // max value of Z buffer
31 
32 #define NUM_CUBES   8
33 #define BOUNDARY    400
34 
35 #define Clamp(val,min,max) \
36     ((val) = (((val) < (min)) ? (min) : ((val) > (max)) ? (max) : (val)))
37 
38 /*---------------------------------------------------------------------------*
39    Structure definitions
40  *---------------------------------------------------------------------------*/
41 // for camera
42 typedef struct
43 {
44     Vec    location;
45     Vec    up;
46     Vec    target;
47     f32    left;
48     f32    top;
49     f32    znear;
50     f32    zfar;
51 } CameraConfig;
52 
53 typedef struct
54 {
55     CameraConfig  cfg;
56     Mtx           view;
57     Mtx44         proj;
58 } MyCameraObj;
59 
60 // for cube objects
61 typedef struct
62 {
63     Vec         pos;
64     Vec         vel;
65     Vec         axis;
66     f32         deg;
67 } MyCubeObj;
68 
69 // bounding box
70 typedef u16 MyBoundingBox[4];
71 
72 // for entire scene control
73 typedef struct
74 {
75     MyCameraObj cam;
76     MyCubeObj   cube[NUM_CUBES];
77     u16         screen_width;
78     u16         screen_height;
79 } MySceneCtrlObj;
80 
81 /*---------------------------------------------------------------------------*
82    Forward references
83  *---------------------------------------------------------------------------*/
84 void        main                ( void );
85 static void DrawInit            ( MySceneCtrlObj* sc );
86 static void DrawTick            ( MySceneCtrlObj* sc );
87 static void AnimTick            ( MySceneCtrlObj* sc );
88 static void DrawCubes           ( MySceneCtrlObj* sc );
89 static void DrawBoundingBox     ( MyBoundingBox bb );
90 static void SetCamera           ( MyCameraObj* cam );
91 static void SetScreenSpaceMode  ( MySceneCtrlObj* sc );
92 static void SetLight            ( void );
93 static void DisableLight        ( void );
94 static void PrintIntro          ( void );
95 
96 /*---------------------------------------------------------------------------*
97   Model and texture data
98  *---------------------------------------------------------------------------*/
99 // for cube models
100 #define REG_AMBIENT  ColorArray[NUM_CUBES]
101 #define LIGHT_COLOR  ColorArray[NUM_CUBES+1]
102 #define BG_COLOR     ColorArray[NUM_CUBES+2]
103 
104 static GXColor ColorArray[NUM_CUBES+3] ATTRIBUTE_ALIGN(32) =
105 {
106     { 0x80, 0xFF, 0x80, 0xFF },
107     { 0x00, 0xFF, 0xFF, 0xFF },
108     { 0xFF, 0x00, 0xFF, 0xFF },
109     { 0xFF, 0xFF, 0x00, 0xFF },
110     { 0x20, 0x20, 0xFF, 0x80 },
111     { 0x20, 0xA0, 0x00, 0x80 },
112     { 0xC0, 0xC0, 0xC0, 0x40 },
113     { 0xFF, 0x80, 0x80, 0x40 },
114     { 0x40, 0x40, 0x40, 0xFF },    // Gray  (Ambient etc.)
115     { 0xFF, 0xFF, 0xFF, 0xFF },    // White (Light etc.)
116     { 0x00, 0x00, 0x00, 0x00 }     // Background
117 };
118 
119 static Vec CubeIniData[NUM_CUBES*3] =
120 {
121     // Position          Velocity                 Rotation axis
122     { -300, -150,  30 }, {  5.0F,  2.5F,  5.0F }, {  0.0F,  1.0F,  1.0F },
123     {  300, -150,  30 }, {  5.0F, -7.5F, -2.5F }, {  0.5F,  0.0F, -1.0F },
124     { -200,  250,   0 }, {  2.5F, -2.5F, -7.5F }, { -0.5F, -1.0F,  0.0F },
125     {  200,  250,   0 }, { -5.0F, -5.0F, -5.0F }, {  1.0F,  1.0F,  1.0F },
126     { -300,   50, -50 }, { 10.0F, -2.5F, -2.5F }, {  0.0F, -0.5F, -1.0F },
127     {  300,   50, -50 }, { -2.5F,  5.0F,  2.5F }, {  1.0F,  0.0F, -1.0F },
128     { -200,   50, -80 }, {  0.0F,  7.5F, -7.5F }, { -1.0F, -0.5F,  0.5F },
129     {  200,   50, -80 }, {  7.5F, -2.5F,  5.0F }, { -0.5F,  0.5F,  1.0F }
130 };
131 
132 /*---------------------------------------------------------------------------*
133    Camera configuration
134  *---------------------------------------------------------------------------*/
135 static CameraConfig DefaultCamera =
136 {
137     {   0.0F, 0.0F, 800.0F }, // location
138     {   0.0F, 1.0F, 0.0F }, // up
139     {   0.0F, 0.0F, 0.0F }, // target
140     -160.0F,  // left
141      120.0F,  // top
142      200.0F,  // near
143     2000.0F   // far
144 };
145 
146 /*---------------------------------------------------------------------------*
147    Global variables
148  *---------------------------------------------------------------------------*/
149 static MySceneCtrlObj   SceneCtrl;                // scene control parameters
150 
151 /*---------------------------------------------------------------------------*
152    Application main loop
153  *---------------------------------------------------------------------------*/
main(void)154 void main ( void )
155 {
156     DEMOInit(NULL);       // Init the OS, game pad, graphics and video.
157 
158     DrawInit(&SceneCtrl); // Initialize vertex formats, array pointers
159                           // and default scene settings.
160 
161     PrintIntro();    // Print demo directions
162 
163     while(!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
164     {
165 		DEMOBeforeRender();
166         DrawTick(&SceneCtrl);    // Draw the model.
167         DEMODoneRender();
168         DEMOPadRead();           // Read controller
169         AnimTick(&SceneCtrl);    // Do animation
170     }
171 
172     OSHalt("End of test");
173 }
174 
175 /*---------------------------------------------------------------------------*
176    Functions
177  *---------------------------------------------------------------------------*/
178 /*---------------------------------------------------------------------------*
179     Name:           DrawInit
180 
181     Description:    Initializes the vertex attribute format and sets up
182                     the array pointer for the indexed data.
183                     This function also initializes scene control parameters.
184 
185     Arguments:      sc : pointer to the structure of scene control parameters
186 
187     Returns:        none
188  *---------------------------------------------------------------------------*/
DrawInit(MySceneCtrlObj * sc)189 static void DrawInit( MySceneCtrlObj* sc )
190 {
191     GXRenderModeObj *rmp;
192     u32             i;
193 
194     // Get framebuffer size of current rendering mode
195     rmp = DEMOGetRenderModeObj();
196     sc->screen_width  = rmp->fbWidth;
197     sc->screen_height = rmp->efbHeight;
198 
199     //  Vertex Attribute
200     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 0);
201     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S16, 8);
202     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
203 
204     //  Array Pointers and Strides
205     GXSetArray(GX_VA_CLR0, ColorArray, 4 * sizeof(u8));
206 
207     // Background color
208     GXSetCopyClear(BG_COLOR, MAX_Z);
209 
210     // Z compare
211     GXSetZCompLoc(GX_FALSE); // Z after texturing
212     // NOTE: You should use Z after texturing to avoid
213     //       the bounding box feature bug.
214 
215 
216     // Default scene control parameter settings
217 
218     // camera
219     sc->cam.cfg   = DefaultCamera;
220 
221     // cube objects
222     for ( i = 0 ; i < NUM_CUBES ; ++i )
223     {
224         sc->cube[i].pos  = CubeIniData[i*3];
225         sc->cube[i].vel  = CubeIniData[i*3+1];
226         sc->cube[i].axis = CubeIniData[i*3+2];
227         sc->cube[i].deg  = 0.0F;
228     }
229 }
230 
231 /*---------------------------------------------------------------------------*
232     Name:           DrawTick
233 
234     Description:    Draw the model by using given scene parameters
235 
236     Arguments:      sc : pointer to the structure of scene control parameters
237 
238     Returns:        none
239  *---------------------------------------------------------------------------*/
DrawTick(MySceneCtrlObj * sc)240 static void DrawTick( MySceneCtrlObj* sc )
241 {
242     static u16      token = 0;
243     MyBoundingBox   bbox;
244 
245     // Clear bounding box on HW
246     GXClearBoundingBox();
247 
248     // Set up camera
249     SetCamera(&sc->cam);
250 
251     // Draw cube models
252     DrawCubes(sc);
253 
254     // Make sure every cube is drawn
255     GXSetDrawSync(++token);
256     while ( GXReadDrawSync() != token )
257     {}
258 
259     // Get bounding box from HW
260     GXReadBoundingBox(&bbox[0], &bbox[1], &bbox[2], &bbox[3]);
261 
262     // Draw the bounding box obtained
263     SetScreenSpaceMode(sc);
264     DrawBoundingBox(bbox);
265 }
266 
267 /*---------------------------------------------------------------------------*
268     Name:           AnimTick
269 
270     Description:    Changes scene parameters according to the pad status.
271 
272     Arguments:      sc : pointer to the structure of scene control parameters
273 
274     Returns:        none
275  *---------------------------------------------------------------------------*/
276 #define VelReflect(cmp) \
277     if ( sc->cube[i].pos.cmp < - BOUNDARY )                 \
278         sc->cube[i].vel.cmp = fabsf(sc->cube[i].vel.cmp);   \
279     if ( sc->cube[i].pos.cmp > BOUNDARY )                   \
280         sc->cube[i].vel.cmp = - fabsf(sc->cube[i].vel.cmp);
281 
AnimTick(MySceneCtrlObj * sc)282 static void AnimTick( MySceneCtrlObj* sc )
283 {
284     u32  i;
285 
286     // Animate cubes
287     if ( !(DEMOPadGetButton(0) & PAD_BUTTON_A) )
288     {
289         for ( i = 0 ; i < NUM_CUBES ; ++i )
290         {
291             // rotation
292             sc->cube[i].deg += 5;
293             if ( sc->cube[i].deg > 360 )
294             {
295                 sc->cube[i].deg -= 360;
296             }
297 
298             // position
299             VECAdd(&sc->cube[i].pos, &sc->cube[i].vel, &sc->cube[i].pos);
300 
301             // velocity
302             VelReflect(x);
303             VelReflect(y);
304             VelReflect(z);
305         }
306     }
307 }
308 
309 /*---------------------------------------------------------------------------*
310     Name:           DrawCubes
311 
312     Description:    Draw cube models
313 
314     Arguments:      sc : pointer to the structure of scene control parameters
315 
316     Returns:        none
317  *---------------------------------------------------------------------------*/
DrawCubes(MySceneCtrlObj * sc)318 static void DrawCubes( MySceneCtrlObj* sc )
319 {
320     u32     i;
321     Mtx     mt, mr, ms, mv, mvi;
322 
323     // enable lighting
324     SetLight();
325 
326     // set Tev operation to use vertex color
327     GXSetNumTexGens(0);
328 	GXSetNumChans(1);
329 	GXSetNumTevStages(1);
330     GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
331     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
332 
333     for ( i = 0 ; i < NUM_CUBES ; ++i )
334     {
335         MTXTrans(mt, sc->cube[i].pos.x, sc->cube[i].pos.y, sc->cube[i].pos.z);
336         MTXConcat(sc->cam.view, mt, mv);
337         MTXScale(ms, 100.0F, 100.0F, 100.0F);
338         MTXConcat(mv, ms, mv);
339         MTXRotAxisDeg(mr, &sc->cube[i].axis, sc->cube[i].deg);
340         MTXConcat(mv, mr, mv);
341         GXLoadPosMtxImm(mv, GX_PNMTX0);
342         MTXInverse(mv, mvi);
343         MTXTranspose(mvi, mv);
344         GXLoadNrmMtxImm(mv, GX_PNMTX0);
345 
346         GXSetChanMatColor(GX_COLOR0A0, ColorArray[i]);
347 
348         GXDrawCube();
349     }
350 }
351 
352 /*---------------------------------------------------------------------------*
353     Name:           DrawBoundingBox
354 
355     Description:    Draw the bounding box obtained by the API
356 
357     Arguments:      bb : a bounding box object which contains
358                     (left, top, right, bottom) positions
359 
360     Returns:        none
361  *---------------------------------------------------------------------------*/
DrawBoundingBox(MyBoundingBox bb)362 static void DrawBoundingBox( MyBoundingBox bb )
363 {
364     s16  x0, x1, y0, y1;
365 
366     // set TEV operation
367     GXSetNumTexGens(0);
368 	GXSetNumChans(1);
369 	GXSetNumTevStages(1);
370     GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
371     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
372 
373     // disable light
374     DisableLight();
375 
376     // set vertex descriptor
377     GXClearVtxDesc();
378     GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
379     GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
380 
381     x0 = (s16)bb[0];
382     y0 = (s16)bb[1];
383     x1 = (s16)bb[2];
384     y1 = (s16)bb[3];
385 
386     // draw the box
387     GXBegin(GX_LINESTRIP, GX_VTXFMT0, 5);
388         GXPosition3s16(x0, y0, 0);
389         GXColor4u8(255, 255, 255, 255);
390         GXPosition3s16(x1, y0, 0);
391         GXColor4u8(255, 255, 255, 255);
392         GXPosition3s16(x1, y1, 0);
393         GXColor4u8(255, 255, 255, 255);
394         GXPosition3s16(x0, y1, 0);
395         GXColor4u8(255, 255, 255, 255);
396         GXPosition3s16(x0, y0, 0);
397         GXColor4u8(255, 255, 255, 255);
398     GXEnd();
399 }
400 
401 /*---------------------------------------------------------------------------*
402     Name:           SetCamera
403 
404     Description:    set view matrix and load projection matrix into hardware
405 
406     Arguments:      cam : pointer to the MyCameraObj structure
407 
408     Returns:        none
409  *---------------------------------------------------------------------------*/
SetCamera(MyCameraObj * cam)410 static void SetCamera( MyCameraObj* cam )
411 {
412     MTXLookAt(
413         cam->view,
414         &cam->cfg.location,
415         &cam->cfg.up,
416         &cam->cfg.target );
417 
418     MTXFrustum(
419         cam->proj,
420         cam->cfg.top,
421         - (cam->cfg.top),
422         cam->cfg.left,
423         - (cam->cfg.left),
424         cam->cfg.znear,
425         cam->cfg.zfar );
426     GXSetProjection(cam->proj, GX_PERSPECTIVE);
427 }
428 
429 /*---------------------------------------------------------------------------*
430     Name:           SetScreenSpaceMode
431 
432     Description:    set projection matrix up to screen coordinate system
433 
434     Arguments:      none
435 
436     Returns:        none
437  *---------------------------------------------------------------------------*/
SetScreenSpaceMode(MySceneCtrlObj * sc)438 static void SetScreenSpaceMode( MySceneCtrlObj* sc )
439 {
440     Mtx44  proj;
441     Mtx    mv;
442 
443     MTXOrtho( proj, 0.0F, sc->screen_height - 1, 0.0f, sc->screen_width - 1, 0.0f, - MAX_Z );
444     GXSetProjection( proj, GX_ORTHOGRAPHIC );
445     MTXIdentity(mv);
446     GXLoadPosMtxImm(mv, GX_PNMTX0);
447 }
448 
449 /*---------------------------------------------------------------------------*
450     Name:           SetLight
451 
452     Description:    Sets light objects and color channels
453 
454     Arguments:      le   : pointer to a MyLightEnvObj structure
455                     view : view matrix.
456 
457     Returns:        none
458  *---------------------------------------------------------------------------*/
SetLight(void)459 static void SetLight( void )
460 {
461     GXLightObj  lobj;
462 
463     // set up light position and color
464     GXInitLightPos(&lobj, 0.0F, 0.0F, 10000.0F); // almost parallel
465     GXInitLightColor(&lobj, LIGHT_COLOR);
466     GXLoadLightObjImm(&lobj, GX_LIGHT0);
467 
468     // channel setting
469     GXSetChanCtrl(
470         GX_COLOR0A0,
471         GX_ENABLE,        // enable channel
472         GX_SRC_REG,       // amb source
473         GX_SRC_REG,       // mat source
474         GX_LIGHT0,        // light mask
475         GX_DF_CLAMP,      // diffuse function
476         GX_AF_NONE);      // attenuation function
477     // channel ambient
478     GXSetChanAmbColor(GX_COLOR0A0, REG_AMBIENT);
479 }
480 
481 /*---------------------------------------------------------------------------*
482     Name:           DisableLight
483 
484     Description:    Disables lighting
485 
486     Arguments:      none
487 
488     Returns:        none
489  *---------------------------------------------------------------------------*/
DisableLight(void)490 static void DisableLight( void )
491 {
492     GXSetChanCtrl(
493         GX_COLOR0A0,
494         GX_DISABLE,    // disable channel
495         GX_SRC_REG,    // amb source
496         GX_SRC_VTX,    // mat source
497         GX_LIGHT_NULL, // light mask
498         GX_DF_NONE,    // diffuse function
499         GX_AF_NONE);
500 }
501 
502 /*---------------------------------------------------------------------------*
503     Name:           PrintIntro
504 
505     Description:    Prints the directions on how to use this demo.
506 
507     Arguments:      none
508 
509     Returns:        none
510  *---------------------------------------------------------------------------*/
PrintIntro(void)511 static void PrintIntro( void )
512 {
513     OSReport("\n\n");
514     OSReport("************************************************\n");
515     OSReport("frb-bound-box: bounding box feature demo\n");
516     OSReport("************************************************\n");
517     OSReport("to quit hit the start button\n");
518     OSReport("\n");
519     OSReport("A Button : Pause animation while pressed\n");
520     OSReport("************************************************\n\n");
521 }
522 
523 /*============================================================================*/
524