1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin GD demo
3   File:     gd-tev-gc.c
4 
5   Copyright 2001 - 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   $Log: gd-tev-gc.c,v $
14   Revision 1.3.70.1  2009/12/08 02:44:59  abe_takehiro
15   Erased warning message
16 
17   Revision 1.3  2006/03/06 09:59:06  kawaset
18   Eliminated warnings.
19 
20   Revision 1.2  2006/02/09 01:17:37  hirose
21   Replaced TEX library calls by TPL library.
22 
23   Revision 1.1  2006/02/08 11:19:43  mitu
24   1st version.
25 
26 
27     3     02/09/06 11:26 Hirose
28     Resolved future time stamp problem.
29 
30     3     10/19/02 6:53p Hirose
31     Changed location of data file.
32 
33     2     10/13/01 2:29a Hirose
34     Fixes due to GDSetTexCoordGen API change.
35 
36     1     10/04/01 2:48p Hirose
37     Initial check in.
38 
39   $NoKeywords: $
40  *---------------------------------------------------------------------------*/
41 /*---------------------------------------------------------------------------*
42    gd-tev
43      Displaylist demo with multitexture shader commands
44      [Main source codr for GAMECUBE exectable]
45  *---------------------------------------------------------------------------*/
46 
47 
48 /*---------------------------------------------------------------------------*
49    Header files
50  *---------------------------------------------------------------------------*/
51 #include <demo.h>
52 #include <math.h>
53 
54 #include "gd-tev.h"
55 
56 /*---------------------------------------------------------------------------*
57    Macro definitions
58  *---------------------------------------------------------------------------*/
59 #define PI    3.14159265F
60 #define PI_2  6.28318531F
61 
62 #define Clamp(val,min,max) \
63     ((val) = (((val) < (min)) ? (min) : ((val) > (max)) ? (max) : (val)))
64 
65 /*---------------------------------------------------------------------------*
66    Structure definitions
67  *---------------------------------------------------------------------------*/
68 // for camera
69 typedef struct
70 {
71     Vec     location;
72     Vec     up;
73     Vec     target;
74     f32     left;
75     f32     top;
76     f32     znear;
77     f32     zfar;
78 } CameraConfig;
79 
80 typedef struct
81 {
82     CameraConfig    cfg;
83     Mtx             view;
84     Mtx44           proj;
85 } MyCameraObj;
86 
87 // for lighting
88 typedef struct
89 {
90     GXLightObj      lobj;
91     s32             theta;
92     s32             phi;
93 } MyLightCtrlObj;
94 
95 typedef struct
96 {
97     void*       dlPtr;
98     u32         dlSize;
99     u32*        plPtr;
100     u32         plSize;
101 } MyDLObj;
102 
103 // for model object
104 typedef struct
105 {
106     s16*        posArray;
107     s16*        nrmArray;
108     s16*        tcdArray;
109     MyDLObj     dl;
110 } MyModelObj;
111 
112 // for entire scene control
113 typedef struct
114 {
115     MyCameraObj     cam;
116     MyLightCtrlObj  lightCtrl;
117     Mtx             modelRot;
118     f32             modelScale;
119     u16             viewWidth;
120     u16             viewHeight;
121 } MySceneCtrlObj;
122 
123 /*---------------------------------------------------------------------------*
124    Forward references
125  *---------------------------------------------------------------------------*/
126 void        main                ( void );
127 
128 static void DrawInit            ( MySceneCtrlObj* sc );
129 static void DrawTick            ( MySceneCtrlObj* sc );
130 static void AnimTick            ( MySceneCtrlObj* sc );
131 static void SetCamera           ( MyCameraObj* cam );
132 static void SetLight            ( MyLightCtrlObj* le, Mtx view );
133 static void PrintIntro          ( void );
134 
135 static void PrepareDL           ( void );
136 static void CreateModelVtxArray ( void );
137 static void PatchShaderDLTCScale( MyDLObj* mdl );
138 
139 
140 /*---------------------------------------------------------------------------*
141    Camera configuration
142  *---------------------------------------------------------------------------*/
143 static CameraConfig DefaultCamera =
144 {
145     { 0.0F, 0.0F, 900.0F }, // location
146     { 0.0F, 1.0F,   0.0F }, // up
147     { 0.0F, 0.0F,   0.0F }, // tatget
148     -320.0F, // left
149     240.0F,  // top
150     400.0F,  // near
151     2000.0F  // far
152 };
153 
154 /*---------------------------------------------------------------------------*
155    Global variables
156  *---------------------------------------------------------------------------*/
157 static MySceneCtrlObj   SceneCtrl;          // scene control parameters
158 static TPLPalettePtr    MyTplObj = NULL;    // texture palette
159 
160 static GXTexObj         MyTexObjs[NUM_TEXTURES];
161 static MyDLObj          ShaderDLs[NUM_SHADERDLS];
162 static MyModelObj       ModelObj;
163 
164 /*---------------------------------------------------------------------------*
165    Application main loop
166  *---------------------------------------------------------------------------*/
main(void)167 void main ( void )
168 {
169     DEMOInit(NULL);  // Init the OS, game pad, graphics and video.
170 
171     DrawInit(&SceneCtrl);       // Initialize vertex formats and scene parameters.
172 
173     PrintIntro();  // Print demo directions
174 
175     while(!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
176     {
177         DEMOBeforeRender();
178         DrawTick(&SceneCtrl);    // Draw the model.
179         DEMODoneRender();
180         DEMOPadRead();           // Update pad status.
181         AnimTick(&SceneCtrl);    // Update animation.
182     }
183 
184     OSHalt("End of demo");
185 }
186 
187 /*---------------------------------------------------------------------------*
188    Functions
189  *---------------------------------------------------------------------------*/
190 /*---------------------------------------------------------------------------*
191     Name:           DrawInit
192 
193     Description:    Initializes the vertex attribute format and
194                     sets up default scene parameters.
195 
196     Arguments:      sc : pointer to the structure of scene control parameters
197 
198     Returns:        none
199  *---------------------------------------------------------------------------*/
DrawInit(MySceneCtrlObj * sc)200 static void DrawInit( MySceneCtrlObj* sc )
201 {
202     GXRenderModeObj* rmode;
203     u32  i, nd;
204 
205     // set up a vertex attribute
206     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, QUANTIZE_SHIFT);
207     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NBT, GX_NRM_NBT, GX_S16, QUANTIZE_SHIFT);
208     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S16, QUANTIZE_SHIFT);
209 
210     // Disable all automatic texcoord scaling settings that
211     // cannot work well with GD display lists.
212     GXSetTexCoordScaleManually(GX_TEXCOORD0, GX_ENABLE, 1, 1);
213     GXSetTexCoordScaleManually(GX_TEXCOORD1, GX_ENABLE, 1, 1);
214     GXSetTexCoordScaleManually(GX_TEXCOORD2, GX_ENABLE, 1, 1);
215     GXSetTexCoordScaleManually(GX_TEXCOORD3, GX_ENABLE, 1, 1);
216     GXSetTexCoordScaleManually(GX_TEXCOORD4, GX_ENABLE, 1, 1);
217     GXSetTexCoordScaleManually(GX_TEXCOORD5, GX_ENABLE, 1, 1);
218     GXSetTexCoordScaleManually(GX_TEXCOORD6, GX_ENABLE, 1, 1);
219     GXSetTexCoordScaleManually(GX_TEXCOORD7, GX_ENABLE, 1, 1);
220 
221 
222     // Get screen information
223     rmode = DEMOGetRenderModeObj();
224     sc->viewWidth  = rmode->fbWidth;    // Screen Width
225     sc->viewHeight = rmode->efbHeight;  // Screen Height
226 
227 
228     // Load TPL file
229     TPLGetPalette(&MyTplObj, "gxTests/tev-03.tpl");
230     nd = MyTplObj->numDescriptors;
231     // get texture maps from a texture palette
232     for ( i = 0 ; i < NUM_TEXTURES ; ++i )
233     {
234         TPLGetGXTexObjFromPalette(MyTplObj, &MyTexObjs[i], i % nd);
235     }
236 
237 
238     // Prepare model display list and shader display lists
239     PrepareDL();
240     CreateModelVtxArray();
241 
242 
243     // Default scene parameter settings
244 
245     // camera
246     sc->cam.cfg = DefaultCamera;
247     SetCamera(&sc->cam);   // never changes in this test
248 
249     // light parameters
250     sc->lightCtrl.theta = 30;
251     sc->lightCtrl.phi   = 0;
252 
253     // model control
254     MTXRotDeg(sc->modelRot, 'x', -30);
255     sc->modelScale = 750.0F;
256 
257 }
258 
259 /*---------------------------------------------------------------------------*
260     Name:           DrawTick
261 
262     Description:    Draws the model by using given scene parameters
263 
264     Arguments:      sc : pointer to the structure of scene control parameters
265 
266     Returns:        none
267  *---------------------------------------------------------------------------*/
268 // Viewport setup
SetWindow(u32 num,u32 wd,u32 ht)269 inline void SetWindow( u32 num, u32 wd, u32 ht )
270 {
271     u32 xorg, yorg;
272     xorg = (num&1) * wd;
273     yorg = ((num>>1)&1) * ht;
274     GXSetScissor(xorg, yorg, wd, ht);
275     GXSetViewport((f32)xorg, (f32)yorg, (f32)wd, (f32)ht, 0.0F, 1.0F);
276 }
277 
DrawTick(MySceneCtrlObj * sc)278 static void DrawTick( MySceneCtrlObj* sc )
279 {
280     Mtx  mn = { { 0.5F, 0.0F, 0.0F, -0.5F },   // Fixed matrix
281                 { 0.0F, 0.5F, 0.0F, -0.5F },   // to regularize normal
282                 { 0.0F, 0.0F, 0.0F,  1.0F } }; // texgen
283     Mtx  ms;  // Scaling matrix.
284     Mtx  mr;  // Rotation matrix.
285     Mtx  mv;  // Modelview matrix.
286     u32  i, vw, vh;
287 
288     // modelview matrix
289     //
290     // Binormal and tangent will not be normalized.
291     // So we should consider scale factor of matrix for normal transformation matrix.
292     MTXScale(ms, sc->modelScale, sc->modelScale, sc->modelScale);
293     MTXConcat(sc->cam.view, sc->modelRot, mr);
294     MTXConcat(mr, ms, mv);
295     GXLoadPosMtxImm(mv, GX_PNMTX0);
296 
297     MTXScale(ms, 0.03F, 0.03F, 0.03F);
298     MTXConcat(mr, ms, mv);
299     GXLoadNrmMtxImm(mv, GX_PNMTX0);
300 
301     // texgen matrices
302     GXLoadTexMtxImm(sc->modelRot, GX_TEXMTX2, GX_MTX3x4);  // for reflection map
303     GXLoadTexMtxImm(mn, GX_PTTEXMTX0, GX_MTX3x4);           //
304     MTXScale(ms, 6.0F, 6.0F, 0.0F);
305     GXLoadTexMtxImm(ms, GX_TEXMTX0, GX_MTX2x4); // for bump map
306     MTXScale(ms, 3.5F, 5.0F, 0.0F);
307     GXLoadTexMtxImm(ms, GX_TEXMTX1, GX_MTX2x4); // for base map
308     MTXScale(ms, 1.0F, 2.0F, 0.0F);
309     GXLoadTexMtxImm(ms, GX_TEXMTX3, GX_MTX2x4); // for gloss map
310 
311     // Lighting
312     SetLight(&sc->lightCtrl, sc->cam.view);
313 
314     // Texmaps
315     for ( i = 0 ; i < NUM_TEXTURES ; ++i )
316     {
317         GXLoadTexObj(&MyTexObjs[i], (GXTexMapID)i);
318     }
319 
320     // Viewport size
321     vw = (u32)(sc->viewWidth / 2);
322     vh = (u32)(sc->viewHeight / 2);
323 
324     // Call display list (shader + model)
325     for ( i = 0 ; i < 4 ; ++i )
326     {
327         SetWindow(i, vw, vh);
328         GXCallDisplayList(ShaderDLs[i].dlPtr, ShaderDLs[i].dlSize);
329         GXCallDisplayList(ModelObj.dl.dlPtr, ModelObj.dl.dlSize);
330     }
331 }
332 
333 /*---------------------------------------------------------------------------*
334     Name:           AnimTick
335 
336     Description:    Changes scene parameters according to the pad status.
337 
338     Arguments:      sc  : pointer to the structure of scene control parameters
339 
340     Returns:        none
341  *---------------------------------------------------------------------------*/
AnimTick(MySceneCtrlObj * sc)342 static void AnimTick( MySceneCtrlObj* sc )
343 {
344     Mtx  mrx, mry;
345 
346     // Model Rotation Calculation
347     MTXRotDeg(mry, 'x', -(DEMOPadGetStickY(0) / 24));
348     MTXRotDeg(mrx, 'y',  (DEMOPadGetStickX(0) / 24));
349     MTXConcat(mry, sc->modelRot, sc->modelRot);
350     MTXConcat(mrx, sc->modelRot, sc->modelRot);
351 
352     // Light Position Calculation
353     sc->lightCtrl.theta += (DEMOPadGetSubStickX(0) / 24);
354     sc->lightCtrl.theta %= 360;
355     sc->lightCtrl.phi += (DEMOPadGetSubStickY(0) / 24);
356     Clamp(sc->lightCtrl.phi, -90, 90);
357 }
358 
359 /*---------------------------------------------------------------------------*
360     Name:           SetCamera
361 
362     Description:    Sets view matrix and loads projection matrix into hardware
363 
364     Arguments:      cam : pointer to the MyCameraObj structure
365 
366     Returns:        none
367  *---------------------------------------------------------------------------*/
SetCamera(MyCameraObj * cam)368 static void SetCamera( MyCameraObj* cam )
369 {
370     MTXLookAt(
371         cam->view,
372         &cam->cfg.location,
373         &cam->cfg.up,
374         &cam->cfg.target );
375 
376     MTXFrustum(
377         cam->proj,
378         cam->cfg.top,
379         - (cam->cfg.top),
380         cam->cfg.left,
381         - (cam->cfg.left),
382         cam->cfg.znear,
383         cam->cfg.zfar );
384     GXSetProjection(cam->proj, GX_PERSPECTIVE);
385 }
386 
387 /*---------------------------------------------------------------------------*
388     Name:           SetLight
389 
390     Description:    Sets up lights and lighting channel parameters
391 
392     Arguments:      le    : pointer to a MyLightCtrlObj structure
393                     view  : view matrix
394 
395     Returns:        none
396  *---------------------------------------------------------------------------*/
SetLight(MyLightCtrlObj * le,Mtx view)397 static void SetLight( MyLightCtrlObj* le, Mtx view )
398 {
399     GXColor litc0 = { 0xC0, 0xC0, 0xC0, 0xC0 };
400     GXColor ambc0 = { 0x40, 0x40, 0x40, 0x40 };
401     GXColor matc0 = { DIFFUSE_BASE, DIFFUSE_BASE, DIFFUSE_BASE, DIFFUSE_BASE };
402     GXColor litc1 = { 0xE0, 0xE0, 0xE0, 0xE0 };
403     GXColor ambc1 = { 0x00, 0x00, 0x00, 0x00 };
404     GXColor matc1 = { SPECULAR_BASE, SPECULAR_BASE, SPECULAR_BASE, SPECULAR_BASE };
405     GXLightObj lo0, lo1;
406     Vec        lpos, ldir;
407     f32        theta, phi;
408 
409     // Light position/direction
410     theta = (f32)le->theta * PI / 180.0F;
411     phi   = (f32)le->phi   * PI / 180.0F;
412     // Direction of specular light
413     ldir.x = - cosf(phi) * sinf(theta);
414     ldir.y = - sinf(phi);
415     ldir.z = - cosf(phi) * cosf(theta);
416     // Position of diffuse light
417     VECScale(&ldir, &lpos, -1000.0F);
418 
419     // Set a diffuse light
420     MTXMultVec(view, &lpos, &lpos);
421     GXInitLightPosv(&lo0, &lpos);
422     GXInitLightColor(&lo0, litc0);
423     GXLoadLightObjImm(&lo0, GX_LIGHT0);
424 
425     // Set a specular light
426     MTXMultVecSR(view, &ldir, &ldir);
427     GXInitSpecularDirv(&lo1, &ldir);
428     GXInitLightShininess(&lo1, 48.0F);
429     GXInitLightColor(&lo1, litc1);
430     GXLoadLightObjImm(&lo1, GX_LIGHT1);
431 
432     // Lighting channel
433     GXSetChanCtrl(GX_COLOR0, GX_ENABLE,         // Diffuse
434                   GX_SRC_REG, GX_SRC_REG,
435                   GX_LIGHT0, GX_DF_CLAMP, GX_AF_NONE);
436     GXSetChanCtrl(GX_COLOR1, GX_ENABLE,         // Specular
437                   GX_SRC_REG, GX_SRC_REG,
438                   GX_LIGHT1, GX_DF_NONE, GX_AF_SPEC);
439     GXSetChanCtrl(GX_ALPHA0, GX_DISABLE,        // Unused
440                   GX_SRC_REG, GX_SRC_REG,
441                   GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE);
442     GXSetChanCtrl(GX_ALPHA1, GX_DISABLE,        // Unused
443                   GX_SRC_REG, GX_SRC_REG,
444                   GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE);
445 
446     // set up ambient/material color
447     GXSetChanAmbColor(GX_COLOR0A0, ambc0);
448     GXSetChanAmbColor(GX_COLOR1A1, ambc1);
449     GXSetChanMatColor(GX_COLOR0A0, matc0);
450     GXSetChanMatColor(GX_COLOR1A1, matc1);
451 }
452 
453 /*---------------------------------------------------------------------------*
454     Name:           PrepareDL
455 
456     Description:    [create mode] Allocate memory for display list and call
457                     the function CreateModelDL to create the display list.
458                     [load mode] Load GDL file from the disc.
459 
460     Arguments:      none
461 
462     Returns:        none
463  *---------------------------------------------------------------------------*/
464 #ifndef LOAD_DL_FROM_FILE
465 static void(*CreateShdDLFunc[NUM_SHADERDLS])() =
466 {
467     CreateShader0DL, CreateShader1DL, CreateShader2DL, CreateShader3DL
468 };
469 #endif
470 
PrepareDL(void)471 static void PrepareDL( void )
472 {
473     u32     i;
474 
475 #ifdef LOAD_DL_FROM_FILE
476     //---------------------------------------------------------
477     // File mode : Read pre-generated GDL file from file
478     //---------------------------------------------------------
479     s32         err;
480     GDGList*    dlArray;
481     GDGList*    plArray;
482     u32         nDls, nPls;
483 
484     err = GDReadDLFile("gddemo/gdTev.gdl", &nDls, &nPls, &dlArray, &plArray);
485 
486     ASSERTMSG( err == 0, "GD file read error.\n" );
487 
488     // Check number of lists.
489     ASSERTMSG( ( nDls == NUM_DLS && nPls == NUM_PLS ),
490                "This data doesn't match requirement of this demo.\n" );
491 
492 
493     OSReport("\nGD file read completed.\n");
494 
495     // Obtain shader display lists.
496     for ( i = 0 ; i < NUM_SHADERDLS ; ++i )
497     {
498         ShaderDLs[i].dlPtr  = dlArray[i].ptr;
499         ShaderDLs[i].dlSize = dlArray[i].byteLength;
500         ShaderDLs[i].plPtr  = plArray[i].ptr;
501         ShaderDLs[i].plSize = plArray[i].byteLength;
502     }
503 
504     // Obtain model display list.
505     ModelObj.dl.dlPtr  = dlArray[i].ptr;
506     ModelObj.dl.dlSize = dlArray[i].byteLength;
507     ModelObj.dl.plPtr  = NULL;
508     ModelObj.dl.plSize = 0;
509 
510 #else
511     //---------------------------------------------------------
512     // Create mode : Create display list in this application
513     //---------------------------------------------------------
514 
515     // Create shader display lists
516     for ( i = 0 ; i < NUM_SHADERDLS ; ++i )
517     {
518         ShaderDLs[i].dlPtr = OSAlloc(SDL_SIZE_MAX);
519         ShaderDLs[i].plPtr = OSAlloc(PL_SIZE_MAX);
520         (*CreateShdDLFunc[i])(ShaderDLs[i].dlPtr, &ShaderDLs[i].dlSize,
521                               ShaderDLs[i].plPtr, &ShaderDLs[i].plSize);
522         OSReport("ShaderDL %d size = %d\n", i, ShaderDLs[i].dlSize);
523     }
524 
525     // Create model display list
526     ModelObj.dl.dlPtr  = OSAlloc(MDL_SIZE_MAX);
527     ModelObj.dl.plPtr  = NULL;
528     ModelObj.dl.plSize = 0;
529     CreateModelDL(ModelObj.dl.dlPtr, &ModelObj.dl.dlSize);
530     OSReport("ModelDL size = %d\n", ModelObj.dl.dlSize);
531 #endif
532 
533 
534     // Patch texcoord scale data of all shader display lists
535     for ( i = 0 ; i < NUM_SHADERDLS ; ++i )
536     {
537         PatchShaderDLTCScale(&ShaderDLs[i]);
538     }
539 }
540 
541 /*---------------------------------------------------------------------------*
542     Name:           PatchShaderDLTCScale
543 
544     Description:    Patch given shader display list and overwrite texcoord
545                     scale informations that were not determinable during
546                     creation time.
547 
548     Arguments:      mdl : MyDLObj which holds a display list to be patched.
549 
550     Returns:        none
551  *---------------------------------------------------------------------------*/
PatchShaderDLTCScale(MyDLObj * mdl)552 static void PatchShaderDLTCScale( MyDLObj* mdl )
553 {
554     GDLObj  gdlObj;
555     u32     plIndex = 0;
556 
557     // Set up a GDL object and make it current.
558     GDInitGDLObj(&gdlObj, mdl->dlPtr, mdl->dlSize);
559     GDSetCurrent(&gdlObj);
560 
561     while( plIndex < mdl->plSize / sizeof(u32) )
562     {
563         u16             scaleS, scaleT;
564         GXBool          biasS, biasT;
565         u32             tmid;
566         GXTexCoordID    tcid;
567 
568         // Patch list contains following entries per patch:
569         //   [0] : patch location offset
570         //   [1] : target texcoord ID
571         //   [2] : texture which scales the texcoord
572 
573         // Move pointer to the patch location.
574         GDSetCurrOffset(mdl->plPtr[plIndex++]);
575 
576         // Get texcoord target
577         tcid = (GXTexCoordID)(mdl->plPtr[plIndex++]);
578 
579         // Get texture size which scales the texcoord
580         tmid = mdl->plPtr[plIndex++];
581         scaleS = GXGetTexObjWidth(&MyTexObjs[tmid]);
582         scaleT = GXGetTexObjHeight(&MyTexObjs[tmid]);
583         // Bias should be turned on if repeat mode
584         biasS  = (GXBool)((GXGetTexObjWrapS(&MyTexObjs[tmid]) == GX_REPEAT)
585                           ? GX_ENABLE : GX_DISABLE);
586         biasT  = (GXBool)((GXGetTexObjWrapT(&MyTexObjs[tmid]) == GX_REPEAT)
587                           ? GX_ENABLE : GX_DISABLE);
588 
589         // Patch command
590         GDSetTexCoordScale2(tcid, scaleS, biasS, GX_DISABLE,
591                                   scaleT, biasT, GX_DISABLE);
592     }
593 
594     GDFlushCurrToMem();
595 
596     GDSetCurrent(NULL);
597 }
598 
599 /*---------------------------------------------------------------------------*
600     Name:           CreateModelVtxArray
601 
602     Description:    Create indexed data array for the model
603 
604     Arguments:      mo : pointer to model object
605 
606     Returns:        none
607  *---------------------------------------------------------------------------*/
CreateModelVtxArray(void)608 static void CreateModelVtxArray( void )
609 {
610     MyModelObj* mo = &ModelObj;
611     u32  size_p, size_n, size_t;
612     u32  cnt_p, cnt_n, cnt_t;
613     s32  i, j;
614     f32  theta, phi;
615     f32  ct, cp, dzdt, dzdp, nt, np, nn;
616 
617     size_p = MODEL_MESHX * MODEL_MESHY * 3;
618     size_n = MODEL_MESHX * MODEL_MESHY * 9;
619     size_t = MODEL_MESHX * MODEL_MESHY * 2;
620 
621     mo->posArray = (s16*)OSAlloc(size_p * sizeof(s16));
622     mo->nrmArray = (s16*)OSAlloc(size_n * sizeof(s16));
623     mo->tcdArray = (s16*)OSAlloc(size_t * sizeof(s16));
624 
625     // make array data
626     cnt_p = cnt_n = cnt_t = 0;
627     for ( i = 0 ; i < MODEL_MESHY ; ++i )
628     {
629         for ( j = 0 ; j < MODEL_MESHX ; ++j )
630         {
631             theta = (f32)j * PI_2 / MODEL_MESHX;
632             phi   = (f32)i * PI_2 / MODEL_MESHX;
633 
634             ct = cosf(theta);
635             cp = cosf(phi);
636 
637             dzdt = MODEL_ZSCALE * PI * -sinf(theta) * cp;
638             dzdp = MODEL_ZSCALE * PI * -sinf(phi)   * ct;
639 
640             nt = 1.0F / sqrtf( 1.0F + dzdt*dzdt );
641             np = 1.0F / sqrtf( 1.0F + dzdp*dzdp );
642             nn = nt * np;
643 
644             // Position
645             mo->posArray[cnt_p++] = (s16)(((f32)j*2 / MODEL_MESHX - 1.0F) * QSCALE);
646             mo->posArray[cnt_p++] = (s16)(((f32)i*2 / MODEL_MESHY - 1.0F) * QSCALE);
647             mo->posArray[cnt_p++] = (s16)(MODEL_ZSCALE * ct * cp * QSCALE);
648 
649             // Normal
650             mo->nrmArray[cnt_n++] = (s16)(nn * -dzdt * QSCALE);
651             mo->nrmArray[cnt_n++] = (s16)(nn * -dzdp * QSCALE);
652             mo->nrmArray[cnt_n++] = (s16)(nn * QSCALE);
653 
654             // Binormal
655             mo->nrmArray[cnt_n++] = (s16)(nt * QSCALE);
656             mo->nrmArray[cnt_n++] = (s16)0;
657             mo->nrmArray[cnt_n++] = (s16)(nt * dzdt * QSCALE);
658 
659             // Tangent
660             mo->nrmArray[cnt_n++] = (s16)0;
661             mo->nrmArray[cnt_n++] = (s16)(np * QSCALE);
662             mo->nrmArray[cnt_n++] = (s16)(np * dzdp * QSCALE);
663 
664             // Texcoord
665             mo->tcdArray[cnt_t++] = (s16)(j * QSCALE / MODEL_MESHX);
666             mo->tcdArray[cnt_t++] = (s16)(i * QSCALE / MODEL_MESHY);
667         }
668     }
669 
670     // make sure data is written to main memory
671     DCFlushRange(mo->posArray, size_p * sizeof(s16));
672     DCFlushRange(mo->nrmArray, size_n * sizeof(s16));
673     DCFlushRange(mo->tcdArray, size_t * sizeof(s16));
674 
675     // set up array pointers
676     GXSetArray(GX_VA_POS,  mo->posArray, sizeof(s16) * 3);
677     GXSetArray(GX_VA_NRM,  mo->nrmArray, sizeof(s16) * 9);
678     GXSetArray(GX_VA_TEX0, mo->tcdArray, sizeof(s16) * 2);
679 }
680 
681 /*---------------------------------------------------------------------------*
682     Name:           PrintIntro
683 
684     Description:    Prints the directions on how to use this demo.
685 
686     Arguments:      none
687 
688     Returns:        none
689  *---------------------------------------------------------------------------*/
PrintIntro(void)690 static void PrintIntro( void )
691 {
692     OSReport("\n\n");
693     OSReport("************************************************\n");
694     OSReport("    GD Multitexturing (TEV) demo\n");
695     OSReport("************************************************\n");
696     OSReport("to quit hit the menu button\n");
697     OSReport("\n");
698     OSReport("Main Stick   : Rotate the model\n");
699     OSReport("Sub  Stick   : Move Light Position\n");
700     OSReport("************************************************\n\n");
701 }
702 
703 /*============================================================================*/
704