1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin/Revolution gx demo
3   File:     tg-project.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      ( Mtx v );
24 static void ViewInit        ( Mtx v );
25 static void DrawInit        ( void );
26 static void DrawTick        ( void );
27 static void VertexLightInit ( void );
28 
29 static void MakeModelMtx    ( Vec xAxis, Vec yAxis, Vec zAxis, Mtx m );
30 static void AnimTick        ( Mtx v );
31 
32 static void DrawFrust       ( void );
33 
34 static void TextureLightInit( Mtx rot );
35 
36 /*---------------------------------------------------------------------------*
37    Global variables
38  *---------------------------------------------------------------------------*/
39 // Vectors to keep track of the camera's coordinate system orientation
40 Vec CamX = {1.0F, 0.0F, 0.0F};
41 Vec CamY = {0.0F, 1.0F, 0.0F};
42 Vec CamZ = {0.0F, 0.0F, 1.0F};
43 
44 Vec LightY = {0.0F, 1.0F, 0.0F};
45 Vec LightX = {1.0F, 0.0F, 0.0F};
46 Vec LightZ = {0.0F, 0.0F, 1.0F};
47 
48 Mtx v, m;
49 
50 // Scale for the camera's distance from the object
51 float CameraLocScale = 10;
52 
53 Mtx lv;
54 
55 float xmin = -.5F, xmax = .5F;
56 float ymin = -.5F, ymax = .5F;
57 float nnear = 5.0F;
58 float ffar = 100.0F;
59 float distance = -45.0F;
60 
61 u8  CurrentControl = 0;
62 u8  CurrentModel = 0;
63 u8  CurrentTexture = 0;
64 GXTevMode   CurrentTevMode = GX_DECAL;
65 
66 TPLPalettePtr tpl = 0;
67 
68 /*---------------------------------------------------------------------------*
69    Application main loop
70  *---------------------------------------------------------------------------*/
main(void)71 void main ( void )
72 {
73     DEMOInit(NULL);
74 
75     DrawInit();         // Define my vertex formats and set array pointers.
76 
77     VertexLightInit();
78 
79     DEMOPadRead();      // Read the joystick for this frame
80 
81     // While the quit button is not pressed
82     while(!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
83     {
84         DEMOPadRead();      // Read the joystick for this frame
85 
86         // Do animation based on input
87         AnimTick(v);
88         DEMOBeforeRender();
89 
90         DrawTick();     // Draw the model.
91 
92         DEMODoneRender();
93     }
94 
95     OSHalt("End of demo");
96 }
97 
98 /*---------------------------------------------------------------------------*
99    Functions
100  *---------------------------------------------------------------------------*/
101 
102 
103 /*---------------------------------------------------------------------------*
104     Name:           CameraInit
105 
106     Description:    Initialize the projection matrix and load into hardware.
107 
108     Arguments:      v   view matrix to be passed to ViewInit
109                     cameraLocScale  scale for the camera's distance from the
110                                     object - to be passed to ViewInit
111 
112     Returns:        none
113  *---------------------------------------------------------------------------*/
CameraInit(Mtx v)114 static void CameraInit      ( Mtx v )
115 {
116     Mtx44 p;
117 
118     MTXFrustum(p, .24F * CameraLocScale,-.24F * CameraLocScale,
119                -.32F * CameraLocScale, .32F * CameraLocScale,
120                .5F * CameraLocScale, 20.0F * CameraLocScale);
121 
122     GXSetProjection(p, GX_PERSPECTIVE);
123 
124     ViewInit(v);
125 }
126 
127 /*---------------------------------------------------------------------------*
128     Name:           ViewInit
129 
130     Description:    Initialize the view matrix.
131 
132     Arguments:      v       view matrix
133                     cameraLocScale  value used to determine camera's distance
134                     from the object
135 
136     Returns:        none
137  *---------------------------------------------------------------------------*/
ViewInit(Mtx v)138 static void ViewInit ( Mtx v )
139 {
140     Vec camPt = {0.0F, 0.0F, 8.0F};
141     Vec up = {0.0F, 1.0F, 0.0F};
142     Vec origin = {0.0F, 0.0F, 0.0F};
143 
144     camPt.x *= CameraLocScale;  // Scale camPt by cameraLocScale
145     camPt.y *= CameraLocScale;
146     camPt.z *= CameraLocScale;
147 
148     MTXLookAt(v, &camPt, &up, &origin);
149 }
150 
151 
152 /*---------------------------------------------------------------------------*
153     Name:           DrawInit
154 
155     Description:    Calls the correct initialization function for the current
156                     model.
157 
158     Arguments:      none
159 
160     Returns:        none
161  *---------------------------------------------------------------------------*/
DrawInit(void)162 static void DrawInit( void )
163 {
164     GXTexObj to;
165     TPLDescriptorPtr tdp;
166 
167     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
168     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
169 
170     GXClearVtxDesc();
171     GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
172     GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
173 
174     CameraInit(v);  // Re-Initialize the camera.
175 
176     GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX3x4, GX_TG_POS, GX_TEXMTX0);
177     GXSetNumChans(1);
178 
179     TPLGetPalette(&tpl, "gxTests/tg-01.tpl");
180     tdp = TPLGet(tpl, 0);
181 
182     GXInitTexObj(&to,
183                  tdp->textureHeader->data,
184                  tdp->textureHeader->width,
185                  tdp->textureHeader->height,
186                  (GXTexFmt)tdp->textureHeader->format,
187                  GX_CLAMP,
188                  GX_CLAMP,
189                  GX_FALSE);
190 
191     GXInitTexObjLOD(&to,
192                     tdp->textureHeader->minFilter,
193                     tdp->textureHeader->magFilter,
194                     tdp->textureHeader->minLOD,
195                     tdp->textureHeader->maxLOD,
196                     tdp->textureHeader->LODBias,
197                     GX_FALSE,
198                     tdp->textureHeader->edgeLODEnable,
199                     GX_ANISO_1);
200 
201     GXLoadTexObj(&to, GX_TEXMAP0);
202 
203     MTXScale(m, 20.0F, 20.0F, 20.0F);
204 }
205 
206 /*---------------------------------------------------------------------------*
207     Name:           DrawTick
208 
209     Description:    Draw the current model once.
210 
211     Arguments:      v       view matrix
212                     m       model matrix
213 
214     Returns:        none
215  *---------------------------------------------------------------------------*/
DrawTick(void)216 static void DrawTick( void )
217 {
218     Mtx mv;
219 
220     GXSetTevOp(GX_TEVSTAGE0, CurrentTevMode);
221     GXSetNumTexGens(1);
222     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
223 
224     GXSetChanCtrl(
225         GX_COLOR0,
226         TRUE,    // enable channel
227         GX_SRC_REG,  // amb source
228         GX_SRC_REG,  // mat source
229         GX_LIGHT0,   // light mask
230         GX_DF_CLAMP, // diffuse function
231         GX_AF_NONE);
232 
233     MTXConcat(v, m, mv);
234     GXLoadPosMtxImm(mv, GX_PNMTX0);
235     MTXInverse(mv, mv);
236     MTXTranspose(mv, mv);
237     GXLoadNrmMtxImm(mv, GX_PNMTX0);
238     switch(CurrentModel)
239     {
240         case 0:
241             GXDrawCube();
242             break;
243         case 1:
244             GXDrawDodeca();
245             break;
246         case 2:
247             GXDrawCylinder(20);
248             break;
249         case 3:
250             GXDrawSphere1(3);
251             break;
252         case 4:
253             GXDrawOctahedron();
254             break;
255         case 5:
256             GXDrawIcosahedron();
257             break;
258         case 6:
259             GXDrawTorus(.3F, 10, 50);
260             break;
261     }
262 
263     GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
264     GXSetNumTexGens(0);
265     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
266     GXSetChanCtrl(
267         GX_COLOR0,
268         FALSE,    // disable channel
269         GX_SRC_VTX,  // amb source
270         GX_SRC_VTX,  // mat source
271         GX_LIGHT0,   // light mask
272         GX_DF_CLAMP, // diffuse function
273         GX_AF_NONE);
274     DrawFrust();
275 }
276 
VertexLightInit(void)277 static void VertexLightInit ( void )
278 {
279     GXLightObj MyLight;
280     GXColor color = {255, 255, 255, 255};
281 
282     GXInitLightPos(&MyLight, 0.0F, 0.0F, 0.0F);
283     GXInitLightColor(&MyLight, color);
284     GXLoadLightObjImm(&MyLight, GX_LIGHT0);
285 
286     color.g = color.b = 0;
287     GXSetChanMatColor(GX_COLOR0, color);
288 }
289 
290 /*---------------------------------------------------------------------------*
291     Name:           MakeModelMtx
292 
293     Description:    computes a model matrix from 3 vectors representing an
294                     object's coordinate system.
295 
296     Arguments:      xAxis   vector for the object's X axis
297                     yAxis   vector for the object's Y axis
298                     zAxis   vector for the object's Z axis
299 
300     Returns:        none
301  *---------------------------------------------------------------------------*/
MakeModelMtx(Vec xAxis,Vec yAxis,Vec zAxis,Mtx m)302 static void MakeModelMtx ( Vec xAxis, Vec yAxis, Vec zAxis, Mtx m )
303 {
304     VECNormalize(&xAxis,&xAxis);
305     VECNormalize(&yAxis,&yAxis);
306     VECNormalize(&zAxis, &zAxis);
307 
308     m[0][0] = xAxis.x;
309     m[1][0] = xAxis.y;
310     m[2][0] = xAxis.z;
311 
312     m[0][1] = yAxis.x;
313     m[1][1] = yAxis.y;
314     m[2][1] = yAxis.z;
315 
316     m[0][2] = zAxis.x;
317     m[1][2] = zAxis.y;
318     m[2][2] = zAxis.z;
319 
320     m[0][3] = 0.0F;
321     m[1][3] = 0.0F;
322     m[2][3] = 0.0F;
323 }
324 
325 /*---------------------------------------------------------------------------*
326     Name:           AnimTick
327 
328     Description:    Animates the camera and object based on the joystick's
329                     state.
330 
331     Arguments:      m       model matrix
332                     v       view matrix
333                     cameraLocScale  scale value for the camera's distance
334                                     to the object.
335 
336     Returns:        none
337  *---------------------------------------------------------------------------*/
AnimTick(Mtx v)338 static void AnimTick ( Mtx v )
339 {
340     Mtx rot;
341     GXTexObj to;
342     TPLDescriptorPtr tdp;
343 
344     u16 buttons = DEMOPadGetButton(0);
345     u16 downs   = DEMOPadGetButtonDown(0);
346     s8 stickX = DEMOPadGetStickX(0);
347     s8 stickY = DEMOPadGetStickY(0);
348 
349     if(downs & PAD_BUTTON_X)
350     {
351         CurrentControl ++;
352         if(CurrentControl > 4)
353             CurrentControl = 0;
354 
355         switch(CurrentControl)
356         {
357             case 0:
358                 OSReport("\n\nCamera Control\n\n");
359                 break;
360             case 1:
361                 OSReport("\n\nLight Position Control\n\n");
362                 break;
363             case 2:
364                 OSReport("\n\nLight Parameter Control\n\n");
365                 break;
366             case 3:
367                 OSReport("\n\nModel Select Control\n\n");
368                 break;
369             case 4:
370                 OSReport("\n\nTexture Select Control\n\n");
371                 break;
372         }
373     }
374     if(CurrentControl == 0)
375     {
376          // Move camera
377         if(buttons & PAD_BUTTON_Y)
378         {
379             CameraLocScale *= .95F;
380             if(CameraLocScale < 0.001F)
381                 CameraLocScale = 0.001F;
382         }
383         if(buttons & PAD_BUTTON_A)
384             CameraLocScale *= 1.05F;
385 
386         // Rotate camera
387         if(stickX || stickY)
388         {
389             if(stickX)
390              {
391                 if(stickX > 0)
392                     MTXRotAxisDeg(rot, &CamY, 3.0F);
393                 else
394                     MTXRotAxisDeg(rot, &CamY, -3.0F);
395 
396                 MTXMultVec(rot, &CamX, &CamX);
397                 MTXMultVec(rot, &CamZ, &CamZ);
398             }
399 
400             if(stickY)
401             {
402                 if(stickY > 0)
403                     MTXRotAxisDeg(rot, &CamX, 3.0F);
404                 else
405                     MTXRotAxisDeg(rot, &CamX, -3.0F);
406 
407                 MTXMultVec(rot, &CamY, &CamY);
408                 MTXMultVec(rot, &CamZ, &CamZ);
409             }
410         }
411     }
412     else if(CurrentControl == 1)
413     {
414         // Rotate light
415         if(stickX || stickY)
416         {
417             if(stickX)
418              {
419                 if(stickX > 0)
420                     MTXRotAxisDeg(rot, &CamY, 3.0F);
421                 else
422                     MTXRotAxisDeg(rot, &CamY, -3.0F);
423 
424                 MTXMultVec(rot, &LightX, &LightX);
425                 MTXMultVec(rot, &LightY, &LightY);
426                 MTXMultVec(rot, &LightZ, &LightZ);
427             }
428 
429             if(stickY)
430             {
431                 if(stickY > 0)
432                     MTXRotAxisDeg(rot, &CamX, 3.0F);
433                 else
434                     MTXRotAxisDeg(rot, &CamX, -3.0F);
435 
436                 MTXMultVec(rot, &LightX, &LightX);
437                 MTXMultVec(rot, &LightY, &LightY);
438                 MTXMultVec(rot, &LightZ, &LightZ);
439             }
440         }
441         if(buttons & PAD_BUTTON_Y)
442         {
443             distance *= .95F;
444             if(distance > -0.001F)
445                 distance = -0.001F;
446         }
447         if(buttons & PAD_BUTTON_A)
448             distance *= 1.05F;
449     }
450     else if(CurrentControl == 2)
451     {
452         if(stickY > 0)
453         {
454             xmax *= .95F;
455             if(xmax < 0.0001F)
456                 xmax = 0.0001F;
457             ymin = -xmax;
458             ymax = xmax;
459             xmin = -xmax;
460         }
461         if(stickY < 0)
462         {
463             xmax *= 1.05F;
464             ymin = -xmax;
465             ymax = xmax;
466             xmin = -xmax;
467         }
468     }
469     else if(CurrentControl == 3)
470     {
471         if(downs & PAD_BUTTON_B)
472         {
473             CurrentModel ++;
474             if(CurrentModel > 6)
475                 CurrentModel = 0;
476         }
477     }
478     else if(CurrentControl == 4)
479     {
480         if(downs & PAD_BUTTON_B)
481         {
482             CurrentTexture ++;
483             if(CurrentTexture > 1)
484                 CurrentTexture = 0;
485             switch(CurrentTexture)
486             {
487                 case 1:
488                     CurrentTevMode = GX_MODULATE;
489                     break;
490                 case 0:
491                     CurrentTevMode = GX_DECAL;
492                     break;
493             }
494             tdp = TPLGet(tpl, CurrentTexture);
495 
496             GXInitTexObj(&to,
497                  tdp->textureHeader->data,
498                  tdp->textureHeader->width,
499                  tdp->textureHeader->height,
500                  (GXTexFmt)tdp->textureHeader->format,
501                  GX_CLAMP,
502                  GX_CLAMP,
503                  GX_FALSE);
504 
505             GXInitTexObjLOD(&to,
506                     tdp->textureHeader->minFilter,
507                     tdp->textureHeader->magFilter,
508                     tdp->textureHeader->minLOD,
509                     tdp->textureHeader->maxLOD,
510                     tdp->textureHeader->LODBias,
511                     GX_FALSE,
512                     tdp->textureHeader->edgeLODEnable,
513                     GX_ANISO_1);
514 
515             GXLoadTexObj(&to, GX_TEXMAP0);
516         }
517     }
518 
519     MakeModelMtx(CamX, CamY, CamZ, v);  // Make a new model matrix
520     MTXTranspose(v, v);
521     MTXTrans(rot, 0.0F, 0.0F, -8.0F * CameraLocScale);
522     MTXConcat(rot, v, v);
523 
524     MakeModelMtx(LightX, LightY, LightZ, lv);   // Make a new model matrix
525     MTXTranspose(lv, lv);
526     MTXTrans(rot, 0.0F, 0.0F, distance);
527     MTXConcat(rot, lv, lv);
528     TextureLightInit(lv);
529     MTXInverse(lv, lv);
530 
531 }
532 
DrawFrust(void)533 static void DrawFrust ( void )
534 {
535     float t = ffar / nnear;
536     Mtx mv;
537 
538     MTXConcat(v, lv, mv);
539     GXLoadPosMtxImm(mv, GX_PNMTX0);
540 
541     GXBegin(GX_LINESTRIP, GX_VTXFMT0, 17);
542 
543         GXPosition3f32(xmin, ymin, -nnear); //n0
544         GXColor4u8(255, 255, 0, 255);
545 
546         GXPosition3f32(xmax, ymin, -nnear);  //n1
547         GXColor4u8(255, 255, 0, 255);
548 
549         GXPosition3f32(xmax, ymax, -nnear);  //n2
550         GXColor4u8(255, 255, 0, 255);
551 
552         GXPosition3f32(xmin, ymax, -nnear);  //n3
553         GXColor4u8(255, 255, 0, 255);
554 
555         GXPosition3f32(xmin * t, ymax * t, -ffar);  //f3
556         GXColor4u8(255, 255, 0, 255);
557 
558         GXPosition3f32(xmax * t, ymax * t, -ffar);  //f2
559         GXColor4u8(255, 255, 0, 255);
560 
561         GXPosition3f32(xmax * t, ymin * t, -ffar);  //f1
562         GXColor4u8(255, 255, 0, 255);
563 
564         GXPosition3f32(xmin * t, ymin * t, -ffar);  //f0
565         GXColor4u8(255, 255, 0, 255);
566 
567         GXPosition3f32(xmin, ymin, -nnear); //n0
568         GXColor4u8(255, 255, 0, 255);
569 
570         GXPosition3f32(xmax, ymin, -nnear);  //n1
571         GXColor4u8(255, 255, 0, 255);
572 
573         GXPosition3f32(xmax * t, ymin * t, -ffar);  //f1
574         GXColor4u8(255, 255, 0, 255);
575 
576         GXPosition3f32(xmin * t, ymin * t, -ffar);  //f0
577         GXColor4u8(255, 255, 0, 255);
578 
579         GXPosition3f32(xmin * t, ymax * t, -ffar);  //f3
580         GXColor4u8(255, 255, 0, 255);
581 
582         GXPosition3f32(xmax * t, ymax * t, -ffar);  //f2
583         GXColor4u8(255, 255, 0, 255);
584 
585         GXPosition3f32(xmax, ymax, -nnear);  //n2
586         GXColor4u8(255, 255, 0, 255);
587 
588         GXPosition3f32(xmin, ymax, -nnear);  //n3
589         GXColor4u8(255, 255, 0, 255);
590 
591         GXPosition3f32(xmin, ymin, -nnear); //n0
592         GXColor4u8(255, 255, 0, 255);
593 
594     GXEnd();
595 }
596 
TextureLightInit(Mtx rot)597 static void TextureLightInit ( Mtx rot )
598 {
599     Mtx proj;
600     Mtx mv;
601 
602     MTXLightFrustum(proj, ymin, ymax, xmin, xmax, nnear,
603                 0.5F, 0.5F, 0.5F, 0.5F);
604 
605     MTXConcat(rot, m, mv);
606 
607     MTXConcat(proj, mv, proj);
608 
609     GXLoadTexMtxImm(proj, GX_TEXMTX0, GX_MTX3x4);
610 }
611 
612 /*===========================================================================*/
613