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