1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin
3   File:     gc-matrix-gc.c
4 
5   Copyright 2000 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   $Log: gd-matrix-gc.c,v $
14   Revision 1.3.64.1  2009/12/08 02:44:59  abe_takehiro
15   Erased warning message
16 
17   Revision 1.3  2006/08/18 21:50:58  carlmu
18   Added explanatory output.
19 
20   Revision 1.2  2006/02/20 04:13:09  mitu
21   changed include path from dolphin/ to revolution/.
22 
23   Revision 1.1  2006/02/08 11:19:43  mitu
24   1st version.
25 
26 
27     3     02/09/06 11:26 Hirose
28     Resolved future time stamp problem.
29 
30     3     10/19/02 6:53p Hirose
31     Changed location of data file.
32 
33     2     9/24/01 2:23p Hirose
34     Changed flag definition.
35 
36     1     9/19/01 5:49p Carl
37     Source files for GD matrix demo.
38 
39   $NoKeywords: $
40  *---------------------------------------------------------------------------*/
41 
42 #include <demo.h>
43 #include <math.h>
44 
45 #include <revolution/gd.h>
46 
47 /*---------------------------------------------------------------------------*
48    Defines
49  *---------------------------------------------------------------------------*/
50 
51 // This macro is used to copy a 3x4 matrix into a 3x3 matrix
52 #define COPY3x3(ms, md) \
53     { md[0][0]=ms[0][0]; md[0][1]=ms[0][1]; md[0][2]=ms[0][2]; \
54       md[1][0]=ms[1][0]; md[1][1]=ms[1][1]; md[1][2]=ms[1][2]; \
55       md[2][0]=ms[2][0]; md[2][1]=ms[2][1]; md[2][2]=ms[2][2]; }
56 
57 /*---------------------------------------------------------------------------*
58    Forward references
59  *---------------------------------------------------------------------------*/
60 
61 void        main          ( void );
62 
63 static void CameraInit    ( void );
64 static void DrawInit      ( void );
65 static void DrawTick      ( void );
66 
67 static void AnimTick      ( void );
68 
69 static void ParameterInit ( void );
70 
71 #ifdef LOAD_DL_FROM_FILE
72 static void LoadDLs       ( void );
73 #else
74 extern void CreateDLs     ( void );
75 #endif
76 
77 /*---------------------------------------------------------------------------*
78    Global variables
79  *---------------------------------------------------------------------------*/
80 
81 // Display lists *************************************************************
82 
83 // This set of display lists will each load an indexed position matrix
84 // and an indexed normal matrix, then draw one face of the cube.
85 
86 GDLObj DrawDLOs[6];
87 
88 /*---------------------------------------------------------------------------*/
89 
90 // Actual primitive data follows
91 
92 #define SIDE 30
93 #define NORM (sqrt(3.0))/3.0
94 
95 // Remember:  Alignment of vertex arrays to 32B IS NOT required, but it
96 // may result in a slight performance improvement.
97 
98 float FloatVert[] ATTRIBUTE_ALIGN(32) =
99 {
100     -SIDE,  SIDE, -SIDE,
101     -SIDE,  SIDE,  SIDE,
102     -SIDE, -SIDE,  SIDE,
103     -SIDE, -SIDE, -SIDE,
104      SIDE,  SIDE, -SIDE,
105      SIDE, -SIDE, -SIDE,
106      SIDE, -SIDE,  SIDE,
107      SIDE,  SIDE,  SIDE,
108 };
109 
110 float FloatNorm[] ATTRIBUTE_ALIGN(32) =
111 {
112     -1,  1, -1,
113     -1,  1,  1,
114     -1, -1,  1,
115     -1, -1, -1,
116      1,  1, -1,
117      1, -1, -1,
118      1, -1,  1,
119      1,  1,  1,
120 };
121 
122 float FloatTex[] ATTRIBUTE_ALIGN(32) =
123 {
124     0.0F, 0.0F,
125     1.0F, 0.0F,
126     1.0F, 1.0F,
127     0.0F, 1.0F,
128 };
129 
130 // This array is used to animate the Draw DL's.
131 // Since it is CPU-only data, no special treatment is needed.
132 
133 float AnimData[6][3] =
134 {
135     -1.0f,  0.0f,  0.0f,
136      1.0f,  0.0f,  0.0f,
137      0.0f, -1.0f,  0.0f,
138      0.0f,  1.0f,  0.0f,
139      0.0f,  0.0f, -1.0f,
140      0.0f,  0.0f,  1.0f
141 };
142 
143 // These matrices will be referenced by the GP from the Draw DL's.
144 // They could be ALIGNed, but they don't have to be.
145 
146 Mtx posMats[6];
147 f32 nrmMats[6][3][3];
148 
149 // Misc data...
150 
151 Mtx v;          // view matrix
152 u32 rot;        // current cube rotation
153 
154 /*---------------------------------------------------------------------------*
155    Application main loop
156  *---------------------------------------------------------------------------*/
157 
main(void)158 void main ( void )
159 {
160     DEMOInit(NULL);
161 
162     OSReport("\n\n");
163     OSReport("**********************************************\n");
164     OSReport("gd-matrix-gc: Matrix-loading display list demo\n");
165     OSReport("**********************************************\n");
166     OSReport("To quit hit the start button.\n");
167     OSReport("\n");
168     OSReport("A button toggles animation.\n");
169     OSReport("**********************************************\n");
170     OSReport("\n\n");
171 
172     DrawInit();         // Prepare the display lists and such
173 
174     ParameterInit();
175 
176     DEMOPadRead();      // Read the joystick for this frame
177 
178     // While the quit button is not pressed
179     while(!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
180     {
181         DEMOPadRead();  // Read the joystick for this frame
182 
183         AnimTick();     // Do animation based on input
184 
185         DEMOBeforeRender();
186 
187         DrawTick();     // Draw the model.
188 
189         DEMODoneRender();
190     }
191 
192     OSHalt("End of test");
193 }
194 
195 /*---------------------------------------------------------------------------*
196    Functions
197  *---------------------------------------------------------------------------*/
198 
199 /*---------------------------------------------------------------------------*
200     Name:           CameraInit
201 
202     Description:    Initialize the projection matrix and load into hardware.
203 
204     Arguments:      v   view matrix to be passed to ViewInit
205                     cameraLocScale  scale for the camera's distance from the
206                                     object - to be passed to ViewInit
207 
208     Returns:        none
209  *---------------------------------------------------------------------------*/
CameraInit(void)210 static void CameraInit      ( void )
211 {
212     Mtx44 p;
213     Vec camPt = {0.0F, 0.0F, 650.0F};
214     Vec up = {0.0F, 1.0F, 0.0F};
215     Vec origin = {0.0F, 0.0F, 0.0F};
216 
217     MTXFrustum(p, 112, -112, -160, 160, 500, 2000);
218 
219     GXSetProjection(p, GX_PERSPECTIVE);
220 
221     MTXLookAt(v, &camPt, &up, &origin);
222 }
223 
224 
225 /*---------------------------------------------------------------------------*
226     Name:           LoadDLs
227 
228     Description:    Loads the display lists used by the program from a file.
229                     This routine is only called if LOAD_DL_FROM_FILE is defined.
230 
231     Arguments:      none
232 
233     Returns:        none
234  *---------------------------------------------------------------------------*/
235 #ifdef LOAD_DL_FROM_FILE
LoadDLs(void)236 static void LoadDLs ( void )
237 {
238     s32 err;
239     GDGList *DLDescArray;
240     GDGList *PLDescArray;
241     u32 numDLs, numPLs;
242     u32 i;
243 
244     err = GDReadDLFile("gddemo/gdMatrix.gdl", &numDLs, &numPLs,
245                        &DLDescArray, &PLDescArray);
246 
247     OSReport("(%d) Read %d DLs, %d PLs\n", err, numDLs, numPLs);
248 
249     ASSERTMSG(!err, "Error reading GDL file.\n");
250 
251     ASSERTMSG(numDLs >= 6 && numPLs >= 0, "Too little data in GDL file.\n");
252 
253     // Note: We put the DL length into the "offset" field, since that's
254     // where the run-time code expects it.  We do this since the CreateDLs
255     // function uses an oversize "length" field, and the actual valid data
256     // length is saved in the "offset" field in that case.  Thus we do the
257     // same thing here for consistency.
258 
259     for(i=0; i<6; i++)
260     {
261         GDInitGDLObj( &DrawDLOs[i],
262                       DLDescArray[i].ptr,
263                       DLDescArray[i].byteLength );
264         GDSetCurrent( &DrawDLOs[i] );
265         GDSetCurrOffset( DLDescArray[i].byteLength );
266     }
267 
268     GDSetCurrent( NULL );
269 }
270 #endif
271 
272 
273 /*---------------------------------------------------------------------------*
274     Name:           DrawInit
275 
276     Description:    Calls the correct initialization function for the current
277                     model.
278 
279     Arguments:      none
280 
281     Returns:        none
282  *---------------------------------------------------------------------------*/
DrawInit(void)283 static void DrawInit( void )
284 {
285     u32 i;
286     GXLightObj MyLight;
287     GXColor White = {255, 255, 255, 255};
288 
289     // Create all the display lists.
290     // In this demo, this is done at run-time.
291     // We can also just load the DL's from a file created by a DL tool.
292 #ifdef LOAD_DL_FROM_FILE
293     LoadDLs();
294 #else
295     CreateDLs();
296 #endif
297 
298     CameraInit();   // Initialize the camera.
299 
300     GXClearVtxDesc();  // Set up VCD/VAT.
301 
302     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
303     GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8);
304     GXSetArray(GX_VA_TEX0, FloatTex, 8);
305 
306     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
307     GXSetVtxDesc(GX_VA_NRM, GX_INDEX8);
308     GXSetArray(GX_VA_NRM, FloatNorm, 12);
309 
310     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
311     GXSetVtxDesc (GX_VA_POS, GX_INDEX8);
312     GXSetArray(GX_VA_POS, FloatVert, 12);
313 
314     // Set up a light
315     GXInitLightPos(&MyLight, 0.0F, 0.0F, 0.0F);
316     GXInitLightColor(&MyLight, White);
317     GXLoadLightObjImm(&MyLight, GX_LIGHT0);
318     GXSetChanCtrl(
319         GX_COLOR0,
320         GX_ENABLE,   // enable channel
321         GX_SRC_REG,  // amb source
322         GX_SRC_REG,  // mat source
323         GX_LIGHT0,   // light mask
324         GX_DF_CLAMP, // diffuse function
325         GX_AF_NONE);
326 
327     // Set up TEV
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     // We'll send the face color in through TEVREG0
334     GXSetTevColorIn(GX_TEVSTAGE0,
335                     GX_CC_ZERO, GX_CC_RASC, GX_CC_C0, GX_CC_ZERO);
336 
337     // Fix up normals
338     for(i = 0; i < 24; i++)
339     {
340         FloatNorm[i] *= NORM;
341     }
342 
343     // Flush to memory
344     DCFlushRange((void *)FloatNorm, sizeof(FloatNorm));
345 
346     // These matrices will be set up in DrawTick, below
347     GXSetArray(GX_POS_MTX_ARRAY, posMats, sizeof(Mtx));
348     GXSetArray(GX_NRM_MTX_ARRAY, nrmMats, sizeof(f32 [3][3]));
349 }
350 
351 /*---------------------------------------------------------------------------*
352     Name:           DrawTick
353 
354     Description:    Draw the current model once.
355 
356     Arguments:      v       view matrix
357                     m       model matrix
358 
359     Returns:        none
360  *---------------------------------------------------------------------------*/
DrawTick(void)361 static void DrawTick( void )
362 {
363     u32 i;
364     static GXColor color[6] = {
365         { 255,  0,  0, 255 },
366         { 0,  255,  0, 255 },
367         { 0,  0,  255, 255 },
368         { 0, 255, 255, 255 },
369         { 255, 0, 255, 255 },
370         { 255, 255, 0, 255 }
371     };
372 
373     // Draw the moving faces
374 
375     GXSetCullMode(GX_CULL_NONE);
376 
377     // Set the color, then call the DL to draw the geometry.
378     for(i=0; i<6; i++)
379     {
380         GXSetTevColor(GX_TEVREG0, color[i]);
381         GXCallDisplayList(GDGetGDLObjStart(&DrawDLOs[i]),
382                           GDGetGDLObjOffset(&DrawDLOs[i]));
383     }
384 }
385 
386 /*---------------------------------------------------------------------------*
387     Name:           AnimTick
388 
389     Description:    Animates the camera and object based on the joystick's
390                     state.
391 
392     Arguments:      none
393 
394     Returns:        none
395  *---------------------------------------------------------------------------*/
AnimTick(void)396 static void AnimTick ( void )
397 {
398     u32 i;
399     Mtx ry, rz, mv, tm, mn;
400     f32 tx, ty, tr;
401     u16 buttons = DEMOPadGetButton(0);
402 
403     // Just simple controls right now...
404 
405     if(buttons & PAD_BUTTON_A)
406     {
407         // suspend animation
408     } else {
409 
410         rot ++;
411         if(rot > 2159)
412             rot = 0;
413     }
414 
415     // Set up our transformations...
416 
417     tx = 0.0f;
418     ty = 0.0f;
419 
420     MTXRotDeg(ry, 'X', (float)rot);
421     MTXRotDeg(rz, 'Y', (float)rot / 3.0F);
422     MTXTrans(tm, tx, ty, 0);
423 
424     MTXConcat(rz, ry, mv);
425     MTXConcat(tm, mv, mv);
426     MTXConcat(v, mv, mv);
427 
428     MTXInverse(mv, mn);
429     MTXTranspose(mn, mn);
430 
431     // Need to set up and flush all matrices for the AltDrawList's.
432     if (rot % 120 < 60)
433     {
434         tr = (float)(rot % 60);
435     } else {
436         tr = (float)(60 - (rot % 60));
437     }
438 
439     // We recalculate and reload all the normal matrices, even though
440     // they're actually the same for all faces.  This is just example
441     // code to illustrate the various steps.
442     for(i=0; i<6; i++)
443     {
444         MTXTrans(tm, AnimData[i][0]*(tr),
445                      AnimData[i][1]*(tr),
446                      AnimData[i][2]*(tr));
447         MTXConcat(mv, tm, posMats[i]);
448         COPY3x3(mn, nrmMats[i]);
449     }
450 
451     // If you had a large number of matrices, you should flush them
452     // as you calculate them.  Since we have just a few here, it's okay
453     // to flush them all at once like this.
454     DCFlushRange((void*) posMats, sizeof(posMats));
455     DCFlushRange((void*) nrmMats, sizeof(nrmMats));
456 }
457 
458 /*---------------------------------------------------------------------------*
459     Name:           ParameterInit
460 
461     Description:    Initialize parameters for single frame display
462 
463     Arguments:      none
464 
465     Returns:        none
466  *---------------------------------------------------------------------------*/
ParameterInit(void)467 static void ParameterInit ( void )
468 {
469     rot = 45;
470 }
471 
472 /****************************************************************************/
473 
474 
475