1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin/Revolution gx demo
3   File:     tev-ztex.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-ztex
15         Z texture test
16  *---------------------------------------------------------------------------*/
17 
18 
19 /*---------------------------------------------------------------------------*
20    Header files
21  *---------------------------------------------------------------------------*/
22 #include <demo.h>
23 #include <string.h>
24 
25 /*---------------------------------------------------------------------------*
26    Macro definitions
27  *---------------------------------------------------------------------------*/
28 // Indices for textures stored in TPL file
29 #define TEX_GROUND      0
30 #define TEX_GROUND_Z    1
31 #define TEX_TREE        2
32 #define TEX_TREE_Z      3
33 #define TEX_WATER       4
34 #define NUM_TEXTURES    5
35 
36 // Number of tree sprites
37 #define NUM_TREES       8
38 
39 // Number of Z modes
40 #define NUM_ZMODES      4
41 
42 // Max value of Z buffer
43 #define MAX_Z           0x00FFFFFF
44 
45 
46 #define Clamp(cast,val,min,max) \
47     ((val) = (cast)((((val) < (min)) ? (min) : ((val) > (max)) ? (max) : (val))))
48 
49 /*---------------------------------------------------------------------------*
50    Structure definitions
51  *---------------------------------------------------------------------------*/
52 // for sprite control
53 typedef struct
54 {
55     s16     xpos;   // left
56     s16     ypos;   // bottom
57     s16     zpos;
58     s16     width;
59     s16     height;
60     s16     s0;
61     s16     s1;
62     s16     t0;
63     s16     t1;
64     u8      texIdx; // texture index
65     u8      ztxIdx; // Z texture index
66     u32     zbias;  // Z texture bias
67 } MySpriteObj;
68 
69 // for entire scene control
70 typedef struct
71 {
72     u32         cur;
73     u32         zmode;
74     s16         waterLv;
75     MySpriteObj tree[NUM_TREES];
76     u16         screenWd;
77     u16         screenHt;
78     GXTexObj    texture[NUM_TEXTURES];
79 } MySceneCtrlObj;
80 
81 /*---------------------------------------------------------------------------*
82    Forward references
83  *---------------------------------------------------------------------------*/
84 void        main                    ( void );
85 static void DrawInit                ( MySceneCtrlObj* sc );
86 static void DrawTick                ( MySceneCtrlObj* sc );
87 static void AnimTick                ( MySceneCtrlObj* sc );
88 static void Draw3DSprite            ( MySpriteObj* sp, u32 zmode );
89 static void DrawWater               ( s16 level );
90 static void MyTexInit               ( void );
91 static void SetShaderModeForSprites ( void );
92 static void SetShaderModeForWater   ( void );
93 static void SetScreenSpace          ( u16 width, u16 height, f32 depth );
94 static void PrintIntro              ( void );
95 
96 /*---------------------------------------------------------------------------*
97    Data for drawing objects
98  *---------------------------------------------------------------------------*/
99 static MySpriteObj GroundSprite =
100 {
101     0, 0, 32767,        // xpos, ypos, zpos
102     640, 256,           // width, height
103     0x0000, 0x0280,     // s0=0.0, s1=2.5
104     0x0000, 0x0100,     // t0=0.0, t1=1.0
105     TEX_GROUND,         // texture index
106     TEX_GROUND_Z,       // Z texture index
107     0x00FF8000          // Z bias = -32768
108 };
109 
110 static MySpriteObj DefaultTreeSprite =
111 {
112     0, 0, 0,            // xpos, ypos, zpos (set later)
113     128, 256,           // width, height
114     0x0000, 0x0100,     // s0=0.0, s1=1.0
115     0x0000, 0x0100,     // t0=0.0, t1=1.0
116     TEX_TREE,           // texture index
117     TEX_TREE_Z,         // Z texture index
118     0x00FFFF80          // Z bias = -128
119 };
120 
121 static s16 DefaultTreePos[NUM_TREES][3] =
122 {
123     { -48, 192, 2688 },
124     {   0,  48, 2370 },
125     { 128, 168, 2716 },
126     { 200,  56, 1900 },
127     { 328, 120, 2464 },
128     { 368, 120, 2484 },
129     { 456, -16, 1780 },
130     { 536,  96, 3096 },
131 };
132 
133 static GXColor WaterBaseColor = { 160, 160, 192, 80 };
134 static GXColor BgColor        = { 120, 136, 152,  0 };
135 
136 /*---------------------------------------------------------------------------*
137    Data for Z texturing mode control
138  *---------------------------------------------------------------------------*/
139 static GXZTexOp ZTexOpTbl[NUM_ZMODES] =
140 {
141     GX_ZT_ADD, GX_ZT_ADD, GX_ZT_REPLACE, GX_ZT_DISABLE
142 };
143 
144 static char* ZModeMsgTbl[NUM_ZMODES] =
145 {
146     "Z texture add mode with bias",
147     "Z texture add mode without bias",
148     "Z texture replace mode without bias",
149     "Z texture off"
150 };
151 
152 
153 /*---------------------------------------------------------------------------*
154    Global variables
155  *---------------------------------------------------------------------------*/
156 static MySceneCtrlObj   SceneCtrl;                  // scene control parameters
157 static TPLPalettePtr    MyTplObj = NULL;            // texture palette
158 static GXTexObj         MyTexArray[NUM_TEXTURES];   // texture objects
159 
160 /*---------------------------------------------------------------------------*
161    Application main loop
162  *---------------------------------------------------------------------------*/
main(void)163 void main ( void )
164 {
165     DEMOInit(NULL);  // Init the OS, game pad, graphics and video.
166 
167     DrawInit(&SceneCtrl); // Initialize vertex formats, pixel modes
168                           // and default scene settings.
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();           // Read controller
178         AnimTick(&SceneCtrl);    // Do 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 sets up
191                     the array pointer for the indexed data.
192                     This function also initializes scene control parameters.
193 
194     Arguments:      sc : pointer to the structure of scene control parameters
195 
196     Returns:        none
197  *---------------------------------------------------------------------------*/
DrawInit(MySceneCtrlObj * sc)198 static void DrawInit( MySceneCtrlObj* sc )
199 {
200     GXRenderModeObj*  rmode;
201     u32               i;
202 
203     // Vertex Attribute
204     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 0);
205     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA4, 0);
206     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S16, 8);
207 
208     // Get Screen Information defined in DEMOInit()
209     rmode = DEMOGetRenderModeObj();
210     sc->screenWd = rmode->fbWidth;   // Screen Width
211     sc->screenHt = rmode->efbHeight; // Screen Height
212 
213     // Z compare mode
214     GXSetZMode(GX_ENABLE, GX_LEQUAL, GX_TRUE);
215     GXSetZCompLoc(GX_FALSE);
216 
217     // Clear background by specified color at first
218     // The operation can be done by dummy display copy.
219     GXSetCopyClear(BgColor, MAX_Z);
220     GXCopyDisp(DEMOGetCurrentBuffer(), GX_TRUE);
221 
222 
223     // Load TPL file
224     MyTexInit();
225 
226 
227     // Default scene control parameter settings
228 
229     // Initialize position of tree sprites
230     for ( i = 0 ; i < NUM_TREES ; ++i )
231     {
232         sc->tree[i] = DefaultTreeSprite;
233 
234         // Overwrite position for each tree
235         sc->tree[i].xpos = DefaultTreePos[i][0];
236         sc->tree[i].ypos = DefaultTreePos[i][1];
237         sc->tree[i].zpos = DefaultTreePos[i][2];
238     }
239 
240     // water level
241     sc->waterLv = 176;
242 
243     // cursor
244     sc->cur = 0;
245 }
246 
247 /*---------------------------------------------------------------------------*
248     Name:           DrawTick
249 
250     Description:    Draw the model by using given scene parameters
251 
252     Arguments:      sc : pointer to the structure of scene control parameters
253 
254     Returns:        none
255  *---------------------------------------------------------------------------*/
DrawTick(MySceneCtrlObj * sc)256 static void DrawTick( MySceneCtrlObj* sc )
257 {
258     u32  i;
259 
260     // set projection to match screen space coordinate system
261     SetScreenSpace(sc->screenWd, sc->screenHt, 0x01000000);
262 
263     // blend mode (semi-transparent values are blended)
264     GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_SET);
265 
266     //------------------------------------
267     //  Draw sprite objects
268     //------------------------------------
269     SetShaderModeForSprites();
270 
271     // ground
272     Draw3DSprite(&GroundSprite, sc->zmode);
273 
274     // trees
275     for ( i = 0 ; i < NUM_TREES ; ++i )
276     {
277         Draw3DSprite(&sc->tree[i], sc->zmode);
278     }
279 
280     //------------------------------------
281     //  Draw water surface
282     //------------------------------------
283 
284     // Z texture off
285     GXSetZTexture(GX_ZT_DISABLE, GX_TF_Z8, 0);
286 
287     SetShaderModeForWater();
288     DrawWater(sc->waterLv);
289 }
290 
291 /*---------------------------------------------------------------------------*
292     Name:           AnimTick
293 
294     Description:    Changes scene parameters according to the pad status.
295 
296     Arguments:      sc : pointer to the structure of scene control parameters
297 
298     Returns:        none
299  *---------------------------------------------------------------------------*/
AnimTick(MySceneCtrlObj * sc)300 static void AnimTick( MySceneCtrlObj* sc )
301 {
302     MySpriteObj* sp;
303     u16          down;
304 
305     // PAD
306     down = DEMOPadGetButtonDown(0);
307 
308     sp = &sc->tree[sc->cur];
309 
310     // Move selected tree sprite
311     sp->xpos += ( DEMOPadGetStickX(0) / 16 );
312     Clamp(s16, sp->xpos, (s16)-128, (s16)sc->screenWd);
313     sp->ypos += ( DEMOPadGetStickY(0) / 16 );
314     Clamp(s16, sp->ypos, (s16)-256, (s16)sc->screenHt);
315     sp->zpos += ( DEMOPadGetSubStickY(0) / 4 );
316     Clamp(s16, sp->zpos, (s16)0, (s16)32767);
317 
318     // Select a tree
319     if ( down & PAD_BUTTON_X )
320     {
321         sc->cur = ( sc->cur + 1 ) % NUM_TREES;
322     }
323 
324     if ( down & PAD_BUTTON_Y )
325     {
326         sc->cur = ( sc->cur + NUM_TREES - 1 ) % NUM_TREES;
327     }
328 
329     // Water level
330     sc->waterLv += ( DEMOPadGetTriggerL(0) - DEMOPadGetTriggerR(0) ) / 32;
331     Clamp(s16, sc->waterLv, (s16)0, (s16)256);
332 
333     // Z texturing mode
334     if ( down & PAD_BUTTON_B )
335     {
336         sc->zmode = ( sc->zmode + 1 ) % NUM_ZMODES;
337         OSReport("%s\n", ZModeMsgTbl[sc->zmode]);
338     }
339 }
340 
341 /*---------------------------------------------------------------------------*
342     Name:           Draw3DSprite
343 
344     Description:    Draw a 3D sprite specified by given data structure.
345 
346     Arguments:      sp: a pointer to MySpriteObj structure
347                     zmode : Z texturing mode
348 
349     Returns:        none
350  *---------------------------------------------------------------------------*/
Draw3DSprite(MySpriteObj * sp,u32 zmode)351 static void Draw3DSprite( MySpriteObj* sp, u32 zmode )
352 {
353     s16  xpos1, ypos1;
354     u32  zbias;
355 
356     // Z bias enable / disable
357     zbias = ( zmode == 0 ) ? sp->zbias : 0U;
358 
359     // load textures and set up Z texturing
360     GXLoadTexObj(&MyTexArray[sp->texIdx], GX_TEXMAP0);
361 
362     GXLoadTexObj(&MyTexArray[sp->ztxIdx], GX_TEXMAP1);
363     GXSetZTexture(
364         ZTexOpTbl[zmode],
365         GXGetTexObjFmt(&MyTexArray[sp->ztxIdx]),
366         zbias );
367 
368     // set vertex descriptor
369     GXClearVtxDesc();
370     GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
371     GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
372 
373     xpos1 = (s16)(sp->xpos + sp->width);
374     ypos1 = (s16)(sp->ypos + sp->height);
375 
376     // draw the quad
377     GXBegin(GX_QUADS, GX_VTXFMT0, 4);
378         GXPosition3s16(sp->xpos, sp->ypos, sp->zpos);
379         GXTexCoord2s16(sp->s0, sp->t1);
380         GXPosition3s16(sp->xpos, ypos1,    sp->zpos);
381         GXTexCoord2s16(sp->s0, sp->t0);
382         GXPosition3s16(xpos1,    ypos1,    sp->zpos);
383         GXTexCoord2s16(sp->s1, sp->t0);
384         GXPosition3s16(xpos1,    sp->ypos, sp->zpos);
385         GXTexCoord2s16(sp->s1, sp->t1);
386     GXEnd();
387 }
388 
389 /*---------------------------------------------------------------------------*
390     Name:           DrawWater
391 
392     Description:    Draw water surface.
393                     The water surface is one textured quad
394                     which has some degree of gradient.
395 
396     Arguments:      level : water level
397 
398     Returns:        none
399  *---------------------------------------------------------------------------*/
DrawWater(s16 level)400 static void DrawWater( s16 level )
401 {
402     static s16  s0 = 0;
403     s16  s1, lv1;
404 
405     s1  = (s16)(s0 + 0x1000);
406     lv1 = (s16)(level - 256);
407 
408     // load texture
409     GXLoadTexObj(&MyTexArray[TEX_WATER], GX_TEXMAP0);
410 
411     // set vertex descriptor
412     GXClearVtxDesc();
413     GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
414     GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
415 
416     // draw the quad
417     GXBegin(GX_QUADS, GX_VTXFMT0, 4);
418         GXPosition3s16(0,   lv1, 0);
419         GXTexCoord2s16(s0, 0x0000);
420         GXPosition3s16(0,   level, 4096);
421         GXTexCoord2s16(s0, 0x0600);
422         GXPosition3s16(640, level, 4096);
423         GXTexCoord2s16(s1, 0x0600);
424         GXPosition3s16(640, lv1, 0);
425         GXTexCoord2s16(s1, 0x0000);
426     GXEnd();
427 
428     s0 = (s16)(++s0 % 0x100);
429 }
430 
431 /*---------------------------------------------------------------------------*
432     Name:           MyTexInit
433 
434     Description:    Load texture data from a TPL file and store it
435                     into the texture object array. (TexArray)
436 
437                     Since TPL file is not able to handle Z texture
438                     format, Z textures are saved as other format
439                     data. This function converts their format
440                     and some other fields to make them suitable
441                     for Z texturing.
442 
443     Arguments:      none
444 
445     Returns:        none
446  *---------------------------------------------------------------------------*/
MyTexInit(void)447 static void MyTexInit( void )
448 {
449     TPLDescriptorPtr  tdp;
450     GXTexFmt          fmt;
451     GXTexFilter       filter;
452     u32  i;
453 
454     TPLGetPalette(&MyTplObj, "gxTests/tev-04.tpl");
455 
456     for ( i = 0 ; i < NUM_TEXTURES ; ++i )
457     {
458         tdp = TPLGet(MyTplObj, i);
459 
460         if ( i % 2 == 0 )
461         {
462             // Even number -> image texture
463             fmt = (GXTexFmt)tdp->textureHeader->format;
464             filter = GX_LINEAR;
465 
466             // Ground texture needs special wrap mode setting
467             if ( i == TEX_GROUND )
468             {
469                 tdp->textureHeader->wrapS = GX_REPEAT;
470                 tdp->textureHeader->wrapT = GX_CLAMP;
471             }
472         }
473         else
474         {
475             // Odd number -> supposed to be Z texture
476 
477             // format conversion
478             switch(tdp->textureHeader->format)
479             {
480               case GX_TF_I8 :
481                 fmt = GX_TF_Z8;
482                 break;
483               case GX_TF_IA8 :
484                 fmt = GX_TF_Z16;
485                 break;
486               case GX_TF_RGBA8:
487                 fmt = GX_TF_Z24X8;
488                 break;
489               default:
490                 OSHalt("Invalid data for Z texturing.");
491             }
492 
493             filter = GX_NEAR;
494         }
495 
496         GXInitTexObj(
497             &MyTexArray[i],
498             tdp->textureHeader->data,
499             tdp->textureHeader->width,
500             tdp->textureHeader->height,
501             fmt,
502             tdp->textureHeader->wrapS,
503             tdp->textureHeader->wrapT,
504             GX_FALSE ); // Mipmap is always off
505         GXInitTexObjLOD(
506             &MyTexArray[i],
507             filter,     // Z doesn't work well with filtering
508             filter,     //
509             0,
510             0,
511             0,
512             GX_FALSE,
513             GX_FALSE,
514             GX_ANISO_1 );
515     }
516 }
517 
518 /*---------------------------------------------------------------------------*
519     Name:           SetShaderModeForSprites
520 
521     Description:    Set up shader mode (TEV, color channel, etc.)
522                     for drawing sprite objects.
523 
524     Arguments:      none
525 
526     Returns:        none
527  *---------------------------------------------------------------------------*/
SetShaderModeForSprites(void)528 static void SetShaderModeForSprites( void )
529 {
530     // accepts alpha > 128 which are used for blending
531     GXSetAlphaCompare(GX_GREATER, 128, GX_AOP_AND, GX_ALWAYS, 0);
532 
533     // use no color channel
534     GXSetNumChans(0);
535 
536     // use two textures that share the same texcoord
537     // (it is possible only if the size is same.)
538     GXSetNumTexGens(1);
539     GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
540 
541     // TEV setting
542     GXSetNumTevStages(2);
543     GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE);
544     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
545     GXSetTevOp(GX_TEVSTAGE1, GX_PASSCLR);
546     GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD0, GX_TEXMAP1, GX_COLOR_NULL);
547 }
548 
549 /*---------------------------------------------------------------------------*
550     Name:           SetShaderModeForWater
551 
552     Description:    Set up shader mode (TEV, color channel, etc.)
553                     for drawing water surface.
554 
555     Arguments:      none
556 
557     Returns:        none
558  *---------------------------------------------------------------------------*/
SetShaderModeForWater(void)559 static void SetShaderModeForWater( void )
560 {
561     // through all alpha
562     GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0);
563 
564     // use one color channel as constant color
565     GXSetNumChans(1);
566     GXSetChanCtrl(GX_COLOR0A0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG,
567                   GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE);
568     GXSetChanMatColor(GX_COLOR0A0, WaterBaseColor);
569 
570     // use one texture
571     GXSetNumTexGens(1);
572     GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
573 
574     // TEV setting
575     GXSetNumTevStages(1);
576     GXSetTevOp(GX_TEVSTAGE0, GX_MODULATE);
577     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
578 }
579 
580 /*---------------------------------------------------------------------------*
581     Name:           SetScreenSpace
582 
583     Description:    Set up projection matrices to match the
584                     screen coordinate system which is suitable to
585                     display sprites.
586                     The left-lower corner becomes (0, 0).
587 
588     Arguments:      width  : screen width
589                     height : screen height
590                     depth  : max depth
591 
592     Returns:        none
593  *---------------------------------------------------------------------------*/
SetScreenSpace(u16 width,u16 height,f32 depth)594 static void SetScreenSpace( u16 width, u16 height, f32 depth )
595 {
596     Mtx44  mp;
597     Mtx    mv;
598 
599     // Orthographic projection
600     MTXOrtho(mp, (f32)height, 0.0F, 0.0F, (f32)width, 0.0F, -depth);
601     GXSetProjection(mp, GX_ORTHOGRAPHIC);
602 
603     // View matrix is set as identity.
604     // (never changed through this demo)
605     MTXIdentity(mv);
606     GXLoadPosMtxImm(mv, GX_PNMTX0);
607     GXSetCurrentMtx(GX_PNMTX0);
608 }
609 
610 /*---------------------------------------------------------------------------*
611     Name:           PrintIntro
612 
613     Description:    Prints the directions on how to use this demo.
614 
615     Arguments:      none
616 
617     Returns:        none
618  *---------------------------------------------------------------------------*/
PrintIntro(void)619 static void PrintIntro( void )
620 {
621     OSReport("\n\n");
622     OSReport("************************************************\n");
623     OSReport("tex-ztex: Z texture demo\n");
624     OSReport("************************************************\n");
625     OSReport("to quit hit the start button\n");
626     OSReport("\n");
627     OSReport("B Button     : Change Z texturing mode\n");
628     OSReport("Sticks       : Move selected tree sprite\n");
629     OSReport("X/Y Buttons  : Toggle selection of a tree sprite\n");
630     OSReport("L/R Triggers : Adjust water level\n");
631     OSReport("************************************************\n\n");
632 }
633 
634 /*============================================================================*/
635