1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin/Revolution gx demo
3   File:     tg-light-fix.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    tg-light-fx
15      Some applications by texgen from the normal
16  *---------------------------------------------------------------------------*/
17 
18 
19 /*---------------------------------------------------------------------------*
20    Header files
21  *---------------------------------------------------------------------------*/
22 #include <demo.h>
23 #include <math.h>
24 
25 /*---------------------------------------------------------------------------*
26    Macro definitions
27  *---------------------------------------------------------------------------*/
28 #define PI         3.14159265358979323846F
29 #define NUM_MODES  3
30 
31 #define Clamp(val,min,max) \
32     ((val) = (((val) < (min)) ? (min) : ((val) > (max)) ? (max) : (val)))
33 
34 /*---------------------------------------------------------------------------*
35    Structure definitions
36  *---------------------------------------------------------------------------*/
37 // for camera
38 typedef struct
39 {
40     Vec    location;
41     Vec    up;
42     Vec    target;
43     f32    left;
44     f32    top;
45     f32    znear;
46     f32    zfar;
47 } CameraConfig;
48 
49 typedef struct
50 {
51     CameraConfig  cfg;
52     Mtx           view;
53     Mtx44         proj;
54 } MyCameraObj;
55 
56 // for lighting
57 typedef struct
58 {
59     GXColor     lightColor;
60     GXColor     ambColor;
61     GXColor     matColor;
62 } MyColorEnvObj;
63 
64 typedef struct
65 {
66     GXLightObj     lobj;
67     s32            theta;
68     s32            phi;
69     GXBool         mark;
70     MyColorEnvObj  colorEnv;
71 } MyLightObj;
72 
73 // for entire scene control
74 typedef struct
75 {
76     MyCameraObj    cam;
77     MyLightObj     light;
78     GXTexObj       texture[NUM_MODES];
79     f32            tune[NUM_MODES];
80     Mtx            modelCtrl;
81     u32            mode;
82 } MySceneCtrlObj;
83 
84 /*---------------------------------------------------------------------------*
85    Forward references
86  *---------------------------------------------------------------------------*/
87 void        main            ( void );
88 static void DrawInit        ( MySceneCtrlObj* sc );
89 static void DrawTick        ( MySceneCtrlObj* sc );
90 static void AnimTick        ( MySceneCtrlObj* sc );
91 static void DrawLightMark   ( void );
92 static void SetCamera       ( MyCameraObj* cam );
93 static void SetLight        ( MyLightObj* light, Mtx view );
94 static void DisableLight    ( void );
95 static void SetTexGenMtx0   ( MySceneCtrlObj* sc );
96 static void SetTexGenMtx1   ( MySceneCtrlObj* sc );
97 static void SetTexGenMtx2   ( MySceneCtrlObj* sc );
98 static void PrintIntro      ( void );
99 
100 /*---------------------------------------------------------------------------*
101    Lighting parameters
102  *---------------------------------------------------------------------------*/
103 MyColorEnvObj MyColors[] ATTRIBUTE_ALIGN(32) =
104 {
105     {
106         { 0xFF, 0xFF, 0xFF, 0xFF }, // Light color 0
107         { 0x80, 0x80, 0x80, 0xFF }, // Ambient 0
108         { 0xFF, 0xFF, 0x00, 0xFF }  // Material 0
109     },
110     {
111         { 0xFF, 0xFF, 0xFF, 0xFF }, // Light color 1
112         { 0x40, 0x40, 0x40, 0xFF }, // Ambient 1
113         { 0x00, 0x00, 0xFF, 0xFF }  // Material 1
114     },
115     {
116         { 0xFF, 0xFF, 0xFF, 0xFF }, // Light color 2
117         { 0x40, 0x40, 0x40, 0xFF }, // Ambient 2
118         { 0xFF, 0x00, 0x20, 0xFF }  // Material 2
119     }
120 };
121 
122 /*---------------------------------------------------------------------------*
123    Test texture data
124  *---------------------------------------------------------------------------*/
125 static u8 TestTexMap0[] ATTRIBUTE_ALIGN(32) =
126 {
127     // IA4 format 16x4
128     0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF0, 0xF0,
129     0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF0, 0xF0,
130     0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF0, 0xF0,
131     0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF0, 0xF0,
132 
133     0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00,
134     0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00,
135     0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00,
136     0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00
137 };
138 
139 static u8 TestTexMap1[] ATTRIBUTE_ALIGN(32) =
140 {
141     // IA8 format 16x4
142     0x00, 0xFF, 0x00, 0xFF, 0x08, 0xFF, 0x20, 0xFF,
143     0x00, 0xFF, 0x00, 0xFF, 0x08, 0xFF, 0x20, 0xFF,
144     0x00, 0xFF, 0x00, 0xFF, 0x08, 0xFF, 0x20, 0xFF,
145     0x00, 0xFF, 0x00, 0xFF, 0x08, 0xFF, 0x20, 0xFF,
146 
147     0x38, 0xFF, 0x50, 0xFF, 0x68, 0xFF, 0x80, 0xFF,
148     0x38, 0xFF, 0x50, 0xFF, 0x68, 0xFF, 0x80, 0xFF,
149     0x38, 0xFF, 0x50, 0xFF, 0x68, 0xFF, 0x80, 0xFF,
150     0x38, 0xFF, 0x50, 0xFF, 0x68, 0xFF, 0x80, 0xFF,
151 
152     0x98, 0xFF, 0xB0, 0xFF, 0xC8, 0xFF, 0xE0, 0xFF,
153     0x98, 0xFF, 0xB0, 0xFF, 0xC8, 0xFF, 0xE0, 0xFF,
154     0x98, 0xFF, 0xB0, 0xFF, 0xC8, 0xFF, 0xE0, 0xFF,
155     0x98, 0xFF, 0xB0, 0xFF, 0xC8, 0xFF, 0xE0, 0xFF,
156 
157     0xF0, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
158     0xF0, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
159     0xF0, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
160     0xF0, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
161 };
162 
163 static u8 TestTexMap2[] ATTRIBUTE_ALIGN(32) =
164 {
165     // IA4 format 16x16
166     0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
167     0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x1F,
168     0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x1F, 0x2F,
169     0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x2F, 0x5F,
170 
171     0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
172     0x1F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
173     0x2F, 0x1F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
174     0x5F, 0x2F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
175 
176 
177     0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x3F, 0x8F,
178     0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x3F, 0x6F, 0xBF,
179     0x0F, 0x0F, 0x1F, 0x2F, 0x3F, 0x6F, 0xAF, 0xDF,
180     0x0F, 0x1F, 0x2F, 0x5F, 0x8F, 0xBF, 0xDF, 0xFF,
181 
182     0x8F, 0x3F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
183     0xBF, 0x6F, 0x3F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
184     0xDF, 0xAF, 0x6F, 0x3F, 0x2F, 0x1F, 0x0F, 0x0F,
185     0xFF, 0xDF, 0xBF, 0x8F, 0x5F, 0x2F, 0x1F, 0x0F,
186 
187 
188     0x0F, 0x1F, 0x2F, 0x5F, 0x8F, 0xBF, 0xDF, 0xFF,
189     0x0F, 0x0F, 0x1F, 0x2F, 0x3F, 0x6F, 0xAF, 0xDF,
190     0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x3F, 0x6F, 0xBF,
191     0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x3F, 0x8F,
192 
193     0xFF, 0xDF, 0xBF, 0x8F, 0x5F, 0x2F, 0x1F, 0x0F,
194     0xDF, 0xAF, 0x6F, 0x3F, 0x2F, 0x1F, 0x0F, 0x0F,
195     0xBF, 0x6F, 0x3F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
196     0x8F, 0x3F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
197 
198 
199     0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x2F, 0x5F,
200     0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x1F, 0x2F,
201     0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x1F,
202     0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
203 
204     0x5F, 0x2F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
205     0x2F, 0x1F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
206     0x1F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
207     0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
208 };
209 
210 static u16 TestTexWidth[NUM_MODES] =
211 {
212     16, 16, 16
213 };
214 
215 static u16 TestTexHeight[NUM_MODES] =
216 {
217     4,  4,  16
218 };
219 
220 static GXTexFmt TestTexFormat[NUM_MODES] =
221 {
222     GX_TF_IA4, GX_TF_IA8, GX_TF_IA4
223 };
224 
225 static u8* TestTexData[NUM_MODES] =
226 {
227     TestTexMap0,
228     TestTexMap1,
229     TestTexMap2
230 };
231 
232 /*---------------------------------------------------------------------------*
233    Camera configuration
234  *---------------------------------------------------------------------------*/
235 static CameraConfig DefaultCamera =
236 {
237     { 0.0F, 0.0F, 2500.0F }, // location
238     { 0.0F, 1.0F,    0.0F }, // up
239     { 0.0F, 0.0F,    0.0F }, // target
240     -320.0F, // left
241     240.0F,  // top
242     1000.0F, // near
243     5000.0F  // far
244 };
245 
246 /*---------------------------------------------------------------------------*
247    Global variables
248  *---------------------------------------------------------------------------*/
249 static MySceneCtrlObj  SceneCtrl;    // scene control parameters
250 
251 /*---------------------------------------------------------------------------*
252    Application main loop
253  *---------------------------------------------------------------------------*/
main(void)254 void main ( void )
255 {
256     DEMOInit(NULL);    // Init the OS, game pad, graphics and video.
257 
258     DrawInit(&SceneCtrl);       // Initialize vertex formats and scene parameters.
259 
260     PrintIntro();  // Print demo directions
261 
262     while(!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
263     {
264 		DEMOBeforeRender();
265         DrawTick(&SceneCtrl);    // Draw the model.
266         DEMODoneRender();
267         DEMOPadRead();           // Update pad status.
268         AnimTick(&SceneCtrl);    // Update animation.
269     }
270 
271     OSHalt("End of demo");
272 }
273 
274 /*---------------------------------------------------------------------------*
275    Functions
276  *---------------------------------------------------------------------------*/
277 /*---------------------------------------------------------------------------*
278     Name:           DrawInit
279 
280     Description:    Initializes the vertex attribute format, texture and
281                     default scene parameters.
282 
283     Arguments:      sc : pointer to the structure of scene control parameters
284 
285     Returns:        none
286  *---------------------------------------------------------------------------*/
DrawInit(MySceneCtrlObj * sc)287 static void DrawInit( MySceneCtrlObj* sc )
288 {
289     GXColor bgColor = { 0x40, 0x40, 0x40, 0xFF };
290     u32     i;
291 
292     GXSetCopyClear(bgColor, 0xFFFFFF);
293 
294     // set up a vertex attribute
295     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
296     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
297     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
298 
299     // textures
300     for ( i = 0 ; i < NUM_MODES ; ++i )
301     {
302         GXInitTexObj(
303             &sc->texture[i],
304             TestTexData[i],
305             TestTexWidth[i],
306             TestTexHeight[i],
307             TestTexFormat[i],
308             GX_CLAMP, // s
309             GX_CLAMP, // t
310             GX_FALSE );
311         GXInitTexObjLOD(
312             &sc->texture[i],
313             GX_LINEAR,
314             GX_LINEAR,
315             0,
316             0,
317             0,
318             GX_FALSE,
319             GX_FALSE,
320             GX_ANISO_1 );
321     }
322 
323 
324     // Default scene parameter settings
325 
326     // camera
327     sc->cam.cfg = DefaultCamera;
328     SetCamera(&sc->cam);   // never changes in this test
329 
330     // light parameters
331     sc->light.theta = 0;
332     sc->light.phi   = 0;
333     sc->light.mark  = GX_FALSE;
334 
335     // tuning parameters
336     for ( i = 0 ; i < NUM_MODES ; ++i )
337     {
338         sc->tune[i] = 0.5F;
339     }
340 
341     // mode
342     sc->mode = 0;
343 
344     // model control matrix
345     MTXIdentity(sc->modelCtrl);
346 }
347 
348 /*---------------------------------------------------------------------------*
349     Name:           DrawTick
350 
351     Description:    Draws the model by using given scene parameters
352 
353     Arguments:      sc : pointer to the structure of scene control parameters
354 
355     Returns:        none
356  *---------------------------------------------------------------------------*/
DrawTick(MySceneCtrlObj * sc)357 static void DrawTick( MySceneCtrlObj* sc )
358 {
359     Mtx  mv, mvi, mr, ms, mm;
360 
361     // enable lighting
362     sc->light.colorEnv = MyColors[sc->mode];
363     SetLight(&sc->light, sc->cam.view);
364     // set texture environments
365     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
366     GXSetTevOp(GX_TEVSTAGE0, GX_DECAL);
367     GXSetNumTexGens(1);
368 	GXSetNumChans(1);
369     GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_NRM, GX_TEXMTX0);
370     GXLoadTexObj(&sc->texture[sc->mode], GX_TEXMAP0);
371 
372     // set texture coord generation matrix
373     switch ( sc->mode )
374     {
375       case 0:
376         SetTexGenMtx0(sc);
377         break;
378       case 1:
379         SetTexGenMtx1(sc);
380         break;
381       case 2:
382         SetTexGenMtx2(sc);
383         break;
384     }
385 
386     // draw a model
387     MTXConcat(sc->cam.view, sc->modelCtrl, mm);
388     MTXInverse(mm, mvi);
389     MTXTranspose(mvi, mv);
390     GXLoadNrmMtxImm(mv, GX_PNMTX0);
391 
392     MTXScale(ms, 400.0F, 400.0F, 400.0F);
393     MTXConcat(mm, ms, mv);
394     GXLoadPosMtxImm(mv, GX_PNMTX0);
395     GXDrawTorus(0.20F, 16, 32);
396 
397     MTXScale(ms, 200.0F, 200.0F, 200.0F);
398     MTXConcat(mm, ms, mv);
399     GXLoadPosMtxImm(mv, GX_PNMTX0);
400     GXDrawSphere1(3);
401 
402 
403     if ( sc->light.mark )
404     {
405         // disable lighting
406         DisableLight();
407         // set texture environments
408         GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
409         GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
410         GXSetNumTexGens(0);
411 
412         // draw a light mark
413         MTXRotDeg(mr, 'y', sc->light.theta);
414         MTXConcat(sc->cam.view, mr, mv);
415         MTXRotDeg(mr, 'x', - sc->light.phi);
416         MTXConcat(mv, mr, mv);
417         GXLoadPosMtxImm(mv, GX_PNMTX0);
418         DrawLightMark();
419     }
420 }
421 
422 /*---------------------------------------------------------------------------*
423     Name:           AnimTick
424 
425     Description:    Changes scene parameters according to the pad status.
426 
427     Arguments:      sc : pointer to the structure of scene control parameters
428 
429     Returns:        none
430  *---------------------------------------------------------------------------*/
AnimTick(MySceneCtrlObj * sc)431 static void AnimTick( MySceneCtrlObj* sc )
432 {
433     Mtx  mrx, mry;
434     u16  button, down;
435     u32  pr = 0;
436 
437     // PAD
438     button = DEMOPadGetButton(0);
439     down   = DEMOPadGetButtonDown(0);
440 
441     // Light Position Calculation
442     sc->light.theta += ( DEMOPadGetStickX(0) / 24 );
443     sc->light.theta = sc->light.theta % 360;
444 
445     sc->light.phi += ( DEMOPadGetStickY(0) / 24 );
446     Clamp(sc->light.phi, -90, 90);
447 
448 
449     // Model Rotation Calculation
450     MTXRotDeg(mry, 'x', -(f32)DEMOPadGetSubStickY(0) / 24.0F);
451     MTXRotDeg(mrx, 'y', (f32)DEMOPadGetSubStickX(0) / 24.0F);
452     MTXConcat(mry, sc->modelCtrl, sc->modelCtrl);
453     MTXConcat(mrx, sc->modelCtrl, sc->modelCtrl);
454 
455 
456     // Hide light direction mark
457     if ( button & PAD_BUTTON_B )
458     {
459         sc->light.mark = GX_FALSE;
460     }
461     else
462     {
463         sc->light.mark = GX_TRUE;
464     }
465 
466     // Tuning parameters
467     if ( down & PAD_TRIGGER_L )
468     {
469         sc->tune[sc->mode] -= 0.1F;
470     }
471     if ( down & PAD_TRIGGER_R )
472     {
473         sc->tune[sc->mode] += 0.1F;
474     }
475     Clamp(sc->tune[sc->mode], 0.0F, 1.0F);
476 
477     // change mode
478     if ( down & PAD_BUTTON_A )
479     {
480         sc->mode = ( sc->mode + 1 ) % NUM_MODES;
481     }
482 
483 }
484 
485 /*---------------------------------------------------------------------------*
486     Name:           DrawLightMark
487 
488     Description:    Draws a mark which shows position of the light.
489 
490     Arguments:      none
491 
492     Returns:        none
493  *---------------------------------------------------------------------------*/
DrawLightMark(void)494 static void DrawLightMark( void )
495 {
496     // sets up vertex descriptors
497     GXClearVtxDesc();
498     GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
499     GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
500 
501     GXBegin(GX_LINES, GX_VTXFMT0, 8);
502         GXPosition3f32(500.0F, 500.0F, -500.0F);
503         GXColor4u8(0, 255, 255, 255);
504         GXPosition3f32(0.0F, 0.0F, 1000.0F);
505         GXColor4u8(0, 255, 255, 255);
506 
507         GXPosition3f32(500.0F, -500.0F, -500.0F);
508         GXColor4u8(0, 255, 255, 255);
509         GXPosition3f32(0.0F, 0.0F, 1000.0F);
510         GXColor4u8(0, 255, 255, 255);
511 
512         GXPosition3f32(-500.0F, 500.0F, -500.0F);
513         GXColor4u8(0, 255, 255, 255);
514         GXPosition3f32(0.0F, 0.0F, 1000.0F);
515         GXColor4u8(0, 255, 255, 255);
516 
517         GXPosition3f32(-500.0F, -500.0F, -500.0F);
518         GXColor4u8(0, 255, 255, 255);
519         GXPosition3f32(0.0F, 0.0F, 1000.0F);
520         GXColor4u8(0, 255, 255, 255);
521     GXEnd();
522 }
523 
524 /*---------------------------------------------------------------------------*
525     Name:           SetCamera
526 
527     Description:    Sets view matrix and loads projection matrix into hardware
528 
529     Arguments:      cam : pointer to the MyCameraObj structure
530 
531     Returns:        none
532  *---------------------------------------------------------------------------*/
SetCamera(MyCameraObj * cam)533 static void SetCamera( MyCameraObj* cam )
534 {
535     MTXLookAt(
536         cam->view,
537         &cam->cfg.location,
538         &cam->cfg.up,
539         &cam->cfg.target );
540 
541     MTXFrustum(
542         cam->proj,
543         cam->cfg.top,
544         - (cam->cfg.top),
545         cam->cfg.left,
546         - (cam->cfg.left),
547         cam->cfg.znear,
548         cam->cfg.zfar );
549     GXSetProjection(cam->proj, GX_PERSPECTIVE);
550 }
551 
552 /*---------------------------------------------------------------------------*
553     Name:           SetLight
554 
555     Description:    Sets up lights and lighting channel parameters
556 
557     Arguments:      light : pointer to a MyLightObj structure
558                     view  : view matrix
559 
560     Returns:        none
561  *---------------------------------------------------------------------------*/
SetLight(MyLightObj * light,Mtx view)562 static void SetLight( MyLightObj* light, Mtx view )
563 {
564     Vec lpos;
565     f32 theta, phi;
566 
567     // Light Position
568     theta = (f32)light->theta * PI / 180.0F;
569     phi   = (f32)light->phi   * PI / 180.0F;
570     lpos.x = 1000.0F * cosf(phi) * sinf(theta);
571     lpos.y = 1000.0F * sinf(phi);
572     lpos.z = 1000.0F * cosf(phi) * cosf(theta);
573 
574     // Convert light position into view space
575     MTXMultVec(view, &lpos, &lpos);
576 
577     GXInitLightPos(&light->lobj, lpos.x, lpos.y, lpos.z);
578     GXInitLightColor(&light->lobj, light->colorEnv.lightColor);
579     GXLoadLightObjImm(&light->lobj, GX_LIGHT0);
580 
581     // Lighting channel
582     GXSetChanCtrl(
583         GX_COLOR0A0,
584         GX_ENABLE,   // enable channel
585         GX_SRC_REG,  // amb source
586         GX_SRC_REG,  // mat source
587         GX_LIGHT0,   // light mask
588         GX_DF_CLAMP, // diffuse function
589         GX_AF_NONE);
590     // set up ambient color
591     GXSetChanAmbColor(GX_COLOR0A0, light->colorEnv.ambColor);
592     // set up material color
593     GXSetChanMatColor(GX_COLOR0A0, light->colorEnv.matColor);
594 
595 }
596 
597 /*---------------------------------------------------------------------------*
598     Name:           DisableLight
599 
600     Description:    Disables lighting
601 
602     Arguments:      none
603 
604     Returns:        none
605  *---------------------------------------------------------------------------*/
DisableLight(void)606 static void DisableLight( void )
607 {
608     GXSetChanCtrl(
609         GX_COLOR0A0,
610         GX_DISABLE,  // disable channel
611         GX_SRC_VTX,  // amb source
612         GX_SRC_VTX,  // mat source
613         GX_LIGHT0,   // light mask
614         GX_DF_NONE,  // diffuse function
615         GX_AF_NONE);
616 }
617 
618 /*---------------------------------------------------------------------------*
619     Name:           SetTexGenMtx0
620 
621     Description:    Calculate and set texture coord generation matrix
622                     for drawing pseudo outline.
623 
624     Arguments:      sc : a pointer to MySceneCtrlObj structure
625 
626     Returns:        none
627  *---------------------------------------------------------------------------*/
SetTexGenMtx0(MySceneCtrlObj * sc)628 static void SetTexGenMtx0( MySceneCtrlObj* sc )
629 {
630     Mtx  mt, ms;
631     f32  scale;
632 
633     // Project object normals from side view
634     MTXRotDeg(mt, 'Y', -90);
635     MTXConcat(mt, sc->cam.view, mt);
636     MTXConcat(mt, sc->modelCtrl, mt);
637     MTXInverse(mt, ms);
638     MTXTranspose(ms, mt);
639 
640     // Scaling and bias
641     scale = 0.5F - 0.25F * sc->tune[sc->mode];
642     MTXScale(ms, scale, 0.5F, 1.0F);
643     MTXConcat(ms, mt, mt);
644     MTXTrans(ms, 0.5F, 0.5F, 0.0F);
645     MTXConcat(ms, mt, mt);
646 
647     // Load into the hardware
648     GXLoadTexMtxImm(mt, GX_TEXMTX0, GX_MTX2x4);
649 }
650 
651 /*---------------------------------------------------------------------------*
652     Name:           SetTexGenMtx1
653 
654     Description:    Calculate and set texture coord generation matrix
655                     for specular highlight (1D lookup version).
656 
657     Arguments:      sc : a pointer to MySceneCtrlObj structure
658 
659     Returns:        none
660  *---------------------------------------------------------------------------*/
SetTexGenMtx1(MySceneCtrlObj * sc)661 static void SetTexGenMtx1( MySceneCtrlObj* sc )
662 {
663     Mtx  mt, ms;
664     f32  theta, phi, scale;
665     Vec  vview = { 0.0F, 0.0F, -1.0F };
666     Vec  vlight, vhalf;
667 
668     // Calculate light direction
669     theta = sc->light.theta * PI / 180.0F;
670     phi   = sc->light.phi   * PI / 180.0F;
671     vlight.x = - cosf(phi) * sinf(theta);
672     vlight.y = - sinf(phi);
673     vlight.z = - cosf(phi) * cosf(theta);
674 
675     // Convert light direction into view space
676     MTXMultVecSR(sc->cam.view, &vlight, &vlight);
677 
678     // Calculate the half angle
679     VECHalfAngle(&vlight, &vview, &vhalf);
680 
681     // Modelview translation
682     MTXConcat(sc->cam.view, sc->modelCtrl, mt);
683     MTXInverse(mt, ms);
684     MTXTranspose(ms, mt);
685 
686     // Make a matrix which generates s-coord by half angle.
687     // actually generated coord is 1D
688     MTXIdentity(ms);
689     MTXRowCol(ms, 0, 0) = vhalf.x;
690     MTXRowCol(ms, 0, 1) = vhalf.y;
691     MTXRowCol(ms, 0, 2) = vhalf.z;
692     MTXConcat(ms, mt, mt);
693 
694     // Scaling and bias
695     scale = 14.0F + 20.0F * sc->tune[sc->mode];
696     MTXScale(ms, scale, 1.0F, 1.0F);
697     MTXConcat(ms, mt, mt);
698     MTXTrans(ms,  1.0F - scale, 0.0F, 0.0F);
699     MTXConcat(ms, mt, mt);
700 
701     // Load into the hardware
702     GXLoadTexMtxImm(mt, GX_TEXMTX0, GX_MTX2x4);
703 }
704 
705 /*---------------------------------------------------------------------------*
706     Name:           SetTexGenMtx2
707 
708     Description:    Calculate and set texture coord generation matrix
709                     for specular highlight (2D lookup version).
710 
711     Arguments:      sc : a pointer to MySceneCtrlObj structure
712 
713     Returns:        none
714  *---------------------------------------------------------------------------*/
SetTexGenMtx2(MySceneCtrlObj * sc)715 static void SetTexGenMtx2( MySceneCtrlObj* sc )
716 {
717     Mtx  mt, mv, ms;
718     f32  theta, phi, scale, dotp, r;
719     Vec  vlight, vhalf, vaxis;
720     Vec  vview = { 0.0F, 0.0F, 1.0F };
721 
722     // Calculate light direction
723     theta = sc->light.theta * PI / 180.0F;
724     phi   = sc->light.phi   * PI / 180.0F;
725     vlight.x = cosf(phi) * sinf(theta);
726     vlight.y = sinf(phi);
727     vlight.z = cosf(phi) * cosf(theta);
728 
729     // Convert light direction into view space
730     MTXMultVecSR(sc->cam.view, &vlight, &vlight);
731 
732     // Calculate the half angle
733     dotp = VECDotProduct(&vlight, &vview);
734     if ( dotp == -1.0F )
735     {
736         // Singular point ( vview + vlight = 0 )
737         MTXScale(mt, 0.0F, 0.0F, 0.0F); // zero matrix
738 
739         GXLoadTexMtxImm(mt, GX_TEXMTX0, GX_MTX2x4);
740         return;
741     }
742     VECHalfAngle(&vlight, &vview, &vhalf);
743     // The obtained half-angle vector directs an opposite side
744     vhalf.x = -vhalf.x;
745     vhalf.y = -vhalf.y;
746     vhalf.z = -vhalf.z;
747 
748     // Modelview translation
749     MTXConcat(sc->cam.view, sc->modelCtrl, mv);
750     MTXInverse(mv, ms);
751     MTXTranspose(ms, mv);
752 
753     // Rotation
754     if ( dotp == 1.0F )
755     {
756         MTXIdentity(ms);
757     }
758     else
759     {
760         VECCrossProduct(&vhalf, &vview, &vaxis);  // rotation axis
761         r = acosf(VECDotProduct(&vview, &vhalf)); // rotation amounts
762         MTXRotAxisRad(ms, &vaxis, r);
763     }
764     MTXConcat(ms, mv, mt);
765 
766     // Scaling and bias
767     scale = 2.0F * sc->tune[sc->mode] + 1.5F;
768     MTXScale(ms, scale, scale, 1.0F);
769     MTXConcat(ms, mt, mt);
770     MTXTrans(ms, 0.5F, 0.5F, 0.0F);
771     MTXConcat(ms, mt, mt);
772 
773     // Load into the hardware
774     GXLoadTexMtxImm(mt, GX_TEXMTX0, GX_MTX2x4);
775 }
776 
777 /*---------------------------------------------------------------------------*
778     Name:           PrintIntro
779 
780     Description:    Prints the directions on how to use this demo.
781 
782     Arguments:      none
783 
784     Returns:        none
785  *---------------------------------------------------------------------------*/
PrintIntro(void)786 static void PrintIntro( void )
787 {
788     OSReport("\n\n");
789     OSReport("**********************************************\n");
790     OSReport("tg-light-fx: some applications using texgen\n");
791     OSReport("             from normals\n");
792     OSReport("**********************************************\n");
793     OSReport("to quit hit the start button\n");
794     OSReport("\n");
795     OSReport("Main stick   : Move Light Position\n");
796     OSReport("Sub  stick   : Rotate the Moddel\n");
797     OSReport("L/R Triggers : Tune parameter\n");
798     OSReport("A Button     : Change texgen mode\n");
799     OSReport("B Button     : Hide light direction mark\n");
800     OSReport("**********************************************\n");
801 }
802 
803 /*============================================================================*/
804