1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin/Revolution gx demo
3   File:     ind-bump-st.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 /******************************************************************************
15  *
16  *   (C) 1999, 2000 ARTX INC..  ALL RIGHTS RESERVED.  UNPUBLISHED -- RIGHTS
17  *   RESERVED UNDER THE COPYRIGHT LAWS OF THE UNITED STATES.  USE OF A
18  *   COPYRIGHT NOTICE IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION
19  *   OR DISCLOSURE.
20  *
21  *   THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND TRADE SECRETS OF
22  *   ARTX INC..  USE, DISCLOSURE, OR REPRODUCTION IS PROHIBITED WITHOUT
23  *   THE PRIOR EXPRESS WRITTEN PERMISSION OF ARTX INC..
24  *
25  *                   RESTRICTED RIGHTS LEGEND
26  *
27  *   Use, duplication, or disclosure by the Government is subject to
28  *   restrictions as set forth in subparagraph (c)(1)(ii) of the Rights
29  *   in Technical Data and Computer Software clause at DFARS 252.227-7013
30  *   or subparagraphs (c)(1) and (2) of Commercial Computer Software --
31  *   Restricted Rights at 48 CFR 52.227-19, as applicable.
32  *
33  *   ArtX Inc.
34  *   3400 Hillview Ave, Bldg 5
35  *   Palo Alto, CA 94304
36  *
37  *****************************************************************************/
38 
39 // Bump mapping test for bumpST method
40 
41 #include <demo.h>
42 #include <math.h>
43 
44 /*---------------------------------------------------------------------------*
45    Defines
46  *---------------------------------------------------------------------------*/
47 
48 #define TPL_NAME "gxTests/dnt-02.tpl"
49 
50 #define CAM_DIST 4                // Camera's distance from origin.
51 #define LIT_X_ANGLE 55.0f         // Rotation around X for light.
52 #define LIT_Y_ANGLE 45.0f         // Rotation around Y for light.
53 
54 #define LIT_TEX_FMT GX_TF_IA8     // 8-bits each for diffuse and specular.
55 
56 #define PI    3.14159265358979323846f
57 
58 #define NRM_SCALE 0.8f
59 
60 /*---------------------------------------------------------------------------*
61    Rendering parameters
62  *---------------------------------------------------------------------------*/
63 
64 u16 W=640, H=448;                 // Display size
65 u16 IW=256, IH=256;               // Indirect (bump) map size.
66 u16 TW=64, TH=64;                 // Light map size.
67 u16 TT=32, ST=32;                 // Light map tessellation
68 u16 TRS=5, TRT=3;                 // Material repetitions around donut.
69 u32 N1=20, N2=10;                 // Donut tessellation
70 f32 R1=1.0f, R2=0.5f;             // Donut radii.
71 
72 typedef struct
73 {
74     f32 x, y, z;
75     f32 nx, ny, nz;
76     f32 bx, by, bz;
77     f32 tx, ty, tz;
78     f32 s, t;
79 } coord;
80 
81 void * lightMap;
82 GXTexObj lightMapObj, materialObj, nPtrbObj;
83 
84 Mtx cameraMtx, objectMtx, lightMtx;
85 
86 coord * donutData;
87 
88 TPLPalettePtr tpl = NULL;
89 
90 u32 sendNormal, sendBinormals, sendCoords;
91 
92 /*---------------------------------------------------------------------------*
93    Forward references
94  *---------------------------------------------------------------------------*/
95 
96 coord donutCoord (u32 a, u32 b, u32 N1, u32 N2, f32 R1, f32 R2);
97 void createDonut();
98 void sendVertex(coord *d);
99 void setupMatrices(void);
100 void setupSize(u16 w, u16 h);
101 void commonInit(void);
102 void updateMatrices(u32 id, Mtx obj, Mtx cam);
103 void setLight(GXLightID litID, GXChannelID diffID, GXChannelID specID,
104               Mtx obj, Mtx cam);
105 void bumpMapSetup();
106 void bumpMapSetdown();
107 void lightMapSetup();
108 void renderSetup1();
109 void renderSetup2();
110 void updateDonut(Mtx cam, f32 r1, f32 r2, f32 x, f32 y, f32 z);
111 void drawDonut();
112 void drawHemisphere();
113 void showMaps();
114 void drawScene(Mtx cam, f32 r1, f32 r2);
115 void main(void);
116 static void PrintIntro( void );
117 
118 /*---------------------------------------------------------------------------*
119    Procedures
120  *---------------------------------------------------------------------------*/
121 
122 // Fill out a coordinate entry for a donut vertex.
donutCoord(u32 a,u32 b,u32 N1,u32 N2,f32 R1,f32 R2)123 coord donutCoord (u32 a, u32 b, u32 N1, u32 N2, f32 R1, f32 R2)
124 {
125     coord result;
126     f32 angle1, angle2;
127 
128     angle1 = (f32) a*2*PI/N1;
129     angle2 = (f32) b*2*PI/N2;
130 
131     result.x = (R1 - (R2*cosf(angle2))) * cosf(angle1);
132     result.y = (R1 - (R2*cosf(angle2))) * sinf(angle1);
133     result.z = R2 * sinf(angle2);
134 
135     result.nx = - cosf(angle2) * cosf(angle1);
136     result.ny = - cosf(angle2) * sinf(angle1);
137     result.nz = sinf(angle2);
138 
139     result.bx = - sinf(angle1);
140     result.by = cosf(angle1);
141     result.bz = 0;
142 
143     result.tx = sinf(angle2) * cosf(angle1);
144     result.ty = sinf(angle2) * sinf(angle1);
145     result.tz = cosf(angle2);
146 
147     result.s = (f32) a/(f32) N1;
148     result.t = (f32) b/(f32) N2;
149 
150     return result;
151 }
152 
153 // Make coordinate structures for all points on the donut.
createDonut()154 void createDonut()
155 {
156     u32 i,j;
157 
158     for (i=0; i<=N1; i++)
159         for (j=0; j<=N2; j++)
160             donutData[i*(N2+1) + j] = donutCoord(i, j, N1, N2, R1, R2);
161 }
162 
163 // Send one vertex from the given coordinate structure, sending only
164 // the information specified in the global variables:
165 // sendNormal, sendBinormals, sendCoords.
sendVertex(coord * d)166 void sendVertex(coord *d)
167 {
168     GXPosition3f32(d->x, d->y, d->z);
169 
170     if (sendNormal)
171         GXNormal3f32(d->nx, d->ny, d->nz);
172 
173     if (sendNormal && sendBinormals)
174     {
175         GXNormal3f32(d->bx, d->by, d->bz);
176         GXNormal3f32(d->tx, d->ty, d->tz);
177     }
178 
179     if (sendCoords)
180         GXTexCoord2f32(d->s, d->t);
181 }
182 
183 // Set up static matrices
setupMatrices(void)184 void setupMatrices(void)
185 {
186     Mtx tempMtx;
187 
188     MTXTrans(cameraMtx, 0, 0, -CAM_DIST);
189 
190     MTXTrans(lightMtx, 0, 0, -1000); // Make light "infinite"
191     MTXRotDeg(tempMtx, 'y', -LIT_Y_ANGLE);
192     MTXConcat(lightMtx, tempMtx, lightMtx);
193     MTXRotDeg(tempMtx, 'x', -LIT_X_ANGLE);
194     MTXConcat(lightMtx, tempMtx, lightMtx);
195 
196     MTXIdentity(objectMtx);
197 }
198 
199 // Setup viewport, scissor, copy, etc. based on w/h.
setupSize(u16 w,u16 h)200 void setupSize(u16 w, u16 h)
201 {
202     GXSetViewport(0, 0, w, h, 0, 1);
203     GXSetScissor(0, 0, w, h);
204     GXSetDispCopySrc(0, 0, w, h);
205     GXSetDispCopyDst(w, h);
206     GXSetDispCopyYScale(1);
207     GXSetTexCopySrc(0, 0, w, h);
208     GXSetTexCopyDst(w, h, LIT_TEX_FMT, FALSE);
209 }
210 
211 // Initialization routine common to all my tests.
commonInit(void)212 void commonInit(void)
213 {
214     GXColor black = {0,0,0,0};
215     DEMOInit(NULL);
216     GXInvalidateTexAll();
217     GXSetCopyClear( black, GX_MAX_Z24 );
218 
219     GXSetZMode(TRUE, GX_LEQUAL, TRUE);
220     GXSetZCompLoc(TRUE);
221     GXSetCullMode(GX_CULL_BACK);
222 
223     setupMatrices();
224 }
225 
226 // Set up position/normal/texture matrices and load.
updateMatrices(u32 id,Mtx obj,Mtx cam)227 void updateMatrices(u32 id, Mtx obj, Mtx cam)
228 {
229     Mtx vertexMtx, normalMtx, binormalMtx;
230     Mtx normalTexMtx, binormalTexMtx, textureMtx, tempMtx;
231 
232     // matrix for transforming vertices from object space to eye space.
233     MTXConcat(cam, obj, vertexMtx);
234 
235     // the normal mtx starts out as the inverse transpose of the vertex mtx
236     if (!MTXInverse(vertexMtx, tempMtx)) {ASSERTMSG(0,"Singular matrix!\n");}
237     MTXTranspose(tempMtx, normalMtx);
238 
239     // matrix for transforming normals from object space to eye space, then
240     // offset by 0.5,0.5, scale by NRM_SCALE/2.
241     MTXTrans(tempMtx, 0.5f, 0.5f, 0.0f);
242     MTXConcat(tempMtx, normalMtx, normalTexMtx);
243     MTXScale(tempMtx, NRM_SCALE/2, NRM_SCALE/2, NRM_SCALE/2);
244     MTXConcat(normalTexMtx, tempMtx, normalTexMtx);
245 
246     // the binormal/tangent mtx starts out as the vertex mtx without translate
247     // it should not use the inverse transpose of the vertex mtx
248     MTXCopy(vertexMtx, binormalMtx);
249     binormalMtx[0][3] = 0.0f;
250     binormalMtx[1][3] = 0.0f;
251     binormalMtx[2][3] = 0.0f;
252 
253     // matrix for transforming binormals from object space to eye space, then
254     // scale by NRM_SCALE/2.
255     MTXConcat(binormalMtx, tempMtx, binormalTexMtx);
256 
257     // matrix for specifying material repetitions
258     MTXScale(textureMtx, TRS, TRT, 1.0f);
259 
260     GXLoadPosMtxImm(vertexMtx, GX_PNMTX0 + id*3);
261     GXLoadNrmMtxImm(normalMtx, GX_PNMTX0 + id*3);
262     GXLoadTexMtxImm(textureMtx, GX_TEXMTX0, GX_MTX2x4);
263     GXLoadTexMtxImm(normalTexMtx, GX_TEXMTX1 + id*6, GX_MTX2x4);
264     GXLoadTexMtxImm(binormalTexMtx, GX_TEXMTX2 + id*6, GX_MTX2x4);
265 }
266 
267 // Create an infinite light with diffuse and specular components.
setLight(GXLightID litID,GXChannelID diffID,GXChannelID specID,Mtx obj,Mtx cam)268 void setLight(GXLightID litID, GXChannelID diffID, GXChannelID specID,
269               Mtx obj, Mtx cam)
270 {
271     GXLightObj light;
272     Mtx   tempMtx, litMtx;
273     Vec   lPos = {0,0,0}, lDir = {0,0,-1};
274     GXColor color0 = {0x88,0x88,0x88,0xff};
275     GXColor color1 = {0x20,0x20,0x20,0x20};
276     GXColor color2 = {0xff,0xff,0xff,0xff};
277     GXColor color3 = {0x00,0x00,0x00,0x00};
278     GXColor color4 = {0x7f,0x7f,0x7f,0x7f};
279 
280     // Calculate light position and direction.
281     if (!MTXInverse(obj, tempMtx)) {ASSERTMSG(0,"Singular matrix!\n");}
282     MTXConcat(cam, tempMtx, litMtx);
283     MTXMultVec(litMtx, &lPos, &lPos);
284 
285     if (!MTXInverse(litMtx, tempMtx)) {ASSERTMSG(0,"Singular matrix!\n");}
286     MTXTranspose(tempMtx, litMtx);
287     MTXMultVec(litMtx, &lDir, &lDir);
288 
289     // Setup light object.
290     // GXInitLightPos(&light, lPos.x, lPos.y, lPos.z);
291     GXInitSpecularDir(&light, lDir.x, lDir.y, lDir.z);
292     GXInitLightColor(&light, color0 );
293 
294     // Light equation 4x^2 - 3. x=N*H.
295     GXInitLightAttn(&light, -3.0f, 0.0f, 4.0f, 1.0f, 0.0f, 0.0f);
296     GXLoadLightObjImm(&light, litID);
297 
298     // Set material and ambient color.
299     GXSetChanAmbColor(diffID, color1 );
300     GXSetChanMatColor(diffID, color2 );
301     GXSetChanAmbColor(specID, color3 );
302     GXSetChanMatColor(specID, color4 );
303 }
304 
305 // Initial setup for shadowing (setup texture).
bumpMapSetup(void)306 void bumpMapSetup(void)
307 {
308     u32 size;
309     f32 indMtx[2][3] = { { 0.5F, 0.0F, 0.0F, },   // Indirect "identity" mtx
310                          { 0.0F, 0.5F, 0.0F, } }; // (not used)
311 
312     // Pre-existing textures are in a tpl file.
313     TPLGetPalette(&tpl, TPL_NAME);
314 
315     // Light Map Texture (generated)
316 
317     // Allocate texture in main memory.
318     lightMap = MEMAllocFromAllocator(&DemoAllocator1, GXGetTexBufferSize(TW, TH, LIT_TEX_FMT, FALSE, 0));
319 
320     // Create texture object.
321     GXInitTexObj(&lightMapObj, lightMap, TW, TH, LIT_TEX_FMT,
322                  GX_CLAMP, GX_CLAMP, FALSE);
323 
324     // Load object into hw. Lightmap will be TEXMAP1.
325     GXLoadTexObj(&lightMapObj, GX_TEXMAP1);
326 
327     // Material Texture (pre-existing)
328 
329     TPLGetGXTexObjFromPalette(tpl, &materialObj, 1);
330     GXLoadTexObj(&materialObj, GX_TEXMAP0); // Material will be TEXMAP0
331 
332     // Normal Perturbation Texture (pre-existing)
333 
334     TPLGetGXTexObjFromPalette(tpl, &nPtrbObj, 0);
335     GXLoadTexObj(&nPtrbObj, GX_TEXMAP2); // Normal perturbation will be TEXMAP2
336 
337     // Set up texgen for rendering. The matrices can be changed per-object,
338     // but the texgen needn't change.
339     GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX0);
340     GXSetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_BINRM,   GX_TEXMTX2);
341     GXSetTexCoordGen(GX_TEXCOORD2, GX_TG_MTX2x4, GX_TG_TANGENT, GX_TEXMTX2);
342     GXSetTexCoordGen(GX_TEXCOORD3, GX_TG_MTX2x4, GX_TG_NRM, GX_TEXMTX1);
343 
344     // I will always use position matrix 0 for my geometry.
345     GXSetCurrentMtx(GX_PNMTX0);
346 
347     // Diffuse is color 0, specular is alpha 0.
348     setLight(GX_LIGHT0, GX_COLOR0, GX_ALPHA0, lightMtx, cameraMtx);
349 
350     // Set indirect matrix and scale to be "identity" for 64x64 textures.
351     GXSetIndTexMtx(GX_ITM_0, indMtx, 0);
352 
353     // Alpha component in frame buffer will be written to.
354     GXSetAlphaUpdate(TRUE);
355 
356     // Make a donut.
357     size = sizeof(coord) * (N1+1)*(N2+1);
358     donutData = MEMAllocFromAllocator(&DemoAllocator1, size);
359     createDonut();
360 }
361 
bumpMapSetdown(void)362 void bumpMapSetdown(void)
363 {
364     TPLReleasePalette(&tpl);
365 
366     MEMFreeToAllocator(&DemoAllocator1, lightMap);
367     MEMFreeToAllocator(&DemoAllocator1, donutData);
368 }
369 
370 // Per-frame setup for actual render.
renderSetup1(void)371 void renderSetup1(void)
372 {
373     Mtx44 pMtx;
374 
375     // Set the rendering size.
376     setupSize(W, H);
377 
378     // Perspective projection
379     // Note that NEGATIVE Y is up for this demo!
380     MTXFrustum(pMtx, -1, 1, -1, 1, 1, 15);
381     GXSetProjection(pMtx, GX_PERSPECTIVE);
382 
383     // Pixel format
384     GXSetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR);
385     // We don't need to clear the display again
386 
387     // Disable lights
388     GXSetChanCtrl(GX_COLOR0, FALSE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT0,
389                   GX_DF_NONE, GX_AF_NONE);
390     GXSetChanCtrl(GX_ALPHA0, FALSE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT0,
391                   GX_DF_NONE, GX_AF_NONE);
392 }
393 
renderSetup2(void)394 void renderSetup2(void)
395 {
396     // Four tev stages, one Bump stage.
397     GXSetNumTevStages(4);
398     GXSetNumIndStages(1);
399 
400     // Four texture coordinates, no colors.
401     GXSetNumTexGens(4);
402     GXSetNumChans(0);
403 
404     // Indirect Stage 0 -- Sample normal perturbation map
405     GXSetIndTexOrder(GX_INDTEXSTAGE0, GX_TEXCOORD0, GX_TEXMAP2);
406     GXSetIndTexCoordScale(GX_INDTEXSTAGE0, GX_ITS_1, GX_ITS_1);
407 
408     // Stage 0 -- Save material texture
409     //
410     // TEVPREV = TEXC/TEXA
411     //
412     GXSetTevDirect(GX_TEVSTAGE0);
413     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
414     GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE);
415 
416     // Set up the indirect bump calculation for Stages 1-3
417     //
418     GXSetTevIndBumpST(GX_TEVSTAGE1, GX_INDTEXSTAGE0, GX_ITM_0);
419 
420     // Stage 1 -- Accumulate binormal perturbation component in Bump
421     //
422     // TEVPREV = PREV
423     //
424     GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1,
425                   (GXTexMapID)(GX_TEXMAP1|GX_TEX_DISABLE), GX_COLOR_NULL);
426     GXSetTevOp(GX_TEVSTAGE1, GX_PASSCLR);
427 
428     // Stage 2 -- Accumulate tangent perturbation component in Bump
429     //
430     // TEVPREV = PREV
431     //
432     GXSetTevOrder(GX_TEVSTAGE2, GX_TEXCOORD2,
433                   (GXTexMapID)(GX_TEXMAP1|GX_TEX_DISABLE), GX_COLOR_NULL);
434     GXSetTevOp(GX_TEVSTAGE2, GX_PASSCLR);
435 
436     // Stage 3 -- Add source normal in Bump. Index lightmap with result of
437     //            perturbation. Apply diffuse and specular components.
438     //
439     // TEVPREVC = PREVC * TEXC + TEXA
440     // TEVPREVA = PREVA
441     //
442     GXSetTevOrder(GX_TEVSTAGE3, GX_TEXCOORD3, GX_TEXMAP1, GX_COLOR_NULL);
443     GXSetTevColorIn(GX_TEVSTAGE3,
444                     GX_CC_ZERO, GX_CC_CPREV, GX_CC_TEXC, GX_CC_TEXA);
445     GXSetTevAlphaIn(GX_TEVSTAGE3,
446                     GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV);
447     GXSetTevColorOp(GX_TEVSTAGE3,
448                     GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, TRUE, GX_TEVPREV);
449     GXSetTevAlphaOp(GX_TEVSTAGE3,
450                     GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, TRUE, GX_TEVPREV);
451 
452 
453     // Vertex packet specification -- Position, normal/tangent/binormal,
454     //                                and one pair of texture coordinates.
455     GXClearVtxDesc();
456     GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
457     GXSetVtxDesc(GX_VA_NBT, GX_DIRECT);
458     GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
459     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
460     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NBT, GX_NRM_NBT, GX_F32, 0);
461     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
462 
463     sendNormal = TRUE;
464     sendBinormals = TRUE;
465     sendCoords = TRUE;
466 }
467 
468 // Per-frame setup for light map.
lightMapSetup(void)469 void lightMapSetup(void)
470 {
471     Mtx44 pMtx;
472     Mtx   idMtx;
473 
474     // Set the rendering size.
475     setupSize(TW, TH);
476 
477     // Orthographic projection
478     MTXOrtho(pMtx, -1, 1, -1, 1, 1, 15);
479     GXSetProjection(pMtx, GX_ORTHOGRAPHIC);
480 
481     // Pixel format
482     GXSetPixelFmt(GX_PF_RGBA6_Z24, GX_ZC_LINEAR);
483     // don't need to re-clear, since we will overwrite everything we use
484 
485     // Enable diffuse and specular lights.
486     // COLOR0 = diffuse
487     // ALPHA0 = specular
488     GXSetChanCtrl(GX_COLOR0, TRUE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT0,
489                   GX_DF_CLAMP, GX_AF_NONE);
490     GXSetChanCtrl(GX_ALPHA0, TRUE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT0,
491                   GX_DF_NONE, GX_AF_SPEC);
492 
493     // One tev stage.
494     GXSetNumTevStages(1);
495 
496     // No textures, one color.
497     GXSetNumTexGens(0);
498     GXSetNumChans(1);
499     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
500 
501     // Stage 0 -- Send out rasterized color.
502     //
503     // TEVPREV = RAS
504     //
505     GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
506 
507     // Vertex packet specification -- Position and normal.
508     GXClearVtxDesc();
509     GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
510     GXSetVtxDesc(GX_VA_NRM, GX_DIRECT);
511     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
512     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
513 
514     sendNormal = TRUE;
515     sendBinormals = FALSE;
516     sendCoords = FALSE;
517 
518     // Identity matrices for object and matrix.
519     MTXIdentity(idMtx);
520     updateMatrices(0, idMtx, idMtx);
521 }
522 
523 // Prepare for donut drawing.
updateDonut(Mtx cam,f32 r1,f32 r2,f32 x,f32 y,f32 z)524 void updateDonut(Mtx cam, f32 r1, f32 r2, f32 x, f32 y, f32 z)
525 {
526     Mtx donutMtx, tempMtx;
527 
528     // update object matrix for this donut.
529     MTXRotDeg(tempMtx, 'x', r2);
530     MTXConcat(tempMtx, objectMtx, objectMtx);
531     MTXRotDeg(tempMtx, 'y', r1);
532     MTXConcat(tempMtx, objectMtx, objectMtx);
533     MTXTrans(tempMtx, x, y, z);
534     MTXConcat(tempMtx, objectMtx, donutMtx);
535 
536     // Create all other matrices derived from this object matrix.
537     updateMatrices(0, donutMtx, cam);
538 }
539 
540 // Draw a donut.
drawDonut()541 void drawDonut()
542 {
543     u32 i,j;
544 
545     for (i=0; i<N1; i++)
546     {
547         GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT0, (u16) ((N2+1)*2) );
548 
549         for (j=0; j<=N2; j++)
550         {
551             sendVertex(&donutData[(i+1)*(N2+1) + j]);
552             sendVertex(&donutData[i*(N2+1) + j]);
553         }
554 
555         GXEnd();
556     }
557 }
558 
559 // Draw a tesselated square, with normals that make it look like a hemisphere.
drawHemisphere()560 void drawHemisphere()
561 {
562     u32 i, j;
563     coord c;
564 
565     for (i=0; i<ST; i++)
566     {
567         GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT0, (u16) (TT*2 + 2));
568 
569         for (j=0; j<=TT; j++)
570         {
571             c.x = ((f32) 2.0f*i/ST) - 1.0f;
572             c.y = ((f32) 2.0f*j/TT) - 1.0f;
573             c.z = -2.0f;
574             c.nx = c.x / NRM_SCALE;
575             c.ny = c.y / NRM_SCALE;
576             c.nz = c.x*c.x + c.y*c.y;
577             c.nz = c.nz < 1 ? sqrtf(1 - c.nz) : 0;
578             sendVertex(&c);
579 
580             c.x = ((f32) 2.0f*(i+1)/ST) - 1.0f;
581             c.nx = c.x / NRM_SCALE;
582             c.nz = c.x*c.x + c.y*c.y;
583             c.nz = c.nz < 1 ? sqrtf(1 - c.nz) : 0;
584             sendVertex(&c);
585         }
586 
587         GXEnd();
588     }
589 }
590 
591 // Draw the full scene from a specific camera.
drawScene(Mtx cam,f32 r1,f32 r2)592 void drawScene(Mtx cam, f32 r1, f32 r2)
593 {
594     // Draw one donut, centered at 0,0,0, rotating at normal speed.
595     updateDonut(cam, r1, r2, 0.0f, 0.0f, 0.0f);
596     drawDonut();
597 }
598 
599 //  Show the generated light maps in the corners of the screen
600 //  Also show bump textures
showMaps()601 void showMaps()
602 {
603     Mtx   idMtx;
604     coord c;
605 
606     // One tev stage.
607     GXSetNumTevStages(1);
608     GXSetNumIndStages(0);
609 
610     // One texture, no color.
611     GXSetNumTexGens(1);
612     GXSetNumChans(0);
613     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP1, GX_COLOR_NULL);
614 
615     // Stage 0 -- Send out texture color.
616     //
617     // TEVPREV = TEXC
618     //
619     GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE);
620     GXSetTevAlphaIn(GX_TEVSTAGE0,GX_CA_ZERO,GX_CA_ZERO,GX_CA_ZERO,GX_CA_ONE);
621 
622     // Vertex packet specification -- Position and normal.
623     GXClearVtxDesc();
624     GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
625     GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
626     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
627     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
628 
629     sendNormal = FALSE;
630     sendBinormals = FALSE;
631     sendCoords = TRUE;
632 
633     // Identity matrices for object and matrix.
634     MTXIdentity(idMtx);
635     GXLoadPosMtxImm(idMtx, GX_PNMTX0);
636     GXLoadTexMtxImm(idMtx, GX_TEXMTX0, GX_MTX2x4);
637 
638     // Show diffuse light map
639     GXBegin(GX_QUADS, GX_VTXFMT0, 4);
640     c.x = -1.0f;
641     c.y = -1.0f;
642     c.z = -1.0f;
643     c.s =  0.0f;
644     c.t =  0.0f;
645     sendVertex(&c);
646     c.x += (f32) TW/W*2;
647     c.s  = 1.0f;
648     sendVertex(&c);
649     c.y += (f32) TH/H*2;
650     c.t  = 1.0f;
651     sendVertex(&c);
652     c.x -= (f32) TW/W*2;
653     c.s  = 0.0f;
654     sendVertex(&c);
655     GXEnd();
656 
657     // Now show alpha (specular) map
658     GXSetTevColorIn(GX_TEVSTAGE0,GX_CC_ZERO,GX_CC_ZERO,GX_CC_ZERO,GX_CC_TEXA);
659 
660     GXBegin(GX_QUADS, GX_VTXFMT0, 4);
661     c.x =  1.0f;
662     c.y = -1.0f;
663     c.z = -1.0f;
664     c.s =  1.0f;
665     c.t =  0.0f;
666     sendVertex(&c);
667     c.y += (f32) TH/H*2;
668     c.t  = 1.0f;
669     sendVertex(&c);
670     c.x -= (f32) TW/W*2;
671     c.s  = 0.0f;
672     sendVertex(&c);
673     c.y -= (f32) TH/H*2;
674     c.t  = 0.0f;
675     sendVertex(&c);
676     GXEnd();
677 
678     // Now show the S component of the bump map
679     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP2, GX_COLOR_NULL);
680 
681     GXBegin(GX_QUADS, GX_VTXFMT0, 4);
682     c.x = -1.0f;
683     c.y =  1.0f;
684     c.z = -1.0f;
685     c.s =  0.0f;
686     c.t =  1.0f;
687     sendVertex(&c);
688     c.y -= (f32) IH/H;
689     c.t  = 0.0f;
690     sendVertex(&c);
691     c.x += (f32) IW/W;
692     c.s  = 1.0f;
693     sendVertex(&c);
694     c.y += (f32) IH/H;
695     c.t  = 1.0f;
696     sendVertex(&c);
697     GXEnd();
698 
699     // Now show the T component of the bump map
700     GXSetTevColorIn(GX_TEVSTAGE0,GX_CC_ZERO,GX_CC_ZERO,GX_CC_ZERO,GX_CC_TEXC);
701 
702     GXBegin(GX_QUADS, GX_VTXFMT0, 4);
703     c.x =  1.0f;
704     c.y =  1.0f;
705     c.z = -1.0f;
706     c.s =  1.0f;
707     c.t =  1.0f;
708     sendVertex(&c);
709     c.x -= (f32) IW/W;
710     c.s  = 0.0f;
711     sendVertex(&c);
712     c.y -= (f32) IH/H;
713     c.t  = 0.0f;
714     sendVertex(&c);
715     c.x += (f32) IW/W;
716     c.s  = 1.0f;
717     sendVertex(&c);
718     GXEnd();
719 }
720 
721 /*---------------------------------------------------------------------------*
722    Application main loop
723  *---------------------------------------------------------------------------*/
724 
main(void)725 void main(void)
726 {
727     f32 rot1=0.0f;
728     f32 rot2=0.0f;
729 
730     commonInit();  // Same init for all tests.
731 
732     bumpMapSetup(); // Setup texture objects and all other static things.
733 
734     // This is only done once in this test since the camera and light never
735     // change direction with respect to one another. If they ever do, the
736     // lightmap must be regenerated.
737     lightMapSetup();  // Setup for lightmap render.
738     drawHemisphere(); // Render hemisphere lightmap
739 
740     GXCopyTex(lightMap, FALSE); // Copy to texture.
741     GXPixModeSync();
742 
743     PrintIntro();
744 
745     while(!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
746     {
747         DEMOPadRead();
748 
749         rot1 = DEMOPadGetStickX(0)/10;
750         rot2 = DEMOPadGetStickY(0)/10;
751         DEMOBeforeRender();
752 
753         renderSetup1();   // Setup for actual render, part 1.
754 
755         showMaps();       // Show the lightmaps used
756 
757         renderSetup2();   // Setup for actual render, part 2.
758 
759         drawScene(cameraMtx, rot1, rot2);
760 
761         DEMODoneRender();
762     }
763 
764     bumpMapSetdown(); // Free memory and such.
765 
766     OSHalt("End of demo");
767 }
768 
769 /*---------------------------------------------------------------------------*
770     Name:           PrintIntro
771 
772     Description:    Prints the directions on how to use this demo.
773 
774     Arguments:      none
775 
776     Returns:        none
777  *---------------------------------------------------------------------------*/
PrintIntro(void)778 static void PrintIntro( void )
779 {
780     OSReport("\n\n");
781     OSReport("************************************************\n");
782     OSReport("ind-bump-st: show indirect texture bump mapping\n");
783     OSReport("************************************************\n");
784     OSReport("to quit hit the start button\n");
785     OSReport("\n");
786     OSReport("  Stick X/Y    : rotate the donut\n");
787     OSReport("************************************************\n\n");
788 }
789 
790