1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin/Revolution gx demo
3   File:     DL-tf-mtx.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     DL-tf-mtx
15         Display list which includes matrix load commands
16  *---------------------------------------------------------------------------*/
17 #include <demo.h>
18 #include <math.h>
19 
20 /*---------------------------------------------------------------------------*
21    Macro definitions
22  *---------------------------------------------------------------------------*/
23 #define ASPECT              ((float)640/(float)448)
24 
25 #define NUM_MTX_SLOTS       10
26 #define MTX_IDX_SPAN        3
27 
28 #define DL_BUFSIZE          16384
29 
30 #define NUM_CONTOUR         100     // (9*11+1) : should be (9n+1)
31 #define CONTOUR_SPAN        50.0F
32 #define VTX_PER_CONTOUR     12
33 
34 
35 /*---------------------------------------------------------------------------*
36    Rendering parameters
37  *---------------------------------------------------------------------------*/
38 typedef f32 Mtx33[3][3];
39 typedef f32 Mtx24[2][4];
40 
41 typedef struct
42 {
43     Point3d   position;
44     Point3d   target;
45     Vec       up;
46     f32       fovy;
47     f32       znear;
48     f32       zfar;
49     Mtx       viewMtx;
50 } MyCameraObj;
51 
52 typedef struct
53 {
54    s8  x,  y;
55    s8  nx, ny, nz;
56    s8  pad;
57 } MyVertex;
58 
59 
60 /*---------------------------------------------------------------------------*
61    Forward references
62  *---------------------------------------------------------------------------*/
63 static void     DrawInit        ( void );
64 static void     DrawTick        ( void );
65 static void     AnimTick        ( void );
66 static void     BuildModelDL    ( void );
67 static void     BuildMtxArray   ( void );
68 static void     CheckMissingObj ( void );
69 inline void     CopyMtxTo3x3    ( Mtx src, Mtx33 dst );
70 
71 //---------------------------------------------------------------------------
72 //  Global variables
73 //---------------------------------------------------------------------------
74 // Camera
75 MyCameraObj DefaultCamera =
76 {
77     { 0.0f, -5000.0f, 0.0f },   // position
78     { 0.0f,     0.0f, 0.0f },   // target
79     { 0.0f,     0.0f, 1.0f },   // upVec
80        33.3f,                   // fovy
81      2000.0f,                   // near plane Z in camera coordinates
82     10000.0f,                   // far  plane Z in camera coordinates
83 };
84 
85 // For texture palette
86 static TPLPalettePtr   MyTplObj = 0;
87 
88 // For model display list
89 static void*    ModelDLBuffer = NULL;
90 static u32      ModelDLSize = 0;
91 // For model transform matrix array (double buffered)
92 static Mtx*     PosMtxArrayBuf[2];
93 static Mtx33*   NrmMtxArrayBuf[2];
94 static Mtx24*   TexMtxArrayBuf[2];
95 static u32      CurrentMtxBuffer;
96 
97 // For animation control
98 static Vec      AnimCtrlArray[NUM_CONTOUR];
99 static u32      AnimCtrlPtr = 0;
100 static s32      AnimCounter = 0;
101 static u32      AnimReset   = 0;
102 static u32      AnimPause   = 0;
103 static Mtx      AnimMtxOrigin;
104 static Mtx      AnimGlobalRot;
105 
106 //---------------------------------------------------------------------------
107 //  Model data
108 //---------------------------------------------------------------------------
109 static MyVertex VtxArray[VTX_PER_CONTOUR] ATTRIBUTE_ALIGN(32) =
110 {
111     {  50,   0,    64,   0,  0 }, /*   0 */
112     {  44,  25,    55,  32,  0 }, /*  30 */
113     {  25,  44,    32,  55,  0 }, /*  60 */
114     {   0,  50,     0,  64,  0 }, /*  90 */
115     { -25,  44,   -32,  55,  0 }, /* 120 */
116     { -44,  25,   -55,  32,  0 }, /* 150 */
117     { -50,   0,   -64,   0,  0 }, /* 180 */
118     { -44, -25,   -55, -32,  0 }, /* 210 */
119     { -25, -44,   -32, -55,  0 }, /* 240 */
120     {   0, -50,     0, -64,  0 }, /* 270 */
121     {  25, -44,    32, -55,  0 }, /* 300 */
122     {  44, -25,    55, -32,  0 }, /* 330 */
123 };
124 
125 /*---------------------------------------------------------------------------*
126    Application main loop
127  *---------------------------------------------------------------------------*/
main(void)128 void  main ( void )
129 {
130     // initialize render settings and set clear color for first frame
131     DEMOInit(NULL);
132     DrawInit();
133 
134     while ( ! ( DEMOPadGetButton(0) & PAD_BUTTON_MENU ) )
135     {
136         DEMOBeforeRender();
137 
138         // Draw scene
139         DrawTick();
140 
141         // get pad status
142         DEMOPadRead();
143         // Control and Animation
144         AnimTick();
145 
146         CheckMissingObj();
147         DEMODoneRender();
148     }
149 
150     OSHalt("End of test");
151 }
152 
153 /*---------------------------------------------------------------------------*
154     Name:           DrawInit
155 
156     Description:    Initializes parameters and default graphics status.
157 
158     Arguments:      none
159 
160     Returns:        none
161  *---------------------------------------------------------------------------*/
DrawInit(void)162 void  DrawInit( void )
163 {
164     u32  i;
165 
166     // Reflection map texture
167     TPLGetPalette(&MyTplObj, "gxTests/tf-02.tpl");
168 
169     // Set background color
170     GXSetCopyClear((GXColor){ 64, 64, 64, 64}, GX_MAX_Z24);
171 
172     // Set pixel processing mode
173     GXSetBlendMode(GX_BM_NONE, GX_BL_ONE, GX_BL_ZERO, GX_LO_CLEAR);
174     GXSetZMode(GX_TRUE, GX_LESS, GX_TRUE);
175 
176     GXSetZCompLoc(GX_FALSE); // Z after texturing
177     // NOTE: You should use Z after texturing to avoid
178     //       the bounding box bug in the easiest way.
179 
180     // Set culling mode
181     GXSetCullMode(GX_CULL_BACK);
182 
183     // Allocate matrix array buffers (double-buffer)
184     PosMtxArrayBuf[0] = (Mtx*)  MEMAllocFromAllocator(&DemoAllocator1, sizeof(Mtx)   * NUM_CONTOUR);
185     PosMtxArrayBuf[1] = (Mtx*)  MEMAllocFromAllocator(&DemoAllocator1, sizeof(Mtx)   * NUM_CONTOUR);
186     NrmMtxArrayBuf[0] = (Mtx33*)MEMAllocFromAllocator(&DemoAllocator1, sizeof(Mtx33) * NUM_CONTOUR);
187     NrmMtxArrayBuf[1] = (Mtx33*)MEMAllocFromAllocator(&DemoAllocator1, sizeof(Mtx33) * NUM_CONTOUR);
188     TexMtxArrayBuf[0] = (Mtx24*)MEMAllocFromAllocator(&DemoAllocator1, sizeof(Mtx24) * NUM_CONTOUR);
189     TexMtxArrayBuf[1] = (Mtx24*)MEMAllocFromAllocator(&DemoAllocator1, sizeof(Mtx24) * NUM_CONTOUR);
190     CurrentMtxBuffer  = 0;
191 
192     // Animation setting
193     AnimReset   = 0;
194     AnimPause   = 0;
195     AnimCtrlPtr = 0;
196     AnimCounter = 0;
197     for ( i = 0; i < NUM_CONTOUR; i++ )
198     {
199         AnimCtrlArray[i] = (Vec){ 5.0F, 0.5F, 0.0F };
200     }
201     // Initial location of the object
202     MTXTrans(AnimMtxOrigin, -800.0F, 0.0F, -400.0F);
203     MTXIdentity(AnimGlobalRot);
204 
205     // Build matrix array for the first frame
206     // (for safety, initialize both of double-buffer)
207     BuildMtxArray();
208     BuildMtxArray();
209 
210     // Build a model display list
211     BuildModelDL();
212 
213     return;
214 }
215 
216 /*---------------------------------------------------------------------------*
217     Name:           DrawTick
218 
219     Description:    Draw the model
220 
221     Arguments:      none
222 
223     Returns:        none
224  *---------------------------------------------------------------------------*/
DrawTick(void)225 void  DrawTick( void )
226 {
227     Mtx*            posMtxArray = PosMtxArrayBuf[CurrentMtxBuffer];
228     Mtx33*          nrmMtxArray = NrmMtxArrayBuf[CurrentMtxBuffer];
229     Mtx24*          texMtxArray = TexMtxArrayBuf[CurrentMtxBuffer];
230     Mtx44           projMtx;
231     MyCameraObj*    c = &DefaultCamera;
232     GXTexObj        texObj;
233     GXLightObj      litObj;
234     Vec             lpos = { 10000.0F, -10000.0F, 10000.0F };
235 
236     // Set projection matrix
237     MTXPerspective(projMtx, c->fovy, ASPECT, c->znear, c->zfar);
238     GXSetProjection(projMtx, GX_PERSPECTIVE);
239 
240     // Lighting
241     GXSetNumChans(1);
242     GXSetChanCtrl(GX_COLOR0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG,
243                   GX_LIGHT0, GX_DF_CLAMP, GX_AF_NONE);
244     GXSetChanCtrl(GX_ALPHA0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG,
245                   GX_LIGHT_NULL, GX_DF_CLAMP, GX_AF_NONE);
246 
247     GXSetChanAmbColor(GX_COLOR0A0, (GXColor){ 48,  48,  48,  48 });
248     GXSetChanMatColor(GX_COLOR0A0, (GXColor){ 255, 255, 192, 255 });
249 
250     MTXMultVec(c->viewMtx, &lpos, &lpos);
251     GXInitLightPosv(&litObj, &lpos);
252     GXInitLightColor(&litObj, (GXColor){ 208, 208, 208, 208 });
253     GXLoadLightObjImm(&litObj, GX_LIGHT0);
254 
255     // TEV
256     GXSetNumTevStages(1);
257     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
258     GXSetTevOp(GX_TEVSTAGE0, GX_MODULATE);
259     // Texture
260     TPLGetGXTexObjFromPalette(MyTplObj, &texObj, 1);
261     GXLoadTexObj(&texObj, GX_TEXMAP0);
262     // Texture coord gen
263     GXSetNumTexGens(1);
264     GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_NRM, GX_TEXMTX0);
265 
266     // Array base & stride setting
267     GXSetArray(GX_POS_MTX_ARRAY, posMtxArray,     sizeof(posMtxArray[0]));
268     GXSetArray(GX_NRM_MTX_ARRAY, nrmMtxArray,     sizeof(nrmMtxArray[0]));
269     GXSetArray(GX_TEX_MTX_ARRAY, texMtxArray,     sizeof(texMtxArray[0]));
270     GXSetArray(GX_VA_POS,        &VtxArray[0].x,  sizeof(VtxArray[0]));
271     GXSetArray(GX_VA_NRM,        &VtxArray[0].nx, sizeof(VtxArray[0]));
272 
273     // Vertex attribute/descriptor settings
274     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XY,  GX_S8, 0);
275     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_S8, 6);
276     GXClearVtxDesc();
277     GXSetVtxDesc(GX_VA_PNMTXIDX,   GX_DIRECT);
278     GXSetVtxDesc(GX_VA_TEX0MTXIDX, GX_DIRECT);
279     GXSetVtxDesc(GX_VA_POS,        GX_INDEX8);
280     GXSetVtxDesc(GX_VA_NRM,        GX_INDEX8);
281 
282     // Draw the model
283     GXCallDisplayList(ModelDLBuffer, ModelDLSize);
284 
285     return;
286 }
287 
288 /*---------------------------------------------------------------------------*
289     Name:           AnimTick
290 
291     Description:    Updates scene animation parameter by using PAD status.
292 
293     Arguments:      none
294 
295     Returns:        none
296  *---------------------------------------------------------------------------*/
AnimTick(void)297 void AnimTick( void )
298 {
299     Mtx     tmpMtx0, tmpMtx1, tmpMtx2;
300     f32     dir0, dir1;
301 
302     // Reset location
303     if ( DEMOPadGetButtonDown(0) & PAD_BUTTON_A )
304     {
305         AnimReset = 1;
306     }
307 
308     // Pause
309     if ( DEMOPadGetButtonDown(0) & PAD_BUTTON_B )
310     {
311         AnimPause = 1 - AnimPause;
312     }
313 
314     // Global model rotation calculation
315     MTXRotDeg(tmpMtx1, 'Z', ( (f32)DEMOPadGetSubStickX(0) / 32 + 0.20F));
316     MTXRotDeg(tmpMtx0, 'X', (-(f32)DEMOPadGetSubStickY(0) / 32));
317     MTXConcat(tmpMtx1, AnimGlobalRot, AnimGlobalRot);
318     MTXConcat(tmpMtx0, AnimGlobalRot, AnimGlobalRot);
319 
320     // Increment animation counter
321     AnimCounter = ( AnimCounter + 1 ) % 180;
322 
323     // Reset location when the object goes somewhere outside the screen.
324     if ( AnimReset )
325     {
326         MTXIdentity(AnimMtxOrigin);
327         AnimReset = 0;
328     }
329 
330     // Update matrix for origin (end point) of the object.
331     if ( !AnimPause )
332     {
333         MTXTrans(tmpMtx0, 0.0F, 0.0F, CONTOUR_SPAN);
334         MTXRotDeg(tmpMtx1, 'Y', AnimCtrlArray[AnimCtrlPtr].x);
335         MTXConcat(tmpMtx1, tmpMtx0, tmpMtx2);
336         MTXRotDeg(tmpMtx1, 'Z', AnimCtrlArray[AnimCtrlPtr].y);
337         MTXConcat(tmpMtx1, tmpMtx2, tmpMtx0);
338         MTXConcat(AnimMtxOrigin, tmpMtx0, AnimMtxOrigin);
339 
340         // Get new parameter for the top point.
341         dir0 = 7.5F * sinf((f32)AnimCounter * 3.1415F / 90) + 2.5F;
342         dir1 = 1.0F * sinf((f32)AnimCounter * 3.1415F / 45);
343         AnimCtrlArray[AnimCtrlPtr].x = (f32)(DEMOPadGetStickX(0)/5) + dir0;
344         AnimCtrlArray[AnimCtrlPtr].y = (f32)(DEMOPadGetStickY(0)/5) + dir1;
345 
346         // Advance pointer of ring buffer.
347         AnimCtrlPtr = (AnimCtrlPtr + 1) % NUM_CONTOUR;
348     }
349 
350     // Build matrix array
351     BuildMtxArray();
352 }
353 
354 /*---------------------------------------------------------------------------*
355     Name:           BuildModelDL
356 
357     Description:    Build a display list for stitched pipe model.
358 
359     Arguments:      none
360 
361     Returns:        none
362  *---------------------------------------------------------------------------*
363     This function puts these three command APIs into the display list:
364 
365         GXLoadPosMtxIndx / GXLoadTexMtxIndx / GXLoadNrmMtxIndx3x3
366 
367     that are basically safe with using inside a display list. Since actual
368     matrix loads will occur when you call this display list, you can
369     animate this object by just updating matrix array on main memory.
370  *---------------------------------------------------------------------------*/
BuildModelDL(void)371 void BuildModelDL( void )
372 {
373     s32          i, j, k;
374     u8           vi;
375     GXPosNrmMtx  pm0, pm1;
376     GXTexMtx     tm0, tm1;
377 
378     //---- allocate buffer for the display list
379     if ( ModelDLBuffer == NULL )
380     {
381         ModelDLBuffer = MEMAllocFromAllocator(&DemoAllocator1, DL_BUFSIZE);
382         DCInvalidateRange(ModelDLBuffer, DL_BUFSIZE);
383     }
384 
385     //---- start generating display list
386     GXBeginDisplayList(ModelDLBuffer, DL_BUFSIZE);
387 
388 
389     //-------- Pipe lid
390     pm0 = GX_PNMTX0;
391     tm0 = GX_TEXMTX0;
392     GXLoadPosMtxIndx   (0, pm0);
393     GXLoadNrmMtxIndx3x3(0, pm0);
394     GXLoadTexMtxIndx   (0, tm0, GX_MTX2x4);
395 
396     GXBegin( GX_TRIANGLEFAN, GX_VTXFMT0, VTX_PER_CONTOUR );
397     for ( i = 0; i < VTX_PER_CONTOUR; i ++ )
398     {
399         GXMatrixIndex1x8((u8)pm0);
400         GXMatrixIndex1x8((u8)tm0);
401         GXPosition1x8   ((u8)i);
402         GXNormal1x8     ((u8)i);
403     }
404     GXEnd( );
405 
406     //-------- Pipe body
407     for ( i = 0; i < NUM_CONTOUR-1; i += (NUM_MTX_SLOTS-1) )
408     {
409         // Load 10 transform matrices into HW slots.
410         //
411         // It is better to load matrices as much as possible at one
412         // time to minimize the stall latency of graphics pipeline.
413         pm0 = GX_PNMTX0;
414         tm0 = GX_TEXMTX0;
415         for ( j = 0 ; j < NUM_MTX_SLOTS ; j++ )
416         {
417             GXLoadPosMtxIndx   ((u16)(i+j), pm0);
418             GXLoadNrmMtxIndx3x3((u16)(i+j), pm0);
419             GXLoadTexMtxIndx   ((u16)(i+j), tm0, GX_MTX2x4);
420             pm0 = (GXPosNrmMtx)(pm0 + MTX_IDX_SPAN);
421             tm0 = (GXTexMtx)(tm0 + MTX_IDX_SPAN);
422         }
423 
424         // Stitch all transformed contour.
425         pm0 = GX_PNMTX0;
426         tm0 = GX_TEXMTX0;
427         for ( j = 0 ; j < (NUM_MTX_SLOTS-1) ; j++ )
428         {
429             pm1 = (GXPosNrmMtx)(pm0 + MTX_IDX_SPAN);
430             tm1 = (GXTexMtx)(tm0 + MTX_IDX_SPAN);
431 
432             GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT0, (VTX_PER_CONTOUR+1)*2);
433             vi = VTX_PER_CONTOUR-1;
434             for ( k = -1; k < VTX_PER_CONTOUR; k++ )
435             {
436                 GXMatrixIndex1x8((u8)pm0);
437                 GXMatrixIndex1x8((u8)tm0);
438                 GXPosition1x8   (vi);
439                 GXNormal1x8     (vi);
440                 GXMatrixIndex1x8((u8)pm1);
441                 GXMatrixIndex1x8((u8)tm1);
442                 GXPosition1x8   (vi);
443                 GXNormal1x8     (vi);
444                 vi = (u8)(k + 1);
445             }
446             GXEnd();
447 
448             pm0 = pm1;
449             tm0 = tm1;
450         }
451     }
452 
453     //-------- Pipe lid 1
454     pm1 = GX_PNMTX9;
455     tm1 = GX_TEXMTX9;
456     GXBegin(GX_TRIANGLEFAN, GX_VTXFMT0, VTX_PER_CONTOUR);
457     for ( i = 0; i < VTX_PER_CONTOUR; i ++ )
458     {
459         GXMatrixIndex1x8((u8)pm1);
460         GXMatrixIndex1x8((u8)tm1);
461         GXPosition1x8   ((u8)(VTX_PER_CONTOUR-1-i));
462         GXNormal1x8     ((u8)(VTX_PER_CONTOUR-1-i));
463     }
464     GXEnd();
465 
466 
467     //---- end of the display list
468     ModelDLSize = GXEndDisplayList();
469     if ( !ModelDLSize )
470     {
471         OSHalt("Display list exceeds size of the buffer\n");
472     }
473     OSReport("Size = %d\n", ModelDLSize);
474 }
475 
476 /*---------------------------------------------------------------------------*
477     Name:           BuildMtxArray
478 
479     Description:    Build matrix array for animation.
480 
481     Arguments:      none
482 
483     Returns:        none
484  *---------------------------------------------------------------------------*/
BuildMtxArray(void)485 void BuildMtxArray( void )
486 {
487     MyCameraObj* c = &DefaultCamera;
488     Mtx*    posMtxArray;
489     Mtx33*  nrmMtxArray;
490     Mtx24*  texMtxArray;
491     Mtx     tmpMtx0, tmpMtx1, tmpMtx2;
492     u32     i, j;
493     Vec     angles;
494     f32     nfct;
495 
496     // Switch matrix array buffer
497     //
498     //    Using double-buffering is good to gain performance.
499     //    This function builds up matrix data for the next frame into
500     //    one buffer while the GP may be drawing object by using matrix
501     //    data from another buffer.
502     CurrentMtxBuffer = 1 - CurrentMtxBuffer;
503     posMtxArray = PosMtxArrayBuf[CurrentMtxBuffer];
504     nrmMtxArray = NrmMtxArrayBuf[CurrentMtxBuffer];
505     texMtxArray = TexMtxArrayBuf[CurrentMtxBuffer];
506 
507 
508     // Get View matrix
509     MTXLookAt(c->viewMtx, &c->position, &c->up, &c->target);
510 
511     // Build position matrix array
512     MTXConcat(c->viewMtx, AnimGlobalRot, tmpMtx0);
513     MTXConcat(tmpMtx0, AnimMtxOrigin, posMtxArray[0]);
514     for ( i = 1; i < NUM_CONTOUR; i++ )
515     {
516         angles = AnimCtrlArray[(i+AnimCtrlPtr-1)%NUM_CONTOUR];
517 
518         MTXTrans(tmpMtx0, 0.0F, 0.0F, 50.0F);
519         MTXRotDeg(tmpMtx1, 'Y', angles.x);
520         MTXConcat(tmpMtx1, tmpMtx0, tmpMtx2);
521         MTXRotDeg(tmpMtx1, 'Z', angles.y);
522         MTXConcat(tmpMtx1, tmpMtx2, tmpMtx0);
523         MTXConcat(posMtxArray[i-1], tmpMtx0, posMtxArray[i]);
524     }
525 
526     // Build normal matrix array
527     for ( i = 0; i < NUM_CONTOUR; i++ )
528     {
529         // No need to calculate inverse-transpose because these
530         // matrices don't contain anisotropic scale factor.
531 
532         // Copy 3x3 part to normal matrix array.
533         CopyMtxTo3x3( posMtxArray[i], nrmMtxArray[i] );
534     }
535 
536     // Build texture matrix array for environment mapping
537     for ( i = 0; i < NUM_CONTOUR; i++ )
538     {
539         for ( j = 0; j < 2; j++ )
540         {
541             nfct = 0.5F / VECMag( (VecPtr)posMtxArray[i][0] );
542             if ( j == 1 ) nfct = -nfct;
543             texMtxArray[i][j][0] = posMtxArray[i][j][0] * nfct;
544             texMtxArray[i][j][1] = posMtxArray[i][j][1] * nfct;
545             texMtxArray[i][j][2] = posMtxArray[i][j][2] * nfct;
546             texMtxArray[i][j][3] = 0.5f;
547         }
548     }
549     DCFlushRange(posMtxArray, sizeof(Mtx)   * NUM_CONTOUR);
550     DCFlushRange(nrmMtxArray, sizeof(Mtx33) * NUM_CONTOUR);
551     DCFlushRange(texMtxArray, sizeof(Mtx24) * NUM_CONTOUR);
552 }
553 
554 /*---------------------------------------------------------------------------*
555     Name:           CopyMtxTo3x3
556 
557     Description:    Copy 3x3 portion from 3x4 matrix to another place
558                     in order to use GXLoadNrmMtxIndx3x3.
559 
560     Arguments:      src: source 3x4 matrix.
561                     dst   : destination 3x3 matrix.
562 
563     Returns:        none
564  *---------------------------------------------------------------------------*/
CopyMtxTo3x3(Mtx src,Mtx33 dst)565 inline void CopyMtxTo3x3( Mtx src, Mtx33 dst )
566 {
567     dst[0][0] = src[0][0];  dst[0][1] = src[0][1];  dst[0][2] = src[0][2];
568     dst[1][0] = src[1][0];  dst[1][1] = src[1][1];  dst[1][2] = src[1][2];
569     dst[2][0] = src[2][0];  dst[2][1] = src[2][1];  dst[2][2] = src[2][2];
570 }
571 
572 /*---------------------------------------------------------------------------*
573     Name:           CheckMissingObj
574 
575     Description:    Check if the object is drawn on the screen.
576                     (The object has gone somewhere outside.)
577 
578     Arguments:      none
579 
580     Returns:        none
581  *---------------------------------------------------------------------------*/
CheckMissingObj(void)582 void CheckMissingObj( void )
583 {
584     u16  bt, bb, br, bl;
585 
586     // Synchronization
587     GXDrawDone();
588     // Get bounding box
589     GXReadBoundingBox(&bl, &bt, &br, &bb);
590 
591     if ( br <= 0 && bl >= 640 )
592     {
593         // Object lost. Need reset.
594         AnimReset = 1;
595     }
596 
597     // Clear bounding box (for next frame)
598     GXClearBoundingBox();
599 }
600 
601 /*===========================================================================*/
602