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