1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin/Revolution gx demo
3   File:     tev-complex.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    tev-complex
15        complex multi-texture example
16  *---------------------------------------------------------------------------*/
17 
18 
19 /*---------------------------------------------------------------------------*
20    Header files
21  *---------------------------------------------------------------------------*/
22 #include <demo.h>
23 #include <math.h>
24 
25 /*---------------------------------------------------------------------------*
26    Macro definitions
27  *---------------------------------------------------------------------------*/
28 #define MAX_TEXMAPS    8
29 #define MAX_TEVSTAGES  8
30 #define MAX_TEXCOORDS  8
31 #define MAX_CHANNELS   2
32 
33 #define MODEL_DIV0     32
34 #define MODEL_DIV1     16
35 
36 #define BUMP_SCALE     0x50
37 #define REFLEX_SCALE   0x70
38 #define DIFFUSE_BASE   0xB0
39 #define SPECULAR_BASE  0x90
40 
41 #define PI    3.14159265F
42 #define PI_2  6.28318531F
43 
44 #define Clamp(val,min,max) \
45     ((val) = (((val) < (min)) ? (min) : ((val) > (max)) ? (max) : (val)))
46 
47 /*---------------------------------------------------------------------------*
48    Structure definitions
49  *---------------------------------------------------------------------------*/
50 // for camera
51 typedef struct
52 {
53     Vec    location;
54     Vec    up;
55     Vec    target;
56     f32    left;
57     f32    top;
58     f32    znear;
59     f32    zfar;
60 } CameraConfig;
61 
62 typedef struct
63 {
64     CameraConfig  cfg;
65     Mtx           view;
66     Mtx44         proj;
67 } MyCameraObj;
68 
69 // for lighting
70 typedef struct
71 {
72     GXLightObj  lobj;
73     s32         theta;
74     s32         phi;
75 } MyLightCtrlObj;
76 
77 // for TEV stage control
78 typedef struct
79 {
80     GXTexMapID     texMap;
81     GXTexCoordID   texCoord;
82     GXChannelID    channel;
83     GXTevColorArg  colArgs[4];
84     GXTevOp        colOp;
85     GXTevBias      colBias;
86     GXTevScale     colScale;
87     GXBool         colClamp;
88     GXTevRegID     colOut;
89     GXTevAlphaArg  alpArgs[4];
90     GXTevOp        alpOp;
91     GXTevBias      alpBias;
92     GXTevScale     alpScale;
93     GXBool         alpClamp;
94     GXTevRegID     alpOut;
95 } MyTevStgObj;
96 
97 // for Texture coord generation
98 typedef struct
99 {
100     GXTexGenType   func;
101     GXTexGenSrc    src;
102     GXTexMtx       mt;
103 } MyTexGenObj;
104 
105 // for multi-texture shading configuration
106 typedef struct
107 {
108     u8             numTevStages;
109     u8             numTexMaps;
110     u8             numTexCoords;
111     u8             numChannels;
112     GXTexObj*      texMapArray;
113     MyTexGenObj*   texGenArray;
114     MyTevStgObj*   tevStgArray;
115     GXColor        tevRegColor[3];
116 } MyMTConfig;
117 
118 // for model
119 typedef struct
120 {
121     Mtx            rot;
122     f32            scale;
123     u32            numDiv0;
124     u32            numDiv1;
125     s16*           posArray;
126     s16*           nrmArray;
127     s16*           tcdArray;
128 } MyModelObj;
129 
130 // for entire scene control
131 typedef struct
132 {
133     MyCameraObj    cam;
134     MyLightCtrlObj lightCtrl;
135     MyMTConfig*    mtConfig;
136     MyModelObj     model;
137     u16            viewWidth;
138     u16            viewHeight;
139 } MySceneCtrlObj;
140 
141 /*---------------------------------------------------------------------------*
142    Forward references
143  *---------------------------------------------------------------------------*/
144 void        main                ( void );
145 static void DrawInit            ( MySceneCtrlObj* sc );
146 static void DrawTick            ( MySceneCtrlObj* sc );
147 static void AnimTick            ( MySceneCtrlObj* sc );
148 static void DrawModel           ( MyModelObj* mo );
149 static void CreateModel         ( MyModelObj* mo );
150 static void SetCamera           ( MyCameraObj* cam );
151 static void SetLight            ( MyLightCtrlObj* le, Mtx view );
152 static void SetMultiTex         ( MyMTConfig* mtc );
153 static void PrintIntro          ( void );
154 
155 /*---------------------------------------------------------------------------*
156    Camera configuration
157  *---------------------------------------------------------------------------*/
158 static CameraConfig DefaultCamera =
159 {
160     { 0.0F, 0.0F, 900.0F }, // location
161     { 0.0F, 1.0F,   0.0F }, // up
162     { 0.0F, 0.0F,   0.0F }, // target
163     -320.0F, // left
164     240.0F,  // top
165     400.0F,  // near
166     2000.0F  // far
167 };
168 
169 /*---------------------------------------------------------------------------*
170    Multi-texture configuration data
171  *---------------------------------------------------------------------------*/
172 static MyTexGenObj TexGenConfig0[] =
173 {
174    // TEXCOORD0
175    { GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX0 },
176    // TEXCOORD1
177    { GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX1 },
178    // TEXCOORD2
179    { GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX2 },
180    // TEXCOORD3 (for reflection map)
181    { GX_TG_MTX2x4, GX_TG_NRM, GX_TEXMTX9 },
182    // TEXCOORD4 (for emboss bump)
183    { GX_TG_BUMP0, GX_TG_TEXCOORD1, GX_IDENTITY }
184 };
185 
186 static MyTevStgObj TevStgConfig0[] =
187 {
188     // ------------------------ TEVSTAGE 0 ------------------------
189     // REGPREV(C) = diffuse lit color(COLOR0A0)
190     //            + bump texture(TEXMAP0/TEXCOORD1) * bump scale(REG0(A))
191     {
192         GX_TEXMAP0,      // texture map ID (emboss bump texture)
193         GX_TEXCOORD1,    // texcoord ID
194         GX_COLOR0A0,     // channel ID
195         // Color operation
196         { GX_CC_ZERO, GX_CC_TEXC, GX_CC_A0, GX_CC_RASC },
197         GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV,
198         // Alpha operation
199         { GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO },
200         GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV
201     },
202     // ------------------------ TEVSTAGE 1 ------------------------
203     // REGPREV(C) = REGPREV(C)
204     //            - bump texture(TEXMAP0/TEXCOORD4) * bump scale(REG0(A))
205     {
206         GX_TEXMAP0,      // texture map ID (emboss bump texture)
207         GX_TEXCOORD4,    // texcoord ID (perturbed coordinate)
208         GX_COLOR0A0,     // channel ID
209         // Color operation
210         { GX_CC_ZERO, GX_CC_TEXC, GX_CC_A0, GX_CC_CPREV },
211         GX_TEV_SUB, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV,
212         // Alpha operation
213         { GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO },
214         GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV
215     },
216     // ------------------------ TEVSTAGE 2 ------------------------
217     // REG2(C) = REGPREV(C) * base texture(TEXMAP1/TEXCOORD2)
218     {
219         GX_TEXMAP1,      // texture map ID
220         GX_TEXCOORD2,    // texcoord ID
221         GX_COLOR0A0,     // channel ID
222         // Color operation
223         { GX_CC_ZERO, GX_CC_CPREV, GX_CC_TEXC, GX_CC_ZERO },
224         GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVREG2,
225         // Alpha operation
226         { GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO },
227         GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVREG2
228     },
229     // ------------------------ TEVSTAGE 3 ------------------------
230     // REGPREV(C) = specular lit color(COLOR1A1)
231     //            + reflection map(TEXMAP2/TEXCOORD3) * reflection scale(REG1(A))
232     {
233         GX_TEXMAP2,      // texture map ID
234         GX_TEXCOORD3,    // texcoord ID
235         GX_COLOR1A1,     // channel ID
236         // Color operation
237         { GX_CC_ZERO, GX_CC_A1, GX_CC_TEXC, GX_CC_RASC },
238         GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV,
239         // Alpha operation
240         { GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO },
241         GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV
242     },
243     // ------------------------ TEVSTAGE 4 ------------------------
244     // REGPREV(C) = diffusion map texture(TEXMAP3/TEXCOORD0) * REG2(C)
245     //            + (1 - diffusion map texture) * REGPREV(C)
246     {
247         GX_TEXMAP3,      // texture map ID
248         GX_TEXCOORD0,    // texcoord ID
249         GX_COLOR0A0,     // channel ID
250         // Color operation
251         { GX_CC_CPREV, GX_CC_C2, GX_CC_TEXC, GX_CC_ZERO },
252         GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV,
253         // Alpha operation
254         { GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO },
255         GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV
256     }
257 };
258 
259 static MyMTConfig MultiTexConfig0 =
260 {
261     5,    // number of TEV stages
262     4,    // number of texture maps
263     5,    // number of texture coordinate generators
264     2,    // number of channels
265     NULL,          // texmap array (set in run-time)
266     TexGenConfig0, // texgen array
267     TevStgConfig0, // tevstage array
268     {
269         { 0, 0, 0, BUMP_SCALE    }, // TEVREG0 preset value
270         { 0, 0, 0, REFLEX_SCALE  }, // TEVREG1 preset value
271         { 0, 0, 0, 0 }              // TEVREG2 preset value
272     }
273 };
274 
275 /*---------------------------------------------------------------------------*
276    Other data tables
277  *---------------------------------------------------------------------------*/
278 static GXTevStageID StageIDTbl[MAX_TEVSTAGES] =
279 {
280     GX_TEVSTAGE0, GX_TEVSTAGE1, GX_TEVSTAGE2, GX_TEVSTAGE3,
281     GX_TEVSTAGE4, GX_TEVSTAGE5, GX_TEVSTAGE6, GX_TEVSTAGE7
282 };
283 
284 static GXTexCoordID CoordIDTbl[MAX_TEXCOORDS] =
285 {
286     GX_TEXCOORD0, GX_TEXCOORD1, GX_TEXCOORD2, GX_TEXCOORD3,
287     GX_TEXCOORD4, GX_TEXCOORD5, GX_TEXCOORD6, GX_TEXCOORD7
288 };
289 
290 static GXTexMtx TexMtxIDTbl[MAX_TEXCOORDS] =
291 {
292     GX_TEXMTX0, GX_TEXMTX1, GX_TEXMTX2, GX_TEXMTX3,
293     GX_TEXMTX4, GX_TEXMTX5, GX_TEXMTX6, GX_TEXMTX7
294 };
295 
296 static GXTexMapID MapIDTbl[MAX_TEXMAPS] =
297 {
298     GX_TEXMAP0, GX_TEXMAP1, GX_TEXMAP2, GX_TEXMAP3,
299     GX_TEXMAP4, GX_TEXMAP5, GX_TEXMAP6, GX_TEXMAP7
300 };
301 
302 static GXChannelID ChannelIDTbl[MAX_CHANNELS] =
303 {
304     GX_COLOR0A0, GX_COLOR1A1
305 };
306 
307 /*---------------------------------------------------------------------------*
308    Global variables
309  *---------------------------------------------------------------------------*/
310 static MySceneCtrlObj  SceneCtrl;          // scene control parameters
311 static TPLPalettePtr   MyTplObj = NULL;    // texture palette
312 
313 /*---------------------------------------------------------------------------*
314    Application main loop
315  *---------------------------------------------------------------------------*/
main(void)316 void main ( void )
317 {
318     DEMOInit(NULL);    // Init the OS, game pad, graphics and video.
319 
320     DrawInit(&SceneCtrl);       // Initialize vertex formats and scene parameters.
321 
322     PrintIntro();  // Print demo directions
323 
324     while(!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
325     {
326         DEMOBeforeRender();
327         DrawTick(&SceneCtrl);    // Draw the model.
328         DEMODoneRender();
329         DEMOPadRead();           // Update pad status.
330         AnimTick(&SceneCtrl);    // Update animation.
331     }
332 
333     OSHalt("End of demo");
334 }
335 
336 /*---------------------------------------------------------------------------*
337    Functions
338  *---------------------------------------------------------------------------*/
339 /*---------------------------------------------------------------------------*
340     Name:           DrawInit
341 
342     Description:    Initializes the vertex attribute format and
343                     sets up default scene parameters.
344 
345     Arguments:      sc : pointer to the structure of scene control parameters
346 
347     Returns:        none
348  *---------------------------------------------------------------------------*/
DrawInit(MySceneCtrlObj * sc)349 static void DrawInit( MySceneCtrlObj* sc )
350 {
351     GXRenderModeObj* rmode;
352     u32  i, nt, nd;
353 
354     // set up a vertex attribute
355     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 13);
356     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NBT, GX_NRM_NBT, GX_S16, 13);
357     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S16, 13);
358 
359     // Load TPL file
360     TPLGetPalette(&MyTplObj, "gxTests/tev-03.tpl");
361     nd = MyTplObj->numDescriptors;
362 
363     // Get screen information
364     rmode = DEMOGetRenderModeObj();
365     sc->viewWidth  = rmode->fbWidth;    // Screen Width
366     sc->viewHeight = rmode->efbHeight;  // Screen Height
367 
368 
369     // Default scene parameter settings
370 
371     // camera
372     sc->cam.cfg = DefaultCamera;
373     SetCamera(&sc->cam);   // never changes in this test
374 
375     // light parameters
376     sc->lightCtrl.theta = 30;
377     sc->lightCtrl.phi   = 0;
378 
379     // multi-texturing configuration
380     sc->mtConfig = &MultiTexConfig0;
381 
382     // get texture maps from a texture palette
383     nt = sc->mtConfig->numTexMaps;
384     sc->mtConfig->texMapArray = (GXTexObj*)MEMAllocFromAllocator(&DemoAllocator1, nt * sizeof(GXTexObj));
385     for ( i = 0 ; i < nt ; ++i )
386     {
387         TPLGetGXTexObjFromPalette(
388             MyTplObj,
389             &sc->mtConfig->texMapArray[i],
390             i % nd );
391     }
392 
393     // model
394     MTXRotDeg(sc->model.rot, 'x', 30);
395     sc->model.scale    = 300.0F;
396     sc->model.numDiv0  = MODEL_DIV0;
397     sc->model.numDiv1  = MODEL_DIV1;
398     sc->model.posArray = NULL;
399     sc->model.nrmArray = NULL;
400     sc->model.tcdArray = NULL;
401     CreateModel(&sc->model);
402 }
403 
404 /*---------------------------------------------------------------------------*
405     Name:           DrawTick
406 
407     Description:    Draws the model by using given scene parameters
408 
409     Arguments:      sc : pointer to the structure of scene control parameters
410 
411     Returns:        none
412  *---------------------------------------------------------------------------*/
DrawTick(MySceneCtrlObj * sc)413 static void DrawTick( MySceneCtrlObj* sc )
414 {
415     Mtx  mn = { { 0.5F, 0.0F, 0.0F, -0.5F },   // Fixed matrix
416                 { 0.0F, 0.5F, 0.0F, -0.5F },   // to regularize normal
417                 { 0.0F, 0.0F, 0.5F, -0.5F } }; // texgen
418     Mtx  ms;  // Scaling matrix.
419     Mtx  mr;  // Rotation matrix.
420     Mtx  mv;  // Modelview matrix.
421 
422     // viewport
423     GXSetViewport(0, 0, sc->viewWidth, sc->viewHeight, 0.0F, 1.0F);
424 
425     // modelview matrix
426     //
427     // Binormal and tangent will not be normalized.
428     // So we should consider scale factor of matrix for normal transformation matrix.
429     MTXScale(ms, sc->model.scale, sc->model.scale, sc->model.scale);
430     MTXConcat(sc->cam.view, sc->model.rot, mr);
431     MTXConcat(mr, ms, mv);
432     GXLoadPosMtxImm(mv, GX_PNMTX0);
433 
434     MTXScale(ms, 0.03F, 0.03F, 0.03F);
435     MTXConcat(mr, ms, mv);
436     GXLoadNrmMtxImm(mv, GX_PNMTX0);
437 
438     // texgen matrix
439     MTXConcat(mn, sc->model.rot, mv);
440     GXLoadTexMtxImm(mv, GX_TEXMTX9, GX_MTX2x4);
441     MTXScale(ms, 1.0F, 2.0F, 1.0F);
442     GXLoadTexMtxImm(ms, GX_TEXMTX0, GX_MTX2x4);
443     MTXScale(ms, 5.0F, 5.0F, 5.0F);
444     GXLoadTexMtxImm(ms, GX_TEXMTX1, GX_MTX2x4);
445     MTXScale(ms, 4.0F, 6.0F, 4.0F);
446     GXLoadTexMtxImm(ms, GX_TEXMTX2, GX_MTX2x4);
447 
448     // enable lighting
449     SetLight(&sc->lightCtrl, sc->cam.view);
450 
451     // set multi-texture environment
452     SetMultiTex(sc->mtConfig);
453 
454     // draw the model
455     DrawModel(&sc->model);
456 }
457 
458 /*---------------------------------------------------------------------------*
459     Name:           AnimTick
460 
461     Description:    Changes scene parameters according to the pad status.
462 
463     Arguments:      sc : pointer to the structure of scene control parameters
464 
465     Returns:        none
466  *---------------------------------------------------------------------------*/
AnimTick(MySceneCtrlObj * sc)467 static void AnimTick( MySceneCtrlObj* sc )
468 {
469     Mtx  mrx, mry;
470 
471     // Model Rotation Calculation
472     MTXRotDeg(mry, 'x', -(DEMOPadGetStickY(0) / 24));
473     MTXRotDeg(mrx, 'y',  (DEMOPadGetStickX(0) / 24));
474     MTXConcat(mry, sc->model.rot, sc->model.rot);
475     MTXConcat(mrx, sc->model.rot, sc->model.rot);
476 
477     // Light Position Calculation
478     sc->lightCtrl.theta += (DEMOPadGetSubStickX(0) / 24);
479     sc->lightCtrl.theta %= 360;
480     sc->lightCtrl.phi += (DEMOPadGetSubStickY(0) / 24);
481     Clamp(sc->lightCtrl.phi, -90, 90);
482 }
483 
484 /*---------------------------------------------------------------------------*
485     Name:           CreateModel
486 
487     Description:    Create indexed data array for the model
488                     (a torus with NBT, texcoord)
489 
490     Arguments:      mo : pointer to model object
491 
492     Returns:        none
493  *---------------------------------------------------------------------------*/
CreateModel(MyModelObj * mo)494 static void CreateModel( MyModelObj* mo )
495 {
496 #define  MODEL_R   0.35F
497 #define  SCALE_Q   0x2000
498     u32  size_p, size_n, size_t;
499     u32  cnt_p, cnt_n, cnt_t;
500     s32  i, j;
501     f32  fs, ft, fr;
502 
503     // allocate necessary array memories
504     if ( mo->posArray != NULL )
505         MEMFreeToAllocator(&DemoAllocator1, mo->posArray);
506     if ( mo->nrmArray != NULL )
507         MEMFreeToAllocator(&DemoAllocator1, mo->nrmArray);
508     if ( mo->tcdArray != NULL )
509         MEMFreeToAllocator(&DemoAllocator1, mo->tcdArray);
510 
511     size_p = mo->numDiv0 * mo->numDiv1 * 3;
512     size_n = mo->numDiv0 * mo->numDiv1 * 9;
513     size_t = ( mo->numDiv0 + 1 ) * ( mo->numDiv1 + 1 ) * 2;
514 
515     mo->posArray = (s16*)MEMAllocFromAllocator(&DemoAllocator1, size_p * sizeof(s16));
516     mo->nrmArray = (s16*)MEMAllocFromAllocator(&DemoAllocator1, size_n * sizeof(s16));
517     mo->tcdArray = (s16*)MEMAllocFromAllocator(&DemoAllocator1, size_t * sizeof(s16));
518 
519     // make array data
520     cnt_p = cnt_n = cnt_t = 0;
521     for ( i = 0 ; i <= mo->numDiv0 ; ++i )
522     {
523         for ( j = 0 ; j <= mo->numDiv1 ; ++j )
524         {
525             // Tex coord
526             mo->tcdArray[cnt_t++] = (s16)(i * SCALE_Q / mo->numDiv0);
527             mo->tcdArray[cnt_t++] = (s16)(j * SCALE_Q / mo->numDiv1);
528 
529             if ( i == mo->numDiv0 || j == mo->numDiv1 )
530                 continue;
531 
532             // Position
533             fs = i * PI_2 / mo->numDiv0;
534             ft = j * PI_2 / mo->numDiv1;
535             fr = 1.0F + MODEL_R * cosf(fs);
536 
537             mo->posArray[cnt_p++] = (s16)(fr * cosf(ft) * SCALE_Q);
538             mo->posArray[cnt_p++] = (s16)(fr * sinf(ft) * SCALE_Q);
539             mo->posArray[cnt_p++] = (s16)(MODEL_R * sinf(fs) * SCALE_Q);
540 
541             // Normal
542             mo->nrmArray[cnt_n++] = (s16)(cosf(ft) * cosf(fs) * SCALE_Q);
543             mo->nrmArray[cnt_n++] = (s16)(sinf(ft) * cosf(fs) * SCALE_Q);
544             mo->nrmArray[cnt_n++] = (s16)(sinf(fs) * SCALE_Q);
545 
546             // Bi-normal
547             mo->nrmArray[cnt_n++] = (s16)(-cosf(ft) * sinf(fs) * SCALE_Q);
548             mo->nrmArray[cnt_n++] = (s16)(-sinf(ft) * sinf(fs) * SCALE_Q);
549             mo->nrmArray[cnt_n++] = (s16)( cosf(fs) * SCALE_Q);
550 
551             // Tangent
552             mo->nrmArray[cnt_n++] = (s16)(-sinf(ft) * SCALE_Q);
553             mo->nrmArray[cnt_n++] = (s16)( cosf(ft) * SCALE_Q);
554             mo->nrmArray[cnt_n++] = 0;
555         }
556     }
557 
558     // make sure data is written to main memory
559     DCFlushRange(mo->posArray, size_p * sizeof(s16));
560     DCFlushRange(mo->nrmArray, size_n * sizeof(s16));
561     DCFlushRange(mo->tcdArray, size_t * sizeof(s16));
562 
563 }
564 
565 /*---------------------------------------------------------------------------*
566     Name:           DrawModel
567 
568     Description:    Draws a model by using prepared array data
569 
570     Arguments:      mo : pointer to model object
571 
572     Returns:        none
573  *---------------------------------------------------------------------------*/
DrawModel(MyModelObj * mo)574 static void DrawModel( MyModelObj* mo )
575 {
576     u32  i, j, k, s, t;
577     u16  idx;
578 
579     // set up array pointer
580     GXSetArray(GX_VA_POS,  mo->posArray, sizeof(s16) * 3);
581     GXSetArray(GX_VA_NRM,  mo->nrmArray, sizeof(s16) * 9);
582     GXSetArray(GX_VA_TEX0, mo->tcdArray, sizeof(s16) * 2);
583 
584     // set up vertex descriptors
585     GXClearVtxDesc();
586     GXSetVtxDesc(GX_VA_POS, GX_INDEX16);
587     GXSetVtxDesc(GX_VA_NBT, GX_INDEX16);
588     GXSetVtxDesc(GX_VA_TEX0, GX_INDEX16);
589 
590     for ( i = 0 ; i < mo->numDiv0 ; i++ )
591     {
592         GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT0, (u16)((mo->numDiv1+1)*2));
593             for ( j = 0 ; j <= mo->numDiv1 ; j++ )
594             {
595                 for ( k = 0 ; k <= 1 ; k++ )
596                 {
597                     s = (i + k) % mo->numDiv0;
598                     t = j % mo->numDiv1;
599 
600                     // Position
601                     idx = (u16)(s * mo->numDiv1 + t);
602                     GXPosition1x16(idx);
603 
604                     // Normal-Binormal-Tangent
605                     GXNormal1x16(idx);
606 
607                     // Tex coord
608                     idx = (u16)((i+k) * (mo->numDiv1+1) + j);
609                     GXTexCoord1x16(idx);
610                 }
611             }
612         GXEnd();
613     }
614 }
615 
616 /*---------------------------------------------------------------------------*
617     Name:           SetCamera
618 
619     Description:    Sets view matrix and loads projection matrix into hardware
620 
621     Arguments:      cam : pointer to the MyCameraObj structure
622 
623     Returns:        none
624  *---------------------------------------------------------------------------*/
SetCamera(MyCameraObj * cam)625 static void SetCamera( MyCameraObj* cam )
626 {
627     MTXLookAt(
628         cam->view,
629         &cam->cfg.location,
630         &cam->cfg.up,
631         &cam->cfg.target );
632 
633     MTXFrustum(
634         cam->proj,
635         cam->cfg.top,
636         - (cam->cfg.top),
637         cam->cfg.left,
638         - (cam->cfg.left),
639         cam->cfg.znear,
640         cam->cfg.zfar );
641     GXSetProjection(cam->proj, GX_PERSPECTIVE);
642 }
643 
644 /*---------------------------------------------------------------------------*
645     Name:           SetLight
646 
647     Description:    Sets up lights and lighting channel parameters
648 
649     Arguments:      le   : pointer to a MyLightCtrlObj structure
650                     view : view matrix
651 
652     Returns:        none
653  *---------------------------------------------------------------------------*/
SetLight(MyLightCtrlObj * le,Mtx view)654 static void SetLight( MyLightCtrlObj* le, Mtx view )
655 {
656     GXColor litc0 = { 0xC0, 0xC0, 0xC0, 0xC0 };
657     GXColor ambc0 = { 0x40, 0x40, 0x40, 0x40 };
658     GXColor matc0 = { DIFFUSE_BASE, DIFFUSE_BASE, DIFFUSE_BASE, DIFFUSE_BASE };
659     GXColor litc1 = { 0xE0, 0xE0, 0xE0, 0xE0 };
660     GXColor ambc1 = { 0x00, 0x00, 0x00, 0x00 };
661     GXColor matc1 = { SPECULAR_BASE, SPECULAR_BASE, SPECULAR_BASE, SPECULAR_BASE };
662     GXLightObj lo0, lo1;
663     Vec        lpos, ldir;
664     f32        theta, phi;
665 
666     // Light position/direction
667     theta = (f32)le->theta * PI / 180.0F;
668     phi   = (f32)le->phi   * PI / 180.0F;
669     // Direction of specular light
670     ldir.x = - cosf(phi) * sinf(theta);
671     ldir.y = - sinf(phi);
672     ldir.z = - cosf(phi) * cosf(theta);
673     // Position of diffuse light
674     VECScale(&ldir, &lpos, -1000.0F);
675 
676     // Set a diffuse light
677     MTXMultVec(view, &lpos, &lpos);
678     GXInitLightPosv(&lo0, &lpos);
679     GXInitLightColor(&lo0, litc0);
680     GXLoadLightObjImm(&lo0, GX_LIGHT0);
681 
682     // Set a specular light
683     MTXMultVecSR(view, &ldir, &ldir);
684     GXInitSpecularDirv(&lo1, &ldir);
685     GXInitLightShininess(&lo1, 16.0F);
686     GXInitLightColor(&lo1, litc1);
687     GXLoadLightObjImm(&lo1, GX_LIGHT1);
688 
689     // Lighting channel
690     GXSetChanCtrl(
691         GX_COLOR0A0,
692         GX_ENABLE,       // enable channel
693         GX_SRC_REG,      // amb source
694         GX_SRC_REG,      // mat source
695         GX_LIGHT0,       // light mask
696         GX_DF_CLAMP,     //
697         GX_AF_NONE );    // used as diffuse light
698     GXSetChanCtrl(
699         GX_COLOR1A1,
700         GX_ENABLE,       // enable channel
701         GX_SRC_REG,      // amb source
702         GX_SRC_REG,      // mat source
703         GX_LIGHT1,       // light mask
704         GX_DF_NONE,      //
705         GX_AF_SPEC );    // used as specular light
706 
707     // set up ambient/material color
708     GXSetChanAmbColor(GX_COLOR0A0, ambc0);
709     GXSetChanAmbColor(GX_COLOR1A1, ambc1);
710     GXSetChanMatColor(GX_COLOR0A0, matc0);
711     GXSetChanMatColor(GX_COLOR1A1, matc1);
712 }
713 
714 /*---------------------------------------------------------------------------*
715     Name:           SetMultiTex
716 
717     Description:    Set up texture maps, texcoord generators and TEV
718                     for complex multi-texturing.
719 
720     Arguments:      mtc : pointer to a multi-texture configuration structure
721 
722     Returns:        none
723  *---------------------------------------------------------------------------*/
SetMultiTex(MyMTConfig * mtc)724 static void SetMultiTex( MyMTConfig* mtc )
725 {
726     u32  i;
727 
728     ASSERTMSG(mtc->numChannels <= MAX_CHANNELS, "Too much channels\n");
729     ASSERTMSG(mtc->numTexCoords <= MAX_TEXCOORDS, "Too much texcoords\n");
730     ASSERTMSG(mtc->numTexMaps <= MAX_TEXMAPS, "Too much texmaps\n");
731     ASSERTMSG(mtc->numTevStages <= MAX_TEVSTAGES, "Too much tevstages\n");
732 
733     // Number of color channels
734     GXSetNumChans(mtc->numChannels);
735 
736     // Texmaps
737     for ( i = 0 ; i < mtc->numTexMaps ; ++i )
738     {
739         GXLoadTexObj(&mtc->texMapArray[i], MapIDTbl[i]);
740     }
741 
742     // Texcoord generators
743     GXSetNumTexGens(mtc->numTexCoords);
744     for ( i = 0 ; i < mtc->numTexCoords ; ++i )
745     {
746         GXSetTexCoordGen(
747             CoordIDTbl[i],
748             mtc->texGenArray[i].func,
749             mtc->texGenArray[i].src,
750             mtc->texGenArray[i].mt );
751     }
752 
753     // TEV
754     GXSetNumTevStages(mtc->numTevStages);
755     GXSetTevColor(GX_TEVREG0, mtc->tevRegColor[0]);
756     GXSetTevColor(GX_TEVREG1, mtc->tevRegColor[1]);
757     GXSetTevColor(GX_TEVREG2, mtc->tevRegColor[2]);
758 
759     // each TEV stage
760     for ( i = 0 ; i < mtc->numTevStages ; ++i )
761     {
762         // color operations
763         GXSetTevColorIn(
764             StageIDTbl[i],
765             mtc->tevStgArray[i].colArgs[0],
766             mtc->tevStgArray[i].colArgs[1],
767             mtc->tevStgArray[i].colArgs[2],
768             mtc->tevStgArray[i].colArgs[3] );
769         GXSetTevColorOp(
770             StageIDTbl[i],
771             mtc->tevStgArray[i].colOp,
772             mtc->tevStgArray[i].colBias,
773             mtc->tevStgArray[i].colScale,
774             mtc->tevStgArray[i].colClamp,
775             mtc->tevStgArray[i].colOut );
776         GXSetTevAlphaIn(
777             StageIDTbl[i],
778             mtc->tevStgArray[i].alpArgs[0],
779             mtc->tevStgArray[i].alpArgs[1],
780             mtc->tevStgArray[i].alpArgs[2],
781             mtc->tevStgArray[i].alpArgs[3] );
782         GXSetTevAlphaOp(
783             StageIDTbl[i],
784             mtc->tevStgArray[i].alpOp,
785             mtc->tevStgArray[i].alpBias,
786             mtc->tevStgArray[i].alpScale,
787             mtc->tevStgArray[i].alpClamp,
788             mtc->tevStgArray[i].alpOut );
789 
790         // TEV order
791         GXSetTevOrder(
792             StageIDTbl[i],
793             mtc->tevStgArray[i].texCoord,
794             mtc->tevStgArray[i].texMap,
795             mtc->tevStgArray[i].channel );
796     }
797 }
798 
799 /*---------------------------------------------------------------------------*
800     Name:           PrintIntro
801 
802     Description:    Prints the directions on how to use this demo.
803 
804     Arguments:      none
805 
806     Returns:        none
807  *---------------------------------------------------------------------------*/
PrintIntro(void)808 static void PrintIntro( void )
809 {
810     OSReport("\n\n");
811     OSReport("************************************************\n");
812     OSReport("tev-complex: complex multitexture\n");
813     OSReport("************************************************\n");
814     OSReport("to quit hit the menu button\n");
815     OSReport("\n");
816     OSReport("Main Stick   : Rotate the model\n");
817     OSReport("Sub  Stick   : Move Light Position\n");
818     OSReport("************************************************\n\n");
819 }
820 
821 /*============================================================================*/
822