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 #include <demo.h>
15 #include <math.h>
16 
17 #define SPHERE_MAP_SIZE  128
18 #define SPHERE_MAP_FMT   GX_TF_RGB565
19 #define SPHERE_MAP_TESS  40
20 
21 /*>*******************************(*)*******************************<*/
22 // defined in spheremap.c so we can look at individual maps and alpha
23 extern u8 CubeFaceStart;
24 extern u8 CubeFaceEnd;
25 extern u8 CubeTevMode;
26 
27 /*>*******************************(*)*******************************<*/
28 static Mtx v, m, mv;
29 static Mtx44 proj;
30 
31 static Vec CamLoc = {0.0F, 0.0F, 6.0F};
32 static Vec UP     = {0.0F, 1.0F, 0.0F};
33 static Vec ObjPt  = {0.0F, 0.0F, 0.0F};
34 
35 static u8 CurrentTexture;
36 
37 static void *mySphere;   // sphere geometry display list
38 static u32   mySphereSz; // sphere geometry display list size
39 
40 static TPLPalettePtr tpl0 = 0; // cube map files
41 static TPLPalettePtr tpl1 = 0;
42 
43 static GXTexObj CubeMap0[6];    // a couple of pre-made cube maps
44 static GXTexObj CubeMap1[6];
45 static GXTexObj SphereMap[2];   // sphere map that is generated
46 
47 /*>*******************************(*)*******************************<*/
48 void        main                ( void );
49 static void InitCamera          ( void );
50 static void DrawInit            ( void );
51 static void DrawTick            ( void );
52 static void InitTexGenMethod    ( void );
53 static void AnimTick            ( void );
54 static void PrintIntro          ( void );
55 
56 /*>*******************************(*)*******************************<*/
57 //
58 // from spheremap.c
59 //
60 extern void genMapSphere        ( void**    display_list,
61                                   u32*      size,
62                                   u16       tess,
63                                   GXVtxFmt  fmt );
64 
65 extern void drawParaboloidMap   ( GXTexObj* cubemap,
66                                   GXTexObj* spheremap,
67                                   void*     dl,
68                                   u32       dlsz,
69                                   GXBool    front );
70 /*>*******************************(*)*******************************<*/
71 
72 
main(void)73 void main ( void )
74 {
75     DEMOInit(NULL);
76 
77     InitCamera();
78 
79     DrawInit();
80     PrintIntro();
81 
82     while(!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
83     {
84         DEMOPadRead();
85 
86         AnimTick();
87         DEMOBeforeRender();
88 
89         DrawTick();
90 
91         DEMODoneRender();
92     }
93 
94     OSHalt("End of demo");
95 }
96 
97 /*>*******************************(*)*******************************<*/
InitCamera(void)98 static void InitCamera ( void )
99 {
100     Mtx44 p;
101 
102     MTXOrtho(p, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 100.0f);
103     GXSetProjection(p, GX_ORTHOGRAPHIC);
104 
105     MTXLookAt(v, &CamLoc, &UP, &ObjPt);
106 }
107 
108 /*>*******************************(*)*******************************<*/
DrawInit(void)109 static void DrawInit    ( void )
110 {
111     u32              i;
112     TPLDescriptorPtr tdp;
113     void*            tex_buffer;
114 
115     GXSetCullMode(GX_CULL_BACK);
116 
117     // no zbuffer needed to create the sphere map
118     GXSetZMode(GX_FALSE, GX_ALWAYS, GX_FALSE);
119 
120     // sphere map geometry is using format 7
121     // this is for textured quad geometry
122     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
123     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
124 
125     //
126     // Initialize texture object for sphere map
127     //   - the data will be filled in each time drawSphereMap is called
128     //
129     for (i = 0; i < 2; i++)
130     {
131         tex_buffer = (void*)MEMAllocFromAllocator(&DemoAllocator1,
132             GXGetTexBufferSize(SPHERE_MAP_SIZE, SPHERE_MAP_SIZE,
133                                (u32)SPHERE_MAP_FMT,  GX_FALSE, 0));
134 
135         GXInitTexObj(
136             &SphereMap[i],
137             tex_buffer,
138             SPHERE_MAP_SIZE,
139             SPHERE_MAP_SIZE,
140             SPHERE_MAP_FMT,
141             GX_CLAMP,
142             GX_CLAMP,
143             GX_FALSE);
144     }
145 
146     // read pre-made cube map textures
147     // order of loading: right, front, left, back, top, bottom
148     OSReport("Opening gxTests/tg-cube.tpl\n");
149     TPLGetPalette(&tpl0, "gxTests/tg-cube.tpl");
150 
151     for (i = 0; i < 6; i++)
152     {
153         tdp = TPLGet(tpl0, i);
154         GXInitTexObj(&CubeMap0[i],
155                  tdp->textureHeader->data,
156                  tdp->textureHeader->width,
157                  tdp->textureHeader->height,
158                  (GXTexFmt)tdp->textureHeader->format,
159                  GX_CLAMP,
160                  GX_CLAMP,
161                  GX_FALSE);
162 
163         // alpha should be zero on edges, clamp so sphere outside
164         // projected texture is not overwritten
165         GXInitTexObjLOD(&CubeMap0[i],
166                     tdp->textureHeader->minFilter,
167                     tdp->textureHeader->magFilter,
168                     tdp->textureHeader->minLOD,
169                     tdp->textureHeader->maxLOD,
170                     tdp->textureHeader->LODBias,
171                     GX_FALSE,
172                     tdp->textureHeader->edgeLODEnable,
173                     GX_ANISO_1);
174     }
175 
176     // read pre-made cube map textures
177     // order of loading: right, front, left, back, top, bottom
178     OSReport("Opening gxTests/tg-cube1.tpl\n");
179     TPLGetPalette(&tpl1, "gxTests/tg-cube1.tpl");
180 
181     for (i = 0; i < 6; i++)
182     {
183         tdp = TPLGet(tpl1, i);
184         GXInitTexObj(&CubeMap1[i],
185                  tdp->textureHeader->data,
186                  tdp->textureHeader->width,
187                  tdp->textureHeader->height,
188                  (GXTexFmt)tdp->textureHeader->format,
189                  GX_CLAMP,
190                  GX_CLAMP,
191                  GX_FALSE);
192 
193         // alpha should be zero on edges, clamp so sphere outside
194         // projected texture is not overwritten
195         GXInitTexObjLOD(&CubeMap1[i],
196                     tdp->textureHeader->minFilter,
197                     tdp->textureHeader->magFilter,
198                     tdp->textureHeader->minLOD,
199                     tdp->textureHeader->maxLOD,
200                     tdp->textureHeader->LODBias,
201                     GX_FALSE,
202                     tdp->textureHeader->edgeLODEnable,
203                     GX_ANISO_1);
204     }
205 
206     // generate sphere geometry once
207     genMapSphere(&mySphere, &mySphereSz, SPHERE_MAP_TESS, GX_VTXFMT7);
208 }
209 
210 /*>*******************************(*)*******************************<*/
DrawTick(void)211 static void DrawTick    ( void )
212 {
213     // create sphere map texture
214     if (CurrentTexture) {
215         drawParaboloidMap(&CubeMap1[0], &SphereMap[0], mySphere, mySphereSz, 0);
216         drawParaboloidMap(&CubeMap1[0], &SphereMap[1], mySphere, mySphereSz, 1);
217     }
218     else {
219         drawParaboloidMap(&CubeMap0[0], &SphereMap[0], mySphere, mySphereSz, 0);
220         drawParaboloidMap(&CubeMap0[0], &SphereMap[1], mySphere, mySphereSz, 1);
221     }
222 
223     //
224     //  Draw sphere map texture on a quad
225     //
226     GXSetViewport(16.0F, 16.0F,
227                   400.0F, 400.0F,
228                   0.0F, 1.0F);
229 
230     GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
231     GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE);
232     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
233     GXSetNumTevStages(1);
234     GXSetNumTexGens(1);
235     GXSetNumChans(0);
236     GXSetBlendMode(GX_BM_BLEND, GX_BL_ONE, GX_BL_ZERO, GX_LO_SET);
237 
238     GXClearVtxDesc();
239     GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
240     GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
241 
242     GXInvalidateTexAll();
243     GXLoadTexObj(&SphereMap[0], GX_TEXMAP0);
244 
245     GXBegin(GX_QUADS, GX_VTXFMT0, 4);
246         GXPosition3f32(-1.0F, 1.0F, 0.0F);
247         GXTexCoord2f32( 0.0F, 0.0F);
248         GXPosition3f32( 0.0F, 1.0F, 0.0F);
249         GXTexCoord2f32( 1.0F, 0.0F);
250         GXPosition3f32( 0.0F, 0.0F, 0.0F);
251         GXTexCoord2f32( 1.0F, 1.0F);
252         GXPosition3f32(-1.0F, 0.0F, 0.0F);
253         GXTexCoord2f32( 0.0F, 1.0F);
254     GXEnd();
255 
256     GXLoadTexObj(&SphereMap[1], GX_TEXMAP0);
257     GXBegin(GX_QUADS, GX_VTXFMT0, 4);
258         GXPosition3f32(0.0F, 1.0F, 0.0F);
259         GXTexCoord2f32(0.0F, 0.0F);
260         GXPosition3f32(1.0F, 1.0F, 0.0F);
261         GXTexCoord2f32(1.0F, 0.0F);
262         GXPosition3f32(1.0F, 0.0F, 0.0F);
263         GXTexCoord2f32(1.0F, 1.0F);
264         GXPosition3f32(0.0F, 0.0F, 0.0F);
265         GXTexCoord2f32(0.0F, 1.0F);
266     GXEnd();
267 }
268 
269 /*>*******************************(*)*******************************<*/
AnimTick(void)270 static void AnimTick    ( void )
271 {
272     u16 buttons = DEMOPadGetButtonDown(0);
273 
274     MTXIdentity(m);
275     MTXConcat(v, m, mv);
276     GXLoadPosMtxImm(mv, GX_PNMTX0);
277     MTXInverse(mv, m);
278     MTXTranspose(m, m);
279     GXLoadNrmMtxImm(m, GX_PNMTX0);
280 
281     if (buttons & PAD_BUTTON_B) {
282         CubeFaceStart++;
283         CubeFaceEnd = (u8)(CubeFaceStart + 1);
284 
285         if (CubeFaceStart == 5) {
286             CubeFaceStart = 0;
287             CubeFaceEnd   = 1;
288         }
289 
290         switch(CubeFaceStart)
291         {
292             case 0: OSReport("left/right face\n"); break;
293             case 1: OSReport("right/front face\n"); break;
294             case 2: OSReport("back/left face\n"); break;
295             case 3: OSReport("bottom/top face\n"); break;
296             case 4: OSReport("top/bottom face\n"); break;
297         }
298     }
299 
300     if (buttons & PAD_BUTTON_A) {
301         CubeFaceStart = 0;
302         CubeFaceEnd   = 5;
303         OSReport("all faces\n");
304     }
305 
306     if (buttons & PAD_BUTTON_X) {
307         CurrentTexture ^= 1;
308         OSReport("Texture %d\n", CurrentTexture);
309     }
310 
311     if (buttons & PAD_BUTTON_Y) {
312         CubeTevMode++;
313         if (CubeTevMode > 4)
314             CubeTevMode = 0;
315 
316         switch (CubeTevMode)
317         {
318             case 0: OSReport("Final result\n"); break;
319             case 1: OSReport("Unclipped texture\n"); break;
320             case 2: OSReport("texture alpha\n"); break;
321             case 3: OSReport("Q-clipping (raster) alpha\n"); break;
322             case 4: OSReport("raster*texture alpha\n"); break;
323         }
324     }
325 }
326 
327 /*---------------------------------------------------------------------------*
328     Name:           PrintIntro
329 
330     Description:    Prints the directions on how to use this demo.
331 
332     Arguments:      none
333 
334     Returns:        none
335  *---------------------------------------------------------------------------*/
PrintIntro(void)336 static void PrintIntro( void )
337 {
338     OSReport("\n\n");
339     OSReport("*************************************************************\n");
340     OSReport("tg-parabolicmap: create a dual-paraboloid map from a cube map\n");
341     OSReport("*************************************************************\n");
342     OSReport("to quit hit the menu button\n");
343     OSReport("\n");
344     OSReport("A button   : display all cube faces in the paraboloid map\n");
345     OSReport("B button   : display individual cube faces\n");
346     OSReport("X button   : select the cube map texture\n");
347     OSReport("Y button   : select alpha/color channel to display\n");
348     OSReport("******************************************************\n");
349     OSReport("\n\n");
350 }
351 
352 /*===========================================================================*/
353