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