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