1 /*---------------------------------------------------------------------------*
2 Project: Dolphin/Revolution gx demo
3 File: ind-warp.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 #define PI 3.1415926535f
17
18 /*---------------------------------------------------------------------------*
19 Defines
20 *---------------------------------------------------------------------------*/
21
22 #define WIDTH_LYR1 64
23 #define HSHIFT_LYR1 6
24 #define HEIGHT_LYR1 64
25
26 #define ASPECT (10.0f/7.0f)
27
28 typedef struct
29 {
30 f32 val, min, max, step;
31 char *name;
32 } Param;
33
34 /*---------------------------------------------------------------------------*
35 Forward references
36 *---------------------------------------------------------------------------*/
37
38 void main ( void );
39 static void ParameterInit ( void );
40 static void TexInit ( void );
41 static void TexUpdate ( f32 phase, f32 freq, f32 amp, f32 ang, u8 func );
42 static void DrawInit ( void );
43 static void DrawTick ( u8 model );
44 static void AnimTick ( void );
45 static void PrintIntro ( void );
46
47 /*---------------------------------------------------------------------------*
48 Global variables
49 *---------------------------------------------------------------------------*/
50
51 // Modeling parameters for the object that is drawn
52
53 Mtx objMtx;
54 f32 scale = 1.5f;
55 f32 xp = 0.0f;
56 f32 yp = 0.0f;
57 f32 zp = -5.0f;
58
59 // Parameters for the indirect texture creation function
60
61 f32 phase = 0.0f;
62
63 #define P_FUNC 0
64 #define P_MODEL 1
65 #define P_FREQ 2
66 #define P_AMPL 3
67 #define P_VANG 4
68 #define P_ROTA 5
69 #define P_LAST 5
70
71 Param parm[P_LAST+1] = {
72 { 1.0f, 1.0f, 3.0f, 1.0f, "Function" },
73 { 1.0f, 1.0f, 4.0f, 1.0f, "Model" },
74 { 5.0f, 0.1f, 30.0f, 0.05f, "Frequency" },
75 { 0.5f, 0.01f, 1.0f, 0.01f, "Amplitude" },
76 { 0.0f, 0.0f, 0.0f, 2.0f, "Vector Angle" },
77 { 0.0f, 0.0f, 0.0f, 0.02f, "Rotation (F3)" }, // for function 3 only
78 };
79
80 u8 select = 0;
81
82 // Texture data
83
84 static TPLPalettePtr tpl = NULL;
85
86 static GXTexObj imageTexObj;
87 static GXTexObj indTexObj;
88
89 static u8 tmap1[WIDTH_LYR1 * HEIGHT_LYR1 * 2] ATTRIBUTE_ALIGN(32);
90
91 /*---------------------------------------------------------------------------*
92 Application main loop
93 *---------------------------------------------------------------------------*/
main(void)94 void main ( void )
95 {
96 DEMOInit(NULL);
97
98 PrintIntro(); // Print demo directions
99
100 TexInit(); // Set up textures
101
102 ParameterInit(); // Set up misc. parameters
103
104 DEMOPadRead(); // Read the joystick for this frame
105
106 DrawInit(); // Set up drawing state
107
108 while(1)
109 {
110 DEMOPadRead(); // Read the joystick for this frame
111
112 AnimTick(); // Do animation based on input
113
114 // Update the indirect texture
115 TexUpdate(phase,
116 parm[P_FREQ].val,
117 parm[P_AMPL].val,
118 parm[P_ROTA].val,
119 (u8) parm[P_FUNC].val);
120
121 DEMOBeforeRender();
122
123 DrawTick((u8) parm[P_MODEL].val); // Draw the model.
124
125 DEMODoneRender();
126 }
127
128 OSHalt("End of demo");
129 }
130
131 /*---------------------------------------------------------------------------*
132 Functions
133 *---------------------------------------------------------------------------*/
134
135 /*---------------------------------------------------------------------------*
136 Name: ParameterInit
137
138 Description: Initialize parameters for single frame display
139
140 Arguments: none
141
142 Returns: none
143 *---------------------------------------------------------------------------*/
ParameterInit(void)144 static void ParameterInit( void )
145 {
146 MTXIdentity(objMtx);
147 }
148
149 /*---------------------------------------------------------------------------*
150 Name: TexInit
151
152 Description: Sets up the texture state.
153
154 Arguments: none
155
156 Returns: none
157 *---------------------------------------------------------------------------*/
TexInit(void)158 static void TexInit( void )
159 {
160 // Get image texture from tpl
161
162 TPLGetPalette(&tpl, "gxTests/tex-01.tpl");
163
164 TPLGetGXTexObjFromPalette(tpl, &imageTexObj, 3);
165 // Override LOD information
166 GXInitTexObjLOD( &imageTexObj, // texture object
167 GX_LINEAR, GX_LINEAR, // min/mag filter
168 0.0F, 0.0F, // min/max LOD
169 0.0F, // LOD bias
170 GX_FALSE, // bias clamp
171 GX_FALSE, // do edge LOD
172 GX_ANISO_1 ); // max anisotropy
173
174
175 // Set up indirect texture for bilinear interpolation
176
177 // Indirect texture data will be created later.
178 // Right now, we only need the pointer to where it will be.
179
180 GXInitTexObj(&indTexObj, // texture object
181 (void*) &tmap1, // data
182 WIDTH_LYR1, // width
183 HEIGHT_LYR1, // height
184 GX_TF_IA8, // format
185 GX_REPEAT, // wrap s
186 GX_REPEAT, // wrap t
187 GX_FALSE); // mipmap
188
189 GXInitTexObjLOD( &indTexObj, // texture object
190 GX_LINEAR, GX_LINEAR, // min/mag filter
191 0.0F, 0.0F, // min/max LOD
192 0.0F, // LOD bias
193 GX_FALSE, // bias clamp
194 GX_FALSE, // do edge LOD
195 GX_ANISO_1 ); // max anisotropy
196 }
197
198 /*---------------------------------------------------------------------------*
199 Name: TexUpdate
200
201 Description: Updates the indirect texture map.
202
203 Arguments: phase, frequency, amplitude, rotation, function select
204
205 Returns: none
206 *---------------------------------------------------------------------------*/
TexUpdate(f32 phase,f32 freq,f32 amp,f32 rot,u8 func)207 static void TexUpdate( f32 phase, f32 freq, f32 amp, f32 rot, u8 func )
208 {
209 s32 nJ, nI, off;
210 u8 nS, nT;
211 f32 dx, dy, di, id;
212
213 // Create indirect texture
214
215 for (nJ=0; nJ<HEIGHT_LYR1; nJ++)
216 {
217 for (nI=0; nI<WIDTH_LYR1; nI++)
218 {
219 // compute the direction vector
220 if (func <= 2)
221 {
222 dx = ((f32) nI / WIDTH_LYR1) - 0.5f;
223 dy = ((f32) nJ / HEIGHT_LYR1) - 0.5f;
224 } else {
225 dx = (f32) nI / WIDTH_LYR1 * cosf(rot);
226 dy = (f32) nJ / HEIGHT_LYR1 * sinf(rot);
227 }
228
229 // normalize the vector
230 if (dx != 0.0f || dy != 0.0f)
231 {
232 di = sqrtf(dx*dx+dy*dy);
233 id = 1.0f/di;
234 dx *= id;
235 dy *= id;
236 } else {
237 di = id = 0.0f;
238 }
239
240 // use inverse distance for function 2
241 if (func == 2)
242 {
243 di = id * 0.1f;
244 }
245
246 // compute magnitude based upon sin function of distance, phase
247 di = sinf(di * freq + phase);
248
249 // compute the actual indirect offsets
250 nS = (u8) ((dx * di) * amp * 127.0f + 128.0f);
251 nT = (u8) ((dy * di) * amp * 127.0f + 128.0f);
252
253 // This offset calculation works for map widths that are
254 // powers of 2
255 off = ((nI & 3) | ((nI >> 2) << 4) | ((nJ & 3) << 2) |
256 ((nJ >> 2) << (4+(HSHIFT_LYR1-2)))) * 2;
257
258 tmap1[off+0] = nS;
259 tmap1[off+1] = nT;
260 }
261 }
262
263 // Important! We must flush the texture data from the CPU cache
264 DCFlushRange((void *) tmap1, WIDTH_LYR1 * HEIGHT_LYR1 * 2);
265 }
266
267 /*---------------------------------------------------------------------------*
268 Name: DrawInit
269
270 Description: Sets up the graphics state.
271
272 Arguments: none
273
274 Returns: none
275 *---------------------------------------------------------------------------*/
DrawInit(void)276 static void DrawInit( void )
277 {
278 Mtx idtMtx;
279 Mtx44 prjMtx;
280
281 // Misc setup
282 GXSetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
283 GXSetCullMode(GX_CULL_BACK);
284
285 // Set up textures
286 GXLoadTexObj(&imageTexObj, GX_TEXMAP0);
287 GXLoadTexObj(&indTexObj, GX_TEXMAP1);
288
289 // Set up texgen
290 GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX0);
291
292 // Set up TEV and such...
293 GXSetNumTevStages(1);
294 GXSetNumIndStages(1);
295
296 // One texture coordinate, no colors.
297 GXSetNumTexGens(1);
298 GXSetNumChans(0);
299
300 // Indirect Stage 0 -- Lookup indirect map
301 GXSetIndTexOrder(GX_INDTEXSTAGE0, GX_TEXCOORD0, GX_TEXMAP1);
302
303 // The image map is four times bigger than the indirect map
304 GXSetIndTexCoordScale(GX_INDTEXSTAGE0, GX_ITS_4, GX_ITS_4);
305
306 // Stage 0 -- Output texture color
307 //
308 // TEVPREV = TEXC/TEXA
309
310 GXSetTevIndWarp(GX_TEVSTAGE0, // tev stage
311 GX_INDTEXSTAGE0, // indirect stage
312 GX_TRUE, // signed offsets?
313 GX_FALSE, // replace mode?
314 GX_ITM_0); // ind matrix select
315
316 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
317 GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE);
318
319 GXClearVtxDesc();
320 GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
321 GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
322 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
323 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
324
325 MTXIdentity(idtMtx);
326 GXLoadPosMtxImm(idtMtx, GX_PNMTX0);
327 GXLoadTexMtxImm(idtMtx, GX_TEXMTX0, GX_MTX2x4);
328
329 MTXFrustum(prjMtx, 0.25f, -0.25f, -0.25f*ASPECT, 0.25f*ASPECT, 1.0f, 15.0f);
330 GXSetProjection(prjMtx, GX_PERSPECTIVE);
331 }
332
333 /*---------------------------------------------------------------------------*
334 Name: DrawTick
335
336 Description: Draw the current model once.
337
338 Arguments: which model
339
340 Returns: none
341 *---------------------------------------------------------------------------*/
DrawTick(u8 model)342 static void DrawTick( u8 model )
343 {
344 Mtx txMtx;
345
346 MTXIdentity(txMtx);
347
348 switch(model)
349 {
350 case 1:
351 // Draw one copy of the texture per cube side
352 GXLoadTexMtxImm(txMtx, GX_TEXMTX0, GX_MTX2x4);
353 GXDrawCube();
354 break;
355 case 2:
356 // Draw nine copies of the texture per cube side
357 txMtx[0][0] = 3.0f;
358 txMtx[1][1] = 3.0f;
359 GXLoadTexMtxImm(txMtx, GX_TEXMTX0, GX_MTX2x4);
360 GXDrawCube();
361 break;
362 case 3:
363 // Draw two copies of the texture on a sphere
364 txMtx[0][0] = 2.0f;
365 GXLoadTexMtxImm(txMtx, GX_TEXMTX0, GX_MTX2x4);
366 GXDrawSphere(12, 20);
367 break;
368 case 4:
369 // Draw two copies of the texture on a torus
370 txMtx[1][1] = 2.0f;
371 GXLoadTexMtxImm(txMtx, GX_TEXMTX0, GX_MTX2x4);
372 GXDrawTorus(0.3f, 12, 20);
373 break;
374 }
375 }
376
377 /*---------------------------------------------------------------------------*
378 Name: AnimTick
379
380 Description: Animate the scene.
381
382 Arguments: none
383
384 Returns: none
385 *---------------------------------------------------------------------------*/
AnimTick(void)386 static void AnimTick( void )
387 {
388 Mtx tmpMtx;
389 Mtx posMtx;
390 f32 indMtx[2][3];
391 f32 rAng1, rAng2, rAng3;
392 u8 act = 0;
393 u8 show = 0;
394 static u8 first = 1;
395 u16 press = DEMOPadGetButton(0);
396 u16 down = DEMOPadGetButtonDown(0);
397
398 if (first == 1)
399 {
400 first = 0;
401 show = 1;
402 }
403
404 if (down & PAD_BUTTON_X)
405 {
406 select = (u8) ((select == P_LAST) ? 0 : select + 1);
407 show = 1;
408 }
409 else if (down & PAD_BUTTON_Y)
410 {
411 select = (u8) ((select == 0) ? P_LAST : select - 1);
412 show = 1;
413 }
414
415 if (show)
416 {
417 OSReport("%s select\n", parm[select].name);
418 }
419
420 if (select == P_FUNC || select == P_MODEL)
421 {
422 if (down & PAD_BUTTON_A)
423 act = 1;
424 else if (down & PAD_BUTTON_B)
425 act = 2;
426 } else {
427 if (press & PAD_BUTTON_A)
428 act = 1;
429 else if (press & PAD_BUTTON_B)
430 act = 2;
431 }
432
433 if (act == 1)
434 {
435 parm[select].val += parm[select].step;
436 if (parm[select].max != 0.0f && parm[select].val > parm[select].max)
437 parm[select].val = parm[select].max;
438 }
439 else if (act == 2)
440 {
441 parm[select].val -= parm[select].step;
442 if (parm[select].min != 0.0f && parm[select].val < parm[select].min)
443 parm[select].val = parm[select].min;
444 }
445
446 if (act)
447 {
448 OSReport("%s = %f\n", parm[select].name, parm[select].val);
449 }
450
451 rAng1 = - DEMOPadGetTriggerR(0) / 100.0f
452 + DEMOPadGetTriggerL(0) / 100.0f;
453 rAng2 = DEMOPadGetStickX(0) / 10.0f;
454 rAng3 = -DEMOPadGetStickY(0) / 10.0f;
455
456 scale += DEMOPadGetSubStickY(0)/1000.0f;
457 if (scale < 0.01f)
458 scale = 0.01f;
459 else if (scale > 100.0f)
460 scale = 100.0f;
461
462 // Compute rotations...
463 MTXRotDeg(tmpMtx, 'x', rAng3);
464 MTXConcat(tmpMtx, objMtx, objMtx);
465 MTXRotDeg(tmpMtx, 'y', rAng2);
466 MTXConcat(tmpMtx, objMtx, objMtx);
467 MTXRotDeg(tmpMtx, 'z', rAng1);
468 MTXConcat(tmpMtx, objMtx, objMtx);
469
470 // Compute the rest...
471 MTXTrans(tmpMtx, xp, yp, zp);
472 MTXConcat(tmpMtx, objMtx, posMtx);
473 MTXScale(tmpMtx, scale, scale, scale);
474 MTXConcat(posMtx, tmpMtx, posMtx);
475
476 GXLoadPosMtxImm(posMtx, GX_PNMTX0);
477
478 // Set indirect matrix (vector angle)
479
480 MTXRotDeg(tmpMtx, 'z', parm[P_VANG].val);
481
482 indMtx[0][0] = tmpMtx[0][0]*0.5f;
483 indMtx[0][1] = tmpMtx[0][1]*0.5f;
484 indMtx[0][2] = 0.0f;
485 indMtx[1][0] = tmpMtx[1][0]*0.5f;
486 indMtx[1][1] = tmpMtx[1][1]*0.5f;
487 indMtx[1][2] = 0.0f;
488
489 GXSetIndTexMtx(GX_ITM_0, indMtx, 1);
490
491 // Phase
492
493 if (!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
494 {
495 phase += 0.02f;
496 }
497 }
498
499 /*---------------------------------------------------------------------------*
500 Name: PrintIntro
501
502 Description: Prints the directions on how to use this demo.
503
504 Arguments: none
505
506 Returns: none
507 *---------------------------------------------------------------------------*/
PrintIntro(void)508 static void PrintIntro( void )
509 {
510 OSReport("\n\n");
511 OSReport("************************************************\n");
512 OSReport("ind-tile-test: tiled texture map using indirect textures\n");
513 OSReport("************************************************\n");
514 OSReport("to quit hit the start button\n");
515 OSReport("main stick : rotates object X/Y\n");
516 OSReport("sub stick : scales object\n");
517 OSReport("l/r triggers : rotates object Z\n");
518 OSReport("A/B buttons : changes paramter value\n");
519 OSReport("X/Y buttons : selects parameter\n");
520 OSReport("\n");
521 OSReport("************************************************\n\n");
522 }
523