1 /*---------------------------------------------------------------------------*
2 Project: Dolphin/Revolution gx demo
3 File: ind-bump-xyz.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 bumpXYZ method
40
41 #include <demo.h>
42 #include <math.h>
43
44 /*---------------------------------------------------------------------------*
45 Defines
46 *---------------------------------------------------------------------------*/
47
48 #define TPL_NAME "gxTests/dnt-03.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=384; // Indirect (bump) map size.
66 f32 IS=2.0f/3.0f; // Scale parameter for displaying indirect maps
67 u16 TW=64, TH=64; // Light map size.
68 u16 TT=32, ST=32; // Light map tessellation
69
70 typedef struct
71 {
72 f32 x, y, z;
73 f32 nx, ny, nz;
74 f32 s, t;
75 u16 tc, pad;
76 } coord;
77
78 u32 face[9] = { // For each of the 9 cubes, which sides to draw
79 //FRBLUD Front Right Back Left Up Down sides of cube
80 0x2E, // 101110
81 0x2B, // 101011
82 0x3A, // 111010
83 0x3C, // 111100
84 0x00, // 000000
85 0x3C, // 111100
86 0x2D, // 101101
87 0x2B, // 101011
88 0x39, // 111001
89 };
90
91 f32 tcoords[12][2] ATTRIBUTE_ALIGN(32) = { // texture coordinate array
92 { 0.0f, 0.0f }, // 0
93 { 0.5f, 0.0f }, // 1
94 { 1.0f, 0.0f }, // 2
95 { 0.0f, 0.25f }, // 3
96 { 0.5f, 0.25f }, // 4
97 { 1.0f, 0.25f }, // 5
98 { 0.0f, 0.50f }, // 6
99 { 0.5f, 0.50f }, // 7
100 { 1.0f, 0.50f }, // 8
101 { 0.0f, 0.75f }, // 9
102 { 0.5f, 0.75f }, // 10
103 { 1.0f, 0.75f } // 11
104 };
105
106 coord cube[6][4] ATTRIBUTE_ALIGN(32);
107
108 void * lightMap;
109 GXTexObj lightMapObj, materialObj, nPtrbObj;
110
111 Mtx cameraMtx, objectMtx, lightMtx;
112
113 TPLPalettePtr tpl = NULL;
114
115 u32 sendNormal, sendIndex, sendCoords;
116
117 /*---------------------------------------------------------------------------*
118 Forward references
119 *---------------------------------------------------------------------------*/
120
121 void createCube();
122 void sendVertex(coord *d);
123 void setupMatrices(void);
124 void setupSize(u16 w, u16 h);
125 void commonInit(void);
126 void updateMatrices(u32 id, Mtx obj, Mtx cam);
127 void setLight(GXLightID litID, GXChannelID diffID, GXChannelID specID,
128 Mtx obj, Mtx cam);
129 void bumpMapSetup();
130 void bumpMapSetdown();
131 void lightMapSetup();
132 void renderSetup1();
133 void renderSetup2();
134 void updateDonut(Mtx cam, f32 r1, f32 r2, f32 x, f32 y, f32 z);
135 void drawDonut();
136 void drawHemisphere();
137 void showMaps();
138 void drawScene(Mtx cam, f32 r1, f32 r2);
139 void main(void);
140 static void PrintIntro( void );
141
142 /*---------------------------------------------------------------------------*
143 Procedures
144 *---------------------------------------------------------------------------*/
145
146 // Create cube
createCube()147 void createCube()
148 {
149 int i;
150 f32 h, v;
151
152 for(i=0; i<4; i++)
153 {
154 h = ((i % 3)!=0) - 0.5f;
155 v = - (i / 2) + 0.5f;
156
157 cube[0][i].x = h;
158 cube[0][i].y = v;
159 cube[0][i].z = 0.5f;
160 cube[1][i].x = 0.5f;
161 cube[1][i].y = v;
162 cube[1][i].z = -h;
163 cube[2][i].x = -h;
164 cube[2][i].y = v;
165 cube[2][i].z = -0.5f;
166 cube[3][i].x = -0.5f;
167 cube[3][i].y = v;
168 cube[3][i].z = h;
169 cube[4][i].x = h;
170 cube[4][i].y = 0.5f;
171 cube[4][i].z = -v;
172 cube[5][i].x = h;
173 cube[5][i].y = -0.5f;
174 cube[5][i].z = v;
175
176 cube[0][i].nx = 0;
177 cube[0][i].ny = 0;
178 cube[0][i].nz = 1;
179 cube[1][i].nx = 1;
180 cube[1][i].ny = 0;
181 cube[1][i].nz = 0;
182 cube[2][i].nx = 0;
183 cube[2][i].ny = 0;
184 cube[2][i].nz = -1;
185 cube[3][i].nx = -1;
186 cube[3][i].ny = 0;
187 cube[3][i].nz = 0;
188 cube[4][i].nx = 0;
189 cube[4][i].ny = 1;
190 cube[4][i].nz = 0;
191 cube[5][i].nx = 0;
192 cube[5][i].ny = -1;
193 cube[5][i].nz = 0;
194 }
195
196 cube[0][0].tc = 0;
197 cube[0][1].tc = 1;
198 cube[0][2].tc = 4;
199 cube[0][3].tc = 3;
200
201 cube[1][0].tc = 1;
202 cube[1][1].tc = 2;
203 cube[1][2].tc = 5;
204 cube[1][3].tc = 4;
205
206 cube[2][0].tc = 3;
207 cube[2][1].tc = 4;
208 cube[2][2].tc = 7;
209 cube[2][3].tc = 6;
210
211 cube[3][0].tc = 4;
212 cube[3][1].tc = 5;
213 cube[3][2].tc = 8;
214 cube[3][3].tc = 7;
215
216 cube[4][0].tc = 6;
217 cube[4][1].tc = 7;
218 cube[4][2].tc = 10;
219 cube[4][3].tc = 9;
220
221 cube[5][0].tc = 7;
222 cube[5][1].tc = 8;
223 cube[5][2].tc = 11;
224 cube[5][3].tc = 10;
225 }
226
227 // Send one vertex from the given coordinate structure.
sendVertex(coord * d)228 void sendVertex(coord *d)
229 {
230 GXPosition3f32(d->x, d->y, d->z);
231
232 if (sendNormal)
233 GXNormal3f32(d->nx, d->ny, d->nz);
234
235 if (sendIndex)
236 GXTexCoord1x16(d->tc);
237
238 if (sendCoords)
239 GXTexCoord2f32(d->s, d->t);
240 }
241
242 // Set up static matrices
setupMatrices(void)243 void setupMatrices(void)
244 {
245 Mtx tempMtx;
246
247 MTXTrans(cameraMtx, 0, 0, -CAM_DIST);
248
249 MTXTrans(lightMtx, 0, 0, -1000); // Make light "infinite"
250 MTXRotDeg(tempMtx, 'y', -(LIT_Y_ANGLE));
251 MTXConcat(lightMtx, tempMtx, lightMtx);
252 MTXRotDeg(tempMtx, 'x', -(LIT_X_ANGLE));
253 MTXConcat(lightMtx, tempMtx, lightMtx);
254
255 MTXIdentity(objectMtx);
256 }
257
258 // Setup viewport, scissor, copy, etc. based on w/h.
setupSize(u16 w,u16 h)259 void setupSize(u16 w, u16 h)
260 {
261 GXSetViewport(0, 0, w, h, 0, 1);
262 GXSetScissor(0, 0, w, h);
263 GXSetDispCopySrc(0, 0, w, h);
264 GXSetDispCopyDst(w, h);
265 GXSetDispCopyYScale(1);
266 GXSetTexCopySrc(0, 0, w, h);
267 GXSetTexCopyDst(w, h, LIT_TEX_FMT, FALSE);
268 }
269
270 // Initialization routine common to all my tests.
commonInit(void)271 void commonInit(void)
272 {
273 GXColor black = {0, 0, 0, 0};
274
275 DEMOInit(NULL);
276 GXInvalidateTexAll();
277 GXSetCopyClear( black, GX_MAX_Z24 );
278
279 GXSetZMode(TRUE, GX_LEQUAL, TRUE);
280 GXSetZCompLoc(TRUE);
281 GXSetCullMode(GX_CULL_BACK);
282
283 GXSetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA);
284 GXSetTevSwapModeTable(GX_TEV_SWAP1, GX_CH_RED, GX_CH_RED, GX_CH_RED, GX_CH_ALPHA);
285 GXSetTevSwapModeTable(GX_TEV_SWAP2, GX_CH_GREEN, GX_CH_GREEN, GX_CH_GREEN, GX_CH_ALPHA);
286 GXSetTevSwapModeTable(GX_TEV_SWAP3, GX_CH_BLUE, GX_CH_BLUE, GX_CH_BLUE, GX_CH_ALPHA);
287
288 setupMatrices();
289 }
290
291 // Set up position/normal/texture matrices and load.
updateMatrices(u32 id,Mtx obj,Mtx cam)292 void updateMatrices(u32 id, Mtx obj, Mtx cam)
293 {
294 Mtx vertexMtx, normalMtx, bumpnormalMtx;
295 Mtx normalTexMtx, textureMtx, tempMtx;
296 f32 indMtx[2][3];
297
298 // matrix for transforming vertices from object space to eye space.
299 MTXConcat(cam, obj, vertexMtx);
300
301 // the normal mtx starts out as the inverse transpose of the vertex mtx
302 if (!MTXInverse(vertexMtx, tempMtx)) {ASSERTMSG(0,"Singular matrix!\n");}
303 MTXTranspose(tempMtx, normalMtx);
304
305 // matrix for transforming normals from object space to eye space,
306 // scale by NRM_SCALE/2, offset by 0.5,0.5.
307 // the negation in Y is needed since the T axis is opposite of the Y axis
308 MTXScale(tempMtx, NRM_SCALE/2, -NRM_SCALE/2, NRM_SCALE/2);
309 MTXConcat(tempMtx, normalMtx, normalTexMtx);
310 MTXTrans(tempMtx, 0.5f, 0.5f, 0.0f);
311 MTXConcat(tempMtx, normalTexMtx, normalTexMtx);
312
313 // matrix for transforming bump offsets
314 // take normal mtx, then scale by NRM_SCALE/2
315 // the negation in [1][1] is needed since the T axis is opposite of the Y axis
316 MTXScale(tempMtx, NRM_SCALE/2, NRM_SCALE/2, NRM_SCALE/2);
317 MTXConcat(tempMtx, normalMtx, bumpnormalMtx);
318 indMtx[0][0] = bumpnormalMtx[0][0];
319 indMtx[0][1] = bumpnormalMtx[0][1];
320 indMtx[0][2] = bumpnormalMtx[0][2];
321 indMtx[1][0] = bumpnormalMtx[1][0];
322 indMtx[1][1] = -bumpnormalMtx[1][1];
323 indMtx[1][2] = bumpnormalMtx[1][2];
324 // set indirect matrix and scale
325 GXSetIndTexMtx(GX_ITM_0, indMtx, 0);
326
327 // matrix for specifying material repetitions
328 MTXScale(textureMtx, 1.0f, 1.0f, 1.0f); // no repetitions for this demo
329
330 GXLoadPosMtxImm(vertexMtx, GX_PNMTX0 + id*3);
331 GXLoadNrmMtxImm(normalMtx, GX_PNMTX0 + id*3);
332 GXLoadTexMtxImm(textureMtx, GX_TEXMTX0, GX_MTX2x4);
333 GXLoadTexMtxImm(normalTexMtx, GX_TEXMTX1 + id*6, GX_MTX2x4);
334 }
335
336 // Create an infinite light with diffuse and specular components.
setLight(GXLightID litID,GXChannelID diffID,GXChannelID specID,Mtx obj,Mtx cam)337 void setLight(GXLightID litID, GXChannelID diffID, GXChannelID specID,
338 Mtx obj, Mtx cam)
339 {
340 GXLightObj light;
341 Mtx tempMtx, litMtx;
342 Vec lPos = {0,0,0}, lDir = {0,0,-1};
343 GXColor color0 = {0x88,0x88,0x88,0xff};
344 GXColor color1 = {0x20,0x20,0x20,0x20};
345 GXColor color2 = {0xff,0xff,0xff,0xff};
346 GXColor color3 = {0x00,0x00,0x00,0x00};
347 GXColor color4 = {0x7f,0x7f,0x7f,0x7f};
348
349 // Calculate light position and direction.
350 if (!MTXInverse(obj, tempMtx)) {ASSERTMSG(0,"Singular matrix!\n");}
351 MTXConcat(cam, tempMtx, litMtx);
352 MTXMultVec(litMtx, &lPos, &lPos);
353
354 if (!MTXInverse(litMtx, tempMtx)) {ASSERTMSG(0,"Singular matrix!\n");}
355 MTXTranspose(tempMtx, litMtx);
356 MTXMultVec(litMtx, &lDir, &lDir);
357
358 // Setup light object.
359 // GXInitLightPos(&light, lPos.x, lPos.y, lPos.z);
360 GXInitSpecularDir(&light, lDir.x, lDir.y, lDir.z);
361 GXInitLightColor(&light, color0 );
362
363 // Light equation 4x^2 - 3. x=N*H.
364 GXInitLightAttn(&light, -3.0f, 0.0f, 4.0f, 1.0f, 0.0f, 0.0f);
365 GXLoadLightObjImm(&light, litID);
366
367 // Set material and ambient color.
368 GXSetChanAmbColor(diffID, color1 );
369 GXSetChanMatColor(diffID, color2 );
370 GXSetChanAmbColor(specID, color3 );
371 GXSetChanMatColor(specID, color4 );
372 }
373
374 // Initial setup for shadowing (setup texture).
bumpMapSetup(void)375 void bumpMapSetup(void)
376 {
377 // Pre-existing textures are in a tpl file.
378 TPLGetPalette(&tpl, TPL_NAME);
379
380 // Light Map Texture (generated)
381
382 // Allocate texture in main memory.
383 lightMap = MEMAllocFromAllocator(&DemoAllocator1, GXGetTexBufferSize(TW, TH, LIT_TEX_FMT, FALSE, 0));
384
385 // Create texture object.
386 GXInitTexObj(&lightMapObj, lightMap, TW, TH, LIT_TEX_FMT,
387 GX_CLAMP, GX_CLAMP, FALSE);
388
389 // Load object into hw. Lightmap will be TEXMAP1.
390 GXLoadTexObj(&lightMapObj, GX_TEXMAP1);
391
392 // Material Texture (pre-existing)
393 //
394 TPLGetGXTexObjFromPalette(tpl, &materialObj, 1);
395 GXLoadTexObj(&materialObj, GX_TEXMAP0); // Material will be TEXMAP0
396
397 // Normal Perturbation Texture (pre-existing)
398 //
399 TPLGetGXTexObjFromPalette(tpl, &nPtrbObj, 0);
400
401 // To make the texture coordinates work out as nice fractions of 2,
402 // we pretend the texture is 256x512 instead of 256x384. We are careful
403 // never to specify a T coordinate larger than 0.75.
404 {
405 void *data = GXGetTexObjData(&nPtrbObj);
406 GXInitTexObj(&nPtrbObj, data, 256, 512, GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE);
407 }
408 GXLoadTexObj(&nPtrbObj, GX_TEXMAP2); // Normal perturbation will be TEXMAP2
409
410 // Set up texgen for rendering. The matrices can be changed per-object,
411 // but the texgen needn't change.
412 GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX0);
413 GXSetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_NRM, GX_TEXMTX1);
414
415 // I will always use position matrix 0 for my geometry.
416 GXSetCurrentMtx(GX_PNMTX0);
417
418 // Diffuse is color 0, specular is alpha 0.
419 setLight(GX_LIGHT0, GX_COLOR0, GX_ALPHA0, lightMtx, cameraMtx);
420
421 // Alpha component in frame buffer will be written to.
422 GXSetAlphaUpdate(TRUE);
423
424 // Make a cube.
425 createCube();
426 }
427
bumpMapSetdown(void)428 void bumpMapSetdown(void)
429 {
430 TPLReleasePalette(&tpl);
431
432 MEMFreeToAllocator(&DemoAllocator1, lightMap);
433 }
434
435 // Per-frame setup for actual render.
renderSetup1(void)436 void renderSetup1(void)
437 {
438 Mtx44 pMtx;
439
440 // Set the rendering size.
441 setupSize(W, H);
442
443 // Perspective projection
444 // Note that in this demo, POSITIVE Y is up!
445 MTXFrustum(pMtx, 1, -1, -1, 1, 1, 15);
446 GXSetProjection(pMtx, GX_PERSPECTIVE);
447
448 // Pixel format
449 GXSetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR);
450 // We don't need to clear the display again
451
452 // Disable lights
453 GXSetChanCtrl(GX_COLOR0, FALSE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT0,
454 GX_DF_NONE, GX_AF_NONE);
455 GXSetChanCtrl(GX_ALPHA0, FALSE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT0,
456 GX_DF_NONE, GX_AF_NONE);
457 }
458
renderSetup2(void)459 void renderSetup2(void)
460 {
461 // Two tev stages, one Bump stage.
462 GXSetNumTevStages(2);
463
464 GXSetNumIndStages(1);
465
466 // Two texture coordinates, no colors.
467 GXSetNumTexGens(2);
468 GXSetNumChans(0);
469
470 // Indirect Stage 0 -- Sample normal perturbation map
471 GXSetIndTexOrder(GX_INDTEXSTAGE0, GX_TEXCOORD0, GX_TEXMAP2);
472 GXSetIndTexCoordScale(GX_INDTEXSTAGE0, GX_ITS_1, GX_ITS_1);
473
474 // Stage 0 -- Save material texture
475 //
476 // TEVPREV = TEXC/TEXA
477 //
478 GXSetTevDirect(GX_TEVSTAGE0);
479 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
480 GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0); // RGBA
481 GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE);
482
483 // Set up the indirect bump calculation for Stage 1
484 //
485 GXSetTevIndBumpXYZ(GX_TEVSTAGE1, GX_INDTEXSTAGE0, GX_ITM_0);
486
487 // Stage 1 -- Add source normal in Bump. Index lightmap with result of
488 // perturbation. Apply diffuse and specular components.
489 //
490 // TEVPREVC = PREVC * TEXC + TEXA
491 // TEVPREVA = PREVA
492 //
493 GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1, GX_TEXMAP1, GX_COLOR_NULL);
494 GXSetTevColorIn(GX_TEVSTAGE1,
495 GX_CC_ZERO, GX_CC_CPREV, GX_CC_TEXC, GX_CC_TEXA);
496 GXSetTevAlphaIn(GX_TEVSTAGE1,
497 GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV);
498 GXSetTevColorOp(GX_TEVSTAGE1,
499 GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, TRUE, GX_TEVPREV);
500 GXSetTevAlphaOp(GX_TEVSTAGE1,
501 GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, TRUE, GX_TEVPREV);
502
503
504 // Vertex packet specification -- Position, normal,
505 // and one pair of texture coordinates.
506 GXClearVtxDesc();
507 GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
508 GXSetVtxDesc(GX_VA_NRM, GX_DIRECT);
509 GXSetVtxDesc(GX_VA_TEX0, GX_INDEX16);
510 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
511 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
512 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
513
514 GXSetArray(GX_VA_TEX0, (void *) tcoords, 2*sizeof(f32));
515
516 sendNormal = TRUE;
517 sendIndex = TRUE;
518 sendCoords = FALSE;
519 }
520
521 // Per-frame setup for light map.
lightMapSetup(void)522 void lightMapSetup(void)
523 {
524 Mtx44 pMtx;
525 Mtx idMtx;
526
527 // Set the rendering size.
528 setupSize(TW, TH);
529
530 // Orthographic projection
531 MTXOrtho(pMtx, 1, -1, -1, 1, 1, 15);
532 GXSetProjection(pMtx, GX_ORTHOGRAPHIC);
533
534 // Pixel format
535 GXSetPixelFmt(GX_PF_RGBA6_Z24, GX_ZC_LINEAR);
536 // don't need to re-clear, since we will overwrite everything we use
537
538 // Enable diffuse and specular lights.
539 // COLOR0 = diffuse
540 // ALPHA0 = specular
541 GXSetChanCtrl(GX_COLOR0, TRUE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT0,
542 GX_DF_CLAMP, GX_AF_NONE);
543 GXSetChanCtrl(GX_ALPHA0, TRUE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT0,
544 GX_DF_NONE, GX_AF_SPEC);
545
546 // One tev stage.
547 GXSetNumTevStages(1);
548
549 // No textures, one color.
550 GXSetNumTexGens(0);
551 GXSetNumChans(1);
552 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
553
554 // Stage 0 -- Send out rasterized color.
555 //
556 // TEVPREV = RAS
557 //
558 GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
559
560 // Vertex packet specification -- Position and normal.
561 GXClearVtxDesc();
562 GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
563 GXSetVtxDesc(GX_VA_NRM, GX_DIRECT);
564 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
565 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
566
567 sendNormal = TRUE;
568 sendIndex = FALSE;
569 sendCoords = FALSE;
570
571 // Identity matrices for object and matrix.
572 MTXIdentity(idMtx);
573 updateMatrices(0, idMtx, idMtx);
574 }
575
576 // Prepare for donut drawing.
updateDonut(Mtx cam,f32 r1,f32 r2,f32 x,f32 y,f32 z)577 void updateDonut(Mtx cam, f32 r1, f32 r2, f32 x, f32 y, f32 z)
578 {
579 Mtx donutMtx, tempMtx;
580
581 // update object matrix for this donut.
582 MTXRotDeg(tempMtx, 'x', -r2);
583 MTXConcat(tempMtx, objectMtx, objectMtx);
584 MTXRotDeg(tempMtx, 'y', r1);
585 MTXConcat(tempMtx, objectMtx, objectMtx);
586 MTXTrans(tempMtx, x, y, z);
587 MTXConcat(tempMtx, objectMtx, donutMtx);
588
589 // Create all other matrices derived from this object matrix.
590 updateMatrices(0, donutMtx, cam);
591 }
592
593 // Draw a donut.
drawDonut()594 void drawDonut()
595 {
596 int c, f, v;
597 f32 x, y;
598
599 GXBegin(GX_QUADS, GX_VTXFMT0, (6-2)*4*8 ); // each cube is missing 2 faces; 8 cubes
600
601 for(c=0; c<9; c++) // for each cube
602 {
603 if (c==4) continue; // middle cube not drawn
604
605 x = (c % 3) - 1; // compute cube offset
606 y = 1 - (c / 3);
607
608 for(f=0; f<6; f++) // for each face
609 {
610 if (!(face[c] & ((1<<5)>>f))) continue;
611
612 for(v=0; v<4; v++) // for each vertex
613 {
614 cube[f][v].x += x; // offset vertex
615 cube[f][v].y += y;
616
617 sendVertex(&cube[f][v]); // draw it
618
619 cube[f][v].x -= x; // put it back
620 cube[f][v].y -= y;
621 }
622 }
623 }
624
625 GXEnd();
626 }
627
628 // Draw a tesselated square, with normals that make it look like a hemisphere.
drawHemisphere()629 void drawHemisphere()
630 {
631 u32 i, j;
632 coord c;
633
634 for (i=0; i<ST; i++)
635 {
636 GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT0, (u16) (TT*2 + 2));
637
638 for (j=0; j<=TT; j++)
639 {
640 c.x = ((f32) 2.0f*(i+1)/ST) - 1.0f;
641 c.y = ((f32) 2.0f*j/TT) - 1.0f;
642 c.z = -2.0f;
643 c.nx = c.x / NRM_SCALE;
644 c.ny = c.y / NRM_SCALE;
645 c.nz = c.x*c.x + c.y*c.y;
646 c.nz = c.nz < 1 ? sqrtf(1 - c.nz) : 0;
647 sendVertex(&c);
648
649 c.x = ((f32) 2.0f*(i+0)/ST) - 1.0f;
650 c.nx = c.x / NRM_SCALE;
651 c.nz = c.x*c.x + c.y*c.y;
652 c.nz = c.nz < 1 ? sqrtf(1 - c.nz) : 0;
653 sendVertex(&c);
654 }
655
656 GXEnd();
657 }
658 }
659
660 // Draw the full scene from a specific camera.
drawScene(Mtx cam,f32 rot1,f32 rot2)661 void drawScene(Mtx cam, f32 rot1, f32 rot2)
662 {
663 // Draw one donut, centered at 0,0,0, rotating at normal speed.
664 updateDonut(cam, rot1, rot2, 0.0f, 0.0f, 0.0f);
665 drawDonut();
666 }
667
668 // Show the generated light maps in the corner of the screen
showMaps()669 void showMaps()
670 {
671 Mtx idMtx;
672 coord c;
673
674 // GXSetCullMode(GX_CULL_NONE); // sanity check
675
676 // One tev stage.
677 GXSetNumTevStages(1);
678 GXSetNumIndStages(0);
679
680 // One texture, no color.
681 GXSetNumTexGens(1);
682 GXSetNumChans(0);
683 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP1, GX_COLOR_NULL);
684
685 // Stage 0 -- Send out texture color.
686 //
687 // TEVPREV = TEXC
688 //
689 GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE);
690 GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0); // RGBA
691 GXSetTevAlphaIn(GX_TEVSTAGE0,GX_CA_ZERO,GX_CA_ZERO,GX_CA_ZERO,GX_CA_ONE);
692
693 // Vertex packet specification -- Position and normal.
694 GXClearVtxDesc();
695 GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
696 GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
697 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
698 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
699
700 sendNormal = FALSE;
701 sendIndex = FALSE;
702 sendCoords = TRUE;
703
704 // Identity matrices for object and matrix.
705 MTXIdentity(idMtx);
706 GXLoadPosMtxImm(idMtx, GX_PNMTX0);
707 GXLoadTexMtxImm(idMtx, GX_TEXMTX0, GX_MTX2x4);
708
709 GXBegin(GX_QUADS, GX_VTXFMT0, 4);
710 c.x = -1.0f;
711 c.y = 1.0f;
712 c.z = -1.0f;
713 c.s = 0.0f;
714 c.t = 0.0f;
715 sendVertex(&c);
716 c.x += (f32) TW/W*2;
717 c.s = 1.0f;
718 sendVertex(&c);
719 c.y -= (f32) TH/H*2;
720 c.t = 1.0f;
721 sendVertex(&c);
722 c.x -= (f32) TW/W*2;
723 c.s = 0.0f;
724 sendVertex(&c);
725 GXEnd();
726
727 // Now show alpha (specular) map
728 GXSetTevColorIn(GX_TEVSTAGE0,GX_CC_ZERO,GX_CC_ZERO,GX_CC_ZERO,GX_CC_TEXA);
729
730 GXBegin(GX_QUADS, GX_VTXFMT0, 4);
731 c.x = -1.0f;
732 c.y = -1.0f;
733 c.z = -1.0f;
734 c.s = 0.0f;
735 c.t = 1.0f;
736 sendVertex(&c);
737 c.y += (f32) TH/H*2;
738 c.t = 0.0f;
739 sendVertex(&c);
740 c.x += (f32) TW/W*2;
741 c.s = 1.0f;
742 sendVertex(&c);
743 c.y -= (f32) TH/H*2;
744 c.t = 1.0f;
745 sendVertex(&c);
746 GXEnd();
747
748 // Now show the X component of the bump map
749 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP2, GX_COLOR_NULL);
750 GXSetTevColorIn(GX_TEVSTAGE0,GX_CC_ZERO,GX_CC_ZERO,GX_CC_ZERO,GX_CC_TEXA);
751
752 GXBegin(GX_QUADS, GX_VTXFMT0, 4);
753 c.x = 1.0f;
754 c.y = 1.0f;
755 c.z = -1.0f;
756 c.s = 1.0f;
757 c.t = 0.0f;
758 sendVertex(&c);
759 c.y -= (f32) IH/H*IS;
760 c.t = 0.75f;
761 sendVertex(&c);
762 c.x -= (f32) IW/W*IS;
763 c.s = 0.0f;
764 sendVertex(&c);
765 c.y += (f32) IH/H*IS;
766 c.t = 0.0f;
767 sendVertex(&c);
768 GXEnd();
769
770 // Now show the Y component of the bump map
771 GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP3); // BBB
772 GXSetTevColorIn(GX_TEVSTAGE0,GX_CC_ZERO,GX_CC_ZERO,GX_CC_ZERO,GX_CC_TEXC);
773
774 GXBegin(GX_QUADS, GX_VTXFMT0, 4);
775 c.y -= (f32) IH/H*IS + (64.0f/H);
776 sendVertex(&c);
777 c.x += (f32) IW/W*IS;
778 c.s = 1.0f;
779 sendVertex(&c);
780 c.y -= (f32) IH/H*IS;
781 c.t = 0.75f;
782 sendVertex(&c);
783 c.x -= (f32) IW/W*IS;
784 c.s = 0.0f;
785 sendVertex(&c);
786 GXEnd();
787
788 // Now show the Z component of the bump map
789 GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP2); // GGG
790 GXSetTevColorIn(GX_TEVSTAGE0,GX_CC_ZERO,GX_CC_ZERO,GX_CC_ZERO,GX_CC_TEXC);
791
792 GXBegin(GX_QUADS, GX_VTXFMT0, 4);
793 c.y -= (f32) 64.0f/H;
794 c.t = 0.0f;
795 sendVertex(&c);
796 c.x += (f32) IW/W*IS;
797 c.s = 1.0f;
798 sendVertex(&c);
799 c.y -= (f32) IH/H*IS;
800 c.t = 0.75f;
801 sendVertex(&c);
802 c.x -= (f32) IW/W*IS;
803 c.s = 0.0f;
804 sendVertex(&c);
805 GXEnd();
806 }
807
808 /*---------------------------------------------------------------------------*
809 Application main loop
810 *---------------------------------------------------------------------------*/
811
main(void)812 void main(void)
813 {
814 f32 rot1=0.0f;
815 f32 rot2=0.0f;
816
817 commonInit(); // Same init for all tests.
818
819 bumpMapSetup(); // Setup texture objects and all other static things.
820
821 // This is only done once in this test since the camera and light never
822 // change direction with respect to one another. If they ever do, the
823 // lightmap must be regenerated.
824 lightMapSetup(); // Setup for lightmap render.
825 drawHemisphere(); // Render hemisphere lightmap
826
827 GXCopyTex(lightMap, FALSE); // Copy to texture.
828 GXPixModeSync();
829
830 PrintIntro();
831
832 while(!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
833 {
834 DEMOPadRead();
835
836 rot1 = DEMOPadGetStickX(0)/10;
837 rot2 = DEMOPadGetStickY(0)/10;
838 DEMOBeforeRender();
839
840 renderSetup1(); // Setup for actual render, part 1.
841
842 showMaps(); // Show the lightmaps used
843
844 renderSetup2(); // Setup for actual render, part 2.
845
846 drawScene(cameraMtx, rot1, rot2);
847
848 DEMODoneRender();
849 }
850
851 bumpMapSetdown(); // Free memory and such.
852
853 OSHalt("End of demo");
854 }
855
856 /*---------------------------------------------------------------------------*
857 Name: PrintIntro
858
859 Description: Prints the directions on how to use this demo.
860
861 Arguments: none
862
863 Returns: none
864 *---------------------------------------------------------------------------*/
PrintIntro(void)865 static void PrintIntro( void )
866 {
867 OSReport("\n\n");
868 OSReport("************************************************\n");
869 OSReport("ind-bump-xyz: demonstrate bumpXYZ method\n");
870 OSReport("************************************************\n");
871 OSReport("to quit hit the start button\n");
872 OSReport("\n");
873 OSReport(" Stick X/Y : rotate model\n");
874 OSReport("************************************************\n\n");
875 }
876
877