1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin/Revolution gx demo
3   File:     tf-tg-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 #include <demo.h>
15 #include <math.h>
16 
17 /*---------------------------------------------------------------------------*
18    Forward references
19  *---------------------------------------------------------------------------*/
20 
21 void        main            ( void );
22 
23 static void CameraInit      ( void );
24 static void DrawInit        ( void );
25 static void DrawTick        ( void );
26 
27 static void AnimTick        ( void );
28 
29 static void DrawSmoothCube  ( float tx, float ty );
30 static void SendVertex      ( u16 posIndex, u16 texCoordIndex );
31 
32 static void SetTexGenMethod ( GXTexMtx mtxIdx );
33 
34 static void SetNoTexGenMtx          ( void );
35 static void SetProjectionTexGenMtx  ( void );
36 static void SetTexCoordTexGenMtx    ( void );
37 static void SetReflectionTexGenMtx  ( void );
38 
39 #define SIDE 35
40 #define NORM (sqrt(3.0))/3.0
41 
42 /*---------------------------------------------------------------------------*
43    Global variables
44  *---------------------------------------------------------------------------*/
45 Mtx v;
46 u32 rot;
47 u32 rot2;
48 float trans;
49 
50 u8 CurrentControl;
51 u8 DoRotation = 1;
52 
53 GXTexObj to1, to2;
54 
55 float FloatVert[] ATTRIBUTE_ALIGN(32) =
56                     {   -SIDE, SIDE, -SIDE,
57                         -SIDE, SIDE, SIDE,
58                         -SIDE, -SIDE, SIDE,
59                         -SIDE, -SIDE, -SIDE,
60                         SIDE, SIDE, -SIDE,
61                         SIDE, -SIDE, -SIDE,
62                         SIDE, -SIDE, SIDE,
63                         SIDE, SIDE, SIDE
64                     };
65 
66 float FloatNorm[] ATTRIBUTE_ALIGN(32) =
67                     {   -1, 1, -1,
68                         -1, 1, 1,
69                         -1, -1, 1,
70                         -1, -1, -1,
71                         1, 1, -1,
72                         1, -1, -1,
73                         1, -1, 1,
74                         1, 1, 1
75                     };
76 
77 float FloatTex[] ATTRIBUTE_ALIGN(32) =
78                     {   0.0F, 0.0F,
79                         1.0F, 0.0F,
80                         1.0F, 1.0F,
81                         0.0F, 1.0F
82                     };
83 /*---------------------------------------------------------------------------*
84    Application main loop
85  *---------------------------------------------------------------------------*/
main(void)86 void main ( void )
87 {
88     DEMOInit(NULL);
89 
90     OSReport("\n\n");
91     OSReport("**********************************************\n");
92     OSReport("tf-tg-mtx: Texgen Matrix demo\n");
93     OSReport("**********************************************\n");
94     OSReport("To quit hit the start button.\n");
95     OSReport("\n");
96     OSReport("Each cube is drawn with a different HW matrix.\n");
97     OSReport("\n");
98     OSReport("B button toggles the animation.\n");
99     OSReport("X button changes the texgen method.\n");
100     OSReport("**********************************************\n");
101     OSReport("\n\n");
102 
103     DrawInit();         // Define my vertex formats and set array pointers.
104 
105     DEMOPadRead();      // Read the joystick for this frame
106 
107     // While the quit button is not pressed
108     while(!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
109     {
110         DEMOPadRead();  // Read the joystick for this frame
111 
112         // Do animation based on input
113         AnimTick();
114         DEMOBeforeRender();
115 
116         DrawTick();     // Draw the model.
117 
118         DEMODoneRender();
119     }
120 
121     OSHalt("End of test");
122 }
123 
124 /*---------------------------------------------------------------------------*
125    Functions
126  *---------------------------------------------------------------------------*/
127 
128 
129 /*---------------------------------------------------------------------------*
130     Name:           CameraInit
131 
132     Description:    Initialize the projection matrix and load into hardware.
133 
134     Arguments:      v   view matrix to be passed to ViewInit
135                     cameraLocScale  scale for the camera's distance from the
136                                     object - to be passed to ViewInit
137 
138     Returns:        none
139  *---------------------------------------------------------------------------*/
CameraInit(void)140 static void CameraInit      ( void )
141 {
142     Mtx44 p;
143     Vec camPt = {0.0F, 0.0F, 650.0F};
144     Vec up = {0.0F, 1.0F, 0.0F};
145     Vec origin = {0.0F, 0.0F, 0.0F};
146 
147     MTXFrustum(p, 240, -240, -320, 320, 500, 2000);
148 
149     GXSetProjection(p, GX_PERSPECTIVE);
150 
151     MTXLookAt(v, &camPt, &up, &origin);
152 }
153 
154 /*---------------------------------------------------------------------------*
155     Name:           DrawInit
156 
157     Description:    Calls the correct initialization function for the current
158                     model.
159 
160     Arguments:      none
161 
162     Returns:        none
163  *---------------------------------------------------------------------------*/
DrawInit(void)164 static void DrawInit( void )
165 {
166     TPLPalettePtr tpl = 0;
167     u32           i;
168 
169     CameraInit();   // Initialize the camera.
170 
171     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
172     GXSetVtxDesc(GX_VA_TEX0, GX_INDEX16);
173     GXSetArray(GX_VA_TEX0, FloatTex, 8);
174 
175     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
176     GXSetVtxDesc(GX_VA_NRM, GX_INDEX16);
177     GXSetArray(GX_VA_NRM, FloatNorm, 12);
178 
179     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
180     GXSetVtxDesc (GX_VA_POS, GX_INDEX16);
181     GXSetArray(GX_VA_POS, FloatVert, 12);
182 
183     TPLGetPalette(&tpl, "gxTests/tf-02.tpl");
184 
185     TPLGetGXTexObjFromPalette(tpl, &to1, 0);
186     TPLGetGXTexObjFromPalette(tpl, &to2, 1);
187 
188     GXLoadTexObj(&to1, GX_TEXMAP0);
189 
190     GXSetNumChans(0);
191     GXSetNumTexGens(1);
192     GXSetNumTevStages(1);
193     GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE);
194     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
195 
196     for(i = 0; i < 24; i++)
197     {
198         FloatNorm[i] *= NORM;
199     }
200 
201     OSReport("\n\nNo TexGen\n\n");
202 }
203 
204 /*---------------------------------------------------------------------------*
205     Name:           DrawTick
206 
207     Description:    Draw the current model once.
208 
209     Arguments:      v       view matrix
210                     m       model matrix
211 
212     Returns:        none
213  *---------------------------------------------------------------------------*/
DrawTick(void)214 static void DrawTick( void )
215 {
216 
217     switch(CurrentControl)
218     {
219         case 0:
220             SetNoTexGenMtx();
221             break;
222         case 1:
223             SetProjectionTexGenMtx();
224             break;
225         case 2:
226             SetTexCoordTexGenMtx();
227             break;
228         case 3:
229             SetReflectionTexGenMtx();
230             break;
231     }
232 
233     SetTexGenMethod(GX_TEXMTX0);
234     DrawSmoothCube(-240, 150);
235 
236     SetTexGenMethod(GX_TEXMTX1);
237     DrawSmoothCube(-80, 150);
238 
239     SetTexGenMethod(GX_TEXMTX2);
240     DrawSmoothCube(80, 150);
241 
242     SetTexGenMethod(GX_TEXMTX3);
243     DrawSmoothCube(240, 150);
244 
245     SetTexGenMethod(GX_TEXMTX4);
246     DrawSmoothCube(-240, -150);
247 
248     SetTexGenMethod(GX_TEXMTX5);
249     DrawSmoothCube(-80, -150);
250 
251     SetTexGenMethod(GX_TEXMTX6);
252     DrawSmoothCube(80, -150);
253 
254     SetTexGenMethod(GX_TEXMTX7);
255     DrawSmoothCube(240, -150);
256 
257     SetTexGenMethod(GX_TEXMTX8);
258     DrawSmoothCube(-160, 0);
259 
260     SetTexGenMethod(GX_TEXMTX9);
261     DrawSmoothCube(160, 0);
262 
263     // Don't draw cube with identity matrix for projected or
264     // normal texcoords since this results in Q=0 on 4 cube faces
265     if (CurrentControl != 1 && CurrentControl != 3)
266     {
267         SetTexGenMethod(GX_IDENTITY);
268         DrawSmoothCube(0, 0);
269     }
270 }
271 
272 /*---------------------------------------------------------------------------*
273     Name:           AnimTick
274 
275     Description:    Animates the camera and object based on the joystick's
276                     state.
277 
278     Arguments:      none
279 
280     Returns:        none
281  *---------------------------------------------------------------------------*/
AnimTick(void)282 static void AnimTick ( void )
283 {
284     u16 buttons = DEMOPadGetButtonDown(0);
285 
286     if(buttons & PAD_BUTTON_X)
287     {
288         CurrentControl ++;
289         if(CurrentControl > 3)
290             CurrentControl = 0;
291 
292         switch(CurrentControl)
293         {
294             case 0:
295                 GXLoadTexObj(&to1, GX_TEXMAP0);
296                 OSReport("\n\nNo TexGen\n\n");
297                 break;
298 
299             case 1:
300                 OSReport("\n\nTexture Projection (position * 3x4 matrix)\n\n");
301                 break;
302 
303             case 2:
304                 OSReport("\n\nTexture rotation and translation (TexCoord * 2x4 matrix)\n\n");
305                 break;
306 
307             case 3:
308                 GXLoadTexObj(&to2, GX_TEXMAP0);
309                 OSReport("\n\nReflection mapping (normal * 3x4 matrix)\n\n");
310                 break;
311         }
312     }
313 
314     if(buttons & PAD_BUTTON_B)
315     {
316         if(DoRotation)
317             DoRotation = 0;
318         else
319             DoRotation = 1;
320     }
321 
322     if(DoRotation)
323     {
324         rot ++;
325         if(rot > 1439)
326             rot = 0;
327     }
328 
329     rot2 ++;
330     if(rot2 > 1439)
331         rot2 = 0;
332 
333     trans += .01F;
334     if(trans > 2.0F)
335         trans = 0.0F;
336 }
337 
338 /*---------------------------------------------------------------------------*/
DrawSmoothCube(float tx,float ty)339 static void DrawSmoothCube ( float tx, float ty )
340 {
341     Mtx ry, rz, mv, t;
342 
343     MTXRotDeg(ry, 'Y', (float)rot);
344     MTXRotDeg(rz, 'Z', (float)rot);
345     MTXTrans(t, tx, ty, 0);
346 
347     MTXConcat(rz, ry, mv);
348     MTXConcat(t, mv, mv);
349     MTXConcat(v, mv, mv);
350     GXLoadPosMtxImm(mv, GX_PNMTX0);
351     MTXInverse(mv, mv);
352     MTXTranspose(mv, mv);
353     GXLoadNrmMtxImm(mv, GX_PNMTX0);
354 
355     GXBegin(GX_QUADS, GX_VTXFMT0, 4*6);
356 
357         SendVertex(0, 0);
358         SendVertex(1, 1);
359         SendVertex(2, 2);
360         SendVertex(3, 3);
361 
362         SendVertex(4, 0);
363         SendVertex(5, 1);
364         SendVertex(6, 2);
365         SendVertex(7, 3);
366 
367         SendVertex(2, 0);
368         SendVertex(6, 1);
369         SendVertex(5, 2);
370         SendVertex(3, 3);
371 
372         SendVertex(1, 0);
373         SendVertex(0, 1);
374         SendVertex(4, 2);
375         SendVertex(7, 3);
376 
377         SendVertex(5, 0);
378         SendVertex(4, 1);
379         SendVertex(0, 2);
380         SendVertex(3, 3);
381 
382         SendVertex(6, 0);
383         SendVertex(2, 1);
384         SendVertex(1, 2);
385         SendVertex(7, 3);
386 
387     GXEnd();
388 }
389 
390 /*---------------------------------------------------------------------------*/
SendVertex(u16 posIndex,u16 texCoordIndex)391 static void SendVertex ( u16 posIndex, u16 texCoordIndex )
392 {
393     GXPosition1x16(posIndex);
394     GXNormal1x16(posIndex);
395     GXTexCoord1x16(texCoordIndex);
396 }
397 
398 /*---------------------------------------------------------------------------*/
SetTexGenMethod(GXTexMtx mtxIdx)399 static void SetTexGenMethod ( GXTexMtx mtxIdx )
400 {
401     switch(CurrentControl)
402     {
403         case 0:
404             GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, mtxIdx);
405             break;
406 
407         case 1:
408             GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX3x4, GX_TG_POS, mtxIdx);
409             break;
410 
411         case 2:
412             GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, mtxIdx);
413             break;
414 
415         case 3:
416             GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX3x4, GX_TG_NRM, mtxIdx);
417             break;
418 
419     }
420 }
421 
422 /*---------------------------------------------------------------------------*/
SetNoTexGenMtx(void)423 static void SetNoTexGenMtx ( void )
424 {
425     Mtx m;
426 
427     MTXIdentity(m);
428 
429     GXLoadTexMtxImm(m, GX_TEXMTX0, GX_MTX2x4);
430     GXLoadTexMtxImm(m, GX_TEXMTX1, GX_MTX2x4);
431     GXLoadTexMtxImm(m, GX_TEXMTX2, GX_MTX2x4);
432     GXLoadTexMtxImm(m, GX_TEXMTX3, GX_MTX2x4);
433     GXLoadTexMtxImm(m, GX_TEXMTX4, GX_MTX2x4);
434     GXLoadTexMtxImm(m, GX_TEXMTX5, GX_MTX2x4);
435     GXLoadTexMtxImm(m, GX_TEXMTX6, GX_MTX2x4);
436     GXLoadTexMtxImm(m, GX_TEXMTX7, GX_MTX2x4);
437     GXLoadTexMtxImm(m, GX_TEXMTX8, GX_MTX2x4);
438     GXLoadTexMtxImm(m, GX_TEXMTX9, GX_MTX2x4);
439 }
440 
441 /*---------------------------------------------------------------------------*/
SetProjectionTexGenMtx(void)442 static void SetProjectionTexGenMtx ( void )
443 {
444     //assume all lights are at the origin pointing down the -z axis
445 
446     Mtx proj;
447     Mtx ry, rz, mv;//, t;
448 
449     MTXRotDeg(ry, 'Y', (float)rot);
450     MTXRotDeg(rz, 'Z', (float)rot);
451 
452     MTXConcat(rz, ry, mv);
453     MTXConcat(v, mv, mv);
454 
455     MTXLightFrustum(proj, -5, 5, -5, 5, 50, 0.5F, 0.5F, 0.5F, 0.5F);
456     MTXConcat(proj, mv, proj);
457     GXLoadTexMtxImm(proj, GX_TEXMTX0, GX_MTX3x4);
458 
459     MTXLightFrustum(proj, -5, 5, -5, 5, 20, 0.5F, 0.5F, 0.5F, 0.5F);
460     MTXConcat(proj, mv, proj);
461     GXLoadTexMtxImm(proj, GX_TEXMTX1, GX_MTX3x4);
462 
463     MTXLightFrustum(proj, -5, 5, -5, 5, 30, 0.5F, 0.5F, 0.7F, 0.3F);
464     MTXConcat(proj, mv, proj);
465     GXLoadTexMtxImm(proj, GX_TEXMTX2, GX_MTX3x4);
466 
467     MTXLightFrustum(proj, -5, 5, -5, 5, 25, 1.0F, 1.0F, 0.5F, 0.5F);
468     MTXConcat(proj, mv, proj);
469     GXLoadTexMtxImm(proj, GX_TEXMTX3, GX_MTX3x4);
470 
471     MTXLightFrustum(proj, -10, 10, -5, 5, 5, 0.5F, 0.5F, 0.5F, 0.5F);
472     MTXConcat(proj, mv, proj);
473     GXLoadTexMtxImm(proj, GX_TEXMTX4, GX_MTX3x4);
474 
475     MTXLightFrustum(proj, -5, 5, -20, 20, 5, 0.5F, 0.5F, 0.5F, 0.5F);
476     MTXConcat(proj, mv, proj);
477     GXLoadTexMtxImm(proj, GX_TEXMTX5, GX_MTX3x4);
478 
479     MTXLightFrustum(proj, -5, 5, -20, 20, 25, 0.5F, 0.5F, 0.5F, 0.5F);
480     MTXConcat(proj, mv, proj);
481     GXLoadTexMtxImm(proj, GX_TEXMTX6, GX_MTX3x4);
482 
483     MTXLightFrustum(proj, -5, 5, -20, 20, 8, 0.5F, 0.5F, 0.5F, 0.5F);
484     MTXConcat(proj, mv, proj);
485     GXLoadTexMtxImm(proj, GX_TEXMTX7, GX_MTX3x4);
486 
487     MTXLightFrustum(proj, -5, 5, -20, 20, 27, 1.5F, 1.5F, 0.5F, 0.5F);
488     MTXConcat(proj, mv, proj);
489     GXLoadTexMtxImm(proj, GX_TEXMTX8, GX_MTX3x4);
490 
491     MTXLightFrustum(proj, -20, 20, -20, 20, 29, 0.5F, 0.5F, 0.75F, 0.75F);
492     MTXConcat(proj, mv, proj);
493     GXLoadTexMtxImm(proj, GX_TEXMTX9, GX_MTX3x4);
494 
495 
496 }
497 
498 /*---------------------------------------------------------------------------*/
SetTexCoordTexGenMtx(void)499 static void SetTexCoordTexGenMtx ( void )
500 {
501     Mtx rz, tx, ty, mt;
502 
503     MTXRotDeg(rz, 'Z', ((float)rot2) / 4.0F);
504     MTXTrans(tx, trans, 0.0F, 0.0F);
505     MTXTrans(ty, 0.0F, trans, 0.0F);
506 
507     GXLoadTexMtxImm(rz, GX_TEXMTX0, GX_MTX2x4);
508     GXLoadTexMtxImm(tx, GX_TEXMTX1, GX_MTX2x4);
509     GXLoadTexMtxImm(ty, GX_TEXMTX2, GX_MTX2x4);
510 
511     MTXConcat(ty, rz, mt);
512     GXLoadTexMtxImm(mt, GX_TEXMTX3, GX_MTX2x4);
513     MTXConcat(tx, rz, mt);
514     GXLoadTexMtxImm(mt, GX_TEXMTX4, GX_MTX2x4);
515     MTXConcat(ty, tx, mt);
516     GXLoadTexMtxImm(mt, GX_TEXMTX5, GX_MTX2x4);
517     MTXConcat(tx, rz, mt);
518     MTXConcat(ty, mt, mt);
519     GXLoadTexMtxImm(mt, GX_TEXMTX6, GX_MTX2x4);
520 
521     MTXTrans(tx, trans/2.0F, 0.0F, 0.0F);
522     MTXTrans(ty, 0.0F, trans * 2.0F, 0.0F);
523 
524     GXLoadTexMtxImm(tx, GX_TEXMTX7, GX_MTX2x4);
525     GXLoadTexMtxImm(ty, GX_TEXMTX8, GX_MTX2x4);
526     MTXConcat(tx, ty, mt);
527     GXLoadTexMtxImm(mt, GX_TEXMTX9, GX_MTX2x4);
528 }
529 
530 /*---------------------------------------------------------------------------*/
SetReflectionTexGenMtx(void)531 static void SetReflectionTexGenMtx ( void )
532 {
533     Mtx ry, rz, mv, t, s;
534 
535     MTXRotDeg(ry, 'Y', (float)rot);
536     MTXRotDeg(rz, 'Z', (float)rot);
537     MTXScale(s, -0.5F, -0.5F, 0.0F);
538     MTXTrans(t, 0.5F, 0.5F, 1.0F);
539 
540     MTXConcat(rz, ry, mv);
541     MTXInverse(mv, mv);
542     MTXTranspose(mv, mv);
543     MTXConcat(s, mv, mv);
544     MTXConcat(t, mv, mv);
545 
546     GXLoadTexMtxImm(mv, GX_TEXMTX0, GX_MTX3x4);
547     GXLoadTexMtxImm(mv, GX_TEXMTX1, GX_MTX3x4);
548     GXLoadTexMtxImm(mv, GX_TEXMTX2, GX_MTX3x4);
549     GXLoadTexMtxImm(mv, GX_TEXMTX3, GX_MTX3x4);
550     GXLoadTexMtxImm(mv, GX_TEXMTX4, GX_MTX3x4);
551     GXLoadTexMtxImm(mv, GX_TEXMTX5, GX_MTX3x4);
552     GXLoadTexMtxImm(mv, GX_TEXMTX6, GX_MTX3x4);
553     GXLoadTexMtxImm(mv, GX_TEXMTX7, GX_MTX3x4);
554     GXLoadTexMtxImm(mv, GX_TEXMTX8, GX_MTX3x4);
555     GXLoadTexMtxImm(mv, GX_TEXMTX9, GX_MTX3x4);
556 }
557 
558 /*===========================================================================*/
559