1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin/Revolution gx demo
3   File:     tg-spheremap.c
4 
5   Copyright 1998-2006 Nintendo.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12  *---------------------------------------------------------------------------*/
13 /*---------------------------------------------------------------------------*
14    tg-spheremap
15      An example of environment mapping by sphere map (made from cube map)
16  *---------------------------------------------------------------------------*/
17 
18 
19 /*---------------------------------------------------------------------------*
20    Header files
21  *---------------------------------------------------------------------------*/
22 #include <demo.h>
23 #include <math.h>
24 
25 /*---------------------------------------------------------------------------*
26    Macro definitions
27  *---------------------------------------------------------------------------*/
28 #define SPHERE_MAP_SIZE  256
29 #define SPHERE_MAP_FMT   GX_TF_RGB565
30 #define SPHERE_MAP_TESS  30
31 
32 /*---------------------------------------------------------------------------*
33    Global variables
34  *---------------------------------------------------------------------------*/
35 // defined in spheremap.c so we can look at individual maps and alpha
36 extern u8 CubeFaceStart;
37 extern u8 CubeFaceEnd;
38 extern u8 CubeTevMode;
39 
40 // static
41 static Mtx  ViewMtx;
42 static Mtx  ModelMtx;
43 static u8   CubeFaceDisp;
44 
45 static Vec CamLoc = {0.0F, 0.0F, 4.0F};
46 static Vec UP     = {0.0F, 1.0F, 0.0F};
47 static Vec ObjPt  = {0.0F, 0.0F, 0.0F};
48 
49 static u8 CurrentTexture;
50 
51 static void *mySphere;          // sphere geometry display list
52 static u32   mySphereSz;        // sphere geometry display list size
53 
54 static TPLPalettePtr tpl0 = 0;  // cube map files
55 static TPLPalettePtr tpl1 = 0;
56 
57 static GXTexObj CubeMap0[6];    // a couple of pre-made cube maps
58 static GXTexObj CubeMap1[6];
59 static GXTexObj SphereMap;      // sphere map that is generated from cube map
60 
61 /*---------------------------------------------------------------------------*
62    External function references
63  *---------------------------------------------------------------------------*/
64 // from spheremap.c
65 extern void genMapSphere        ( void**    display_list,
66                                   u32*      size,
67                                   u16       tess,
68                                   GXVtxFmt  fmt );
69 
70 extern void drawSphereMap       ( GXTexObj* cubemap,
71                                   GXTexObj* spheremap,
72                                   void*     dl,
73                                   u32       dlsz );
74 
75 /*---------------------------------------------------------------------------*
76    Forward references
77  *---------------------------------------------------------------------------*/
78 void        main                    ( void );
79 static void DrawInit                ( void );
80 static void DrawTick                ( void );
81 static void InitTexGenMethod        ( void );
82 static void AnimTick                ( void );
83 static void SetTexGenForSphereMap   ( Mtx nMtx );
84 static void SetCamera               ( void );
85 static void PrintIntro              ( void );
86 
87 /*---------------------------------------------------------------------------*
88    Application main loop
89  *---------------------------------------------------------------------------*/
main(void)90 void main ( void )
91 {
92     DEMOInit(NULL);
93 
94     DrawInit();
95     PrintIntro();
96 
97     while(!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
98     {
99         DEMOPadRead();
100 
101         AnimTick();
102         DEMOBeforeRender();
103         DrawTick();
104 
105         DEMODoneRender();
106     }
107 
108     OSHalt("End of demo");
109 }
110 
111 /*---------------------------------------------------------------------------*
112     Name:           DrawInit
113 
114     Description:    Initializes textures, some permanent GX settings and
115                     all scene parameters.
116 
117     Arguments:      none
118     Returns:        none
119  *---------------------------------------------------------------------------*/
DrawInit(void)120 static void DrawInit    ( void )
121 {
122     u32              i;
123     TPLDescriptorPtr tdp;
124     void*            tex_buffer;
125 
126     GXSetCullMode(GX_CULL_BACK);
127 
128     // sphere map geometry is using format 7
129     // this is for textured quad geometry
130     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
131     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
132 
133     //
134     // Initialize texture object for sphere map
135     //   - the data will be filled in each time drawSphereMap is called
136     //
137     tex_buffer = (void*)MEMAllocFromAllocator(&DemoAllocator1,
138             GXGetTexBufferSize(SPHERE_MAP_SIZE, SPHERE_MAP_SIZE,
139                                (u32)SPHERE_MAP_FMT,  GX_FALSE, 0));
140 
141     OSReport("tex %08x\n", tex_buffer);
142 
143     GXInitTexObj(
144         &SphereMap,
145         tex_buffer,
146         SPHERE_MAP_SIZE,
147         SPHERE_MAP_SIZE,
148         SPHERE_MAP_FMT,
149         GX_CLAMP,
150         GX_CLAMP,
151         GX_FALSE);
152 
153     // read textures
154     // order of loading: right, front, left, back, top, bottom
155     OSReport("Opening gxTests/tg-cube.tpl\n");
156     TPLGetPalette(&tpl0, "gxTests/tg-cube.tpl");
157 
158     for (i = 0; i < 6; i++)
159     {
160         tdp = TPLGet(tpl0, i);
161         GXInitTexObj(&CubeMap0[i],
162                  tdp->textureHeader->data,
163                  tdp->textureHeader->width,
164                  tdp->textureHeader->height,
165                  (GXTexFmt)tdp->textureHeader->format,
166                  GX_CLAMP,
167                  GX_CLAMP,
168                  GX_FALSE);
169 
170         // alpha should be zero on edges, clamp so sphere outside
171         // projected texture is not overwritten
172         GXInitTexObjLOD(&CubeMap0[i],
173                     tdp->textureHeader->minFilter,
174                     tdp->textureHeader->magFilter,
175                     tdp->textureHeader->minLOD,
176                     tdp->textureHeader->maxLOD,
177                     tdp->textureHeader->LODBias,
178                     GX_FALSE,
179                     tdp->textureHeader->edgeLODEnable,
180                     GX_ANISO_1);
181     }
182 
183     // read pre-made cube map textures
184     // order of loading: right, front, left, back, top, bottom
185     OSReport("Opening gxTests/tg-cube1.tpl\n");
186     TPLGetPalette(&tpl1, "gxTests/tg-cube1.tpl");
187 
188     for (i = 0; i < 6; i++)
189     {
190         tdp = TPLGet(tpl1, i);
191         GXInitTexObj(&CubeMap1[i],
192                  tdp->textureHeader->data,
193                  tdp->textureHeader->width,
194                  tdp->textureHeader->height,
195                  (GXTexFmt)tdp->textureHeader->format,
196                  GX_CLAMP,
197                  GX_CLAMP,
198                  GX_FALSE);
199 
200         // alpha should be zero on edges, clamp so sphere outside
201         // projected texture is not overwritten
202         GXInitTexObjLOD(&CubeMap1[i],
203                     tdp->textureHeader->minFilter,
204                     tdp->textureHeader->magFilter,
205                     tdp->textureHeader->minLOD,
206                     tdp->textureHeader->maxLOD,
207                     tdp->textureHeader->LODBias,
208                     GX_FALSE,
209                     tdp->textureHeader->edgeLODEnable,
210                     GX_ANISO_1);
211     }
212 
213     // generate sphere geometry once
214     genMapSphere(&mySphere, &mySphereSz, SPHERE_MAP_TESS, GX_VTXFMT7);
215 
216     // initialization for contourable parameters
217     CubeFaceDisp  = 6;
218     CubeFaceStart = 0;
219     CubeFaceEnd   = 6;
220 
221     MTXIdentity(ModelMtx);
222 }
223 
224 /*---------------------------------------------------------------------------*
225     Name:           DrawTick
226 
227     Description:    Create sphere environment map from cube textures and
228                     draw it on a quad. Displays an example 3D object (torus)
229                     with texgen for sphere environment mapping.
230 
231     Arguments:      none
232     Returns:        none
233  *---------------------------------------------------------------------------*/
DrawTick(void)234 static void DrawTick ( void )
235 {
236     Mtx   mv;
237 
238     SetCamera();
239 
240     // create sphere map texture
241     if (CurrentTexture)
242         drawSphereMap(&CubeMap1[0], &SphereMap, mySphere, mySphereSz);
243     else
244         drawSphereMap(&CubeMap0[0], &SphereMap, mySphere, mySphereSz);
245 
246     // fill screen by another background color
247     GXSetCopyClear((GXColor){ 0x60, 0x60, 0x60, 0xFF }, 0x00FFFFFF);
248     GXCopyDisp(DEMOGetCurrentBuffer(), GX_TRUE);
249 
250     // Texture/rendering path setting
251     GXSetBlendMode(GX_BM_BLEND, GX_BL_ONE, GX_BL_ZERO, GX_LO_SET);
252     GXSetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
253     GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE);
254     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
255     GXSetNumTevStages(1);
256     GXSetNumTexGens(1);
257     GXSetNumChans(0);
258 
259     GXInvalidateTexAll();
260     GXLoadTexObj(&SphereMap, GX_TEXMAP0);
261 
262     // Draw sphere map texture on a quad
263     //  (no distortion)
264     GXSetViewport(16.0F, 16.0F, 256.0F, 256.0F, 0.0F, 1.0F);
265 
266     GXLoadPosMtxImm(ViewMtx, GX_PNMTX0);
267     GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
268 
269     GXClearVtxDesc();
270     GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
271     GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
272 
273     GXBegin(GX_QUADS, GX_VTXFMT0, 4);
274         GXPosition3f32(-1.0F, 1.0F, 0.0F);
275         GXTexCoord2f32(0.0F, 0.0F);
276         GXPosition3f32(1.0F, 1.0F, 0.0F);
277         GXTexCoord2f32(1.0F, 0.0F);
278         GXPosition3f32(1.0F, -1.0F, 0.0F);
279         GXTexCoord2f32(1.0F, 1.0F);
280         GXPosition3f32(-1.0F, -1.0F, 0.0F);
281         GXTexCoord2f32(0.0F, 1.0F);
282     GXEnd();
283 
284     // Draw environment mapped torus
285     //  (uses normal-based spherical projection)
286     GXSetViewport(320.0F, 120.0F, 256.0F, 256.0F, 0.0F, 1.0F);
287 
288     MTXConcat(ViewMtx, ModelMtx, mv);
289     GXLoadPosMtxImm(mv, GX_PNMTX0);
290     MTXInvXpose(mv, mv);
291     SetTexGenForSphereMap(mv);
292 
293     GXDrawTorus(0.25F, 32, 24);
294 
295     // Set background color for the first pass.
296     GXSetCopyClear((GXColor){ 0, 0, 0, 0 }, 0x00FFFFFF);
297 }
298 
299 /*---------------------------------------------------------------------------*
300     Name:           AnimTick
301 
302     Description:    Changes scene parameters according to the pad status.
303 
304     Arguments:      none
305     Returns:        none
306  *---------------------------------------------------------------------------*/
AnimTick(void)307 static void AnimTick ( void )
308 {
309     Mtx  mrx, mry;
310     u16  buttons = DEMOPadGetButtonDown(0);
311 
312     MTXRotDeg(mry, 'x', -(f32)(DEMOPadGetStickY(0))/16.0F);
313     MTXRotDeg(mrx, 'y', (f32)(DEMOPadGetStickX(0))/16.0F);
314     MTXConcat(mry, ModelMtx, ModelMtx);
315     MTXConcat(mrx, ModelMtx, ModelMtx);
316 
317     if (buttons & PAD_BUTTON_B)
318     {
319         CubeFaceDisp++;
320         CubeFaceDisp %= 7;
321 
322         CubeFaceStart = CubeFaceDisp;
323         CubeFaceEnd   = (u8)(CubeFaceStart + 1);
324 
325         if ( CubeFaceDisp == 6 )
326         {
327             CubeFaceStart = 0;
328             CubeFaceEnd   = 6;
329         }
330 
331         switch ( CubeFaceDisp )
332         {
333             case 0: OSReport("right face\n");   break;
334             case 1: OSReport("front face\n");   break;
335             case 2: OSReport("left face\n");    break;
336             case 3: OSReport("back face\n");    break;
337             case 4: OSReport("top face\n");     break;
338             case 5: OSReport("bottom face\n");  break;
339             case 6: OSReport("all faces\n");    break;
340         }
341     }
342 
343     if (buttons & PAD_BUTTON_Y)
344     {
345         CubeFaceDisp  = 6;
346         CubeFaceStart = 0;
347         CubeFaceEnd   = 6;
348         OSReport("all faces\n");
349     }
350 
351     if (buttons & PAD_BUTTON_A)
352     {
353         CurrentTexture ^= 1;
354         OSReport("Texture %d\n", CurrentTexture);
355     }
356 
357     if (buttons & PAD_TRIGGER_Z)
358     {
359         CubeTevMode++;
360         if (CubeTevMode > 4)
361             CubeTevMode = 0;
362 
363         switch (CubeTevMode)
364         {
365             case 0: OSReport("Final result\n"); break;
366             case 1: OSReport("Unclipped texture\n"); break;
367             case 2: OSReport("texture alpha\n"); break;
368             case 3: OSReport("Q-clipping (raster) alpha\n"); break;
369             case 4: OSReport("raster*texture alpha\n"); break;
370         }
371     }
372 }
373 
374 /*---------------------------------------------------------------------------*
375     Name:           SetTexGenForSphereMap
376 
377     Description:    Set up texgen for doing spherical environment mapping
378 
379     Arguments:      nMtx : view normal transformation matrix
380 
381     Returns:        none
382  *---------------------------------------------------------------------------*/
SetTexGenForSphereMap(Mtx nMtx)383 static void SetTexGenForSphereMap( Mtx nMtx )
384 {
385     Mtx  m0, m1, m2;
386 
387     MTXScale(m1, 0.50F, -0.50F, 0.0F);
388     MTXTrans(m0, 0.50F, 0.50F, 1.0F);
389     MTXConcat(m0, m1, m2);
390     GXLoadTexMtxImm(nMtx, GX_TEXMTX0, GX_MTX3x4);
391     GXLoadTexMtxImm(m2, GX_PTTEXMTX0, GX_MTX3x4);
392     GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX3x4, GX_TG_NRM,
393                       GX_TEXMTX0, GX_TRUE, GX_PTTEXMTX0);
394 }
395 
396 /*---------------------------------------------------------------------------*
397     Name:           SetCamera
398 
399     Description:    Set projection and view matrix
400 
401     Arguments:      none
402 
403     Returns:        none
404  *---------------------------------------------------------------------------*/
SetCamera(void)405 static void SetCamera ( void )
406 {
407     Mtx44 p;
408 
409     MTXOrtho(p, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 100.0f);
410     GXSetProjection(p, GX_ORTHOGRAPHIC);
411 
412     MTXLookAt(ViewMtx, &CamLoc, &UP, &ObjPt);
413 }
414 
415 /*---------------------------------------------------------------------------*
416     Name:           PrintIntro
417 
418     Description:    Prints the directions on how to use this demo.
419 
420     Arguments:      none
421 
422     Returns:        none
423  *---------------------------------------------------------------------------*/
PrintIntro(void)424 static void PrintIntro( void )
425 {
426     OSReport("\n\n");
427     OSReport("******************************************************\n");
428     OSReport("tg-spheremap: create a sphere map from a cube map\n");
429     OSReport("******************************************************\n");
430     OSReport("to quit hit the start button\n");
431     OSReport("\n");
432     OSReport("Main Stick : rotate the torus\n");
433     OSReport("A button   : select the environment cube map texture\n");
434     OSReport("B button   : display individual cube faces\n");
435     OSReport("Y button   : display all cube faces in the sphere map\n");
436     OSReport("Z button   : select alpha/color channel to display\n");
437     OSReport("******************************************************\n");
438     OSReport("\n\n");
439 }
440 
441 /*===========================================================================*/
442