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