1 /*---------------------------------------------------------------------------*
2 Project: Dolphin/Revolution gx demo
3 File: tf-stitch.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 PI 3.14159265358979323846F
18
19 /*---------------------------------------------------------------------------*
20 Forward references
21 *---------------------------------------------------------------------------*/
22
23 void main ( void );
24 static void CameraInit ( Mtx v );
25 static void DrawInit ( void );
26 static void DrawTick ( Mtx v );
27 static void AnimTick ( void );
28
29 static float ComputeScale ( float position );
30
31 /*---------------------------------------------------------------------------*
32 Model Data
33 *---------------------------------------------------------------------------*/
34 #define Black MyColors[0]
35 #define White MyColors[5]
36 #define Red MyColors[1]
37 #define Green MyColors[2]
38 #define Blue MyColors[3]
39 #define Gray MyColors[4]
40
41
42 u32 MyColors[] ATTRIBUTE_ALIGN(32) = {
43 0x00ffffff,
44 0xff0000ff,
45 0xffff00ff,
46 0x0000ffff,
47 0x08ff08ff,
48 0xff00ffff,
49
50 0x808080ff,
51 0xffffffff,
52 0xffff00ff,
53 0x00ff00ff};
54
55 GXLightObj MyLight;
56
57 typedef struct {
58 GXPosNrmMtx mtx;
59 f32 xlate;
60 f32 recomputeNormalMtx;
61 } Segment;
62
63 Segment segs[] ATTRIBUTE_ALIGN(32) = {
64 {GX_PNMTX0, -540.0F, 0},
65 {GX_PNMTX1, -520.0F, 0},
66 {GX_PNMTX2, -500.0F, 0},
67 {GX_PNMTX3, -480.0F, 0},
68 {GX_PNMTX4, -460.0F, 0},
69 {GX_PNMTX5, -440.0F, 0},
70 {GX_PNMTX6, -420.0F, 0},
71 {GX_PNMTX7, -400.0F, 0},
72 {GX_PNMTX8, -380.0F, 0},
73
74 {GX_PNMTX9, -360.0F, 0},
75
76 {GX_PNMTX0, -340.0F, 0},
77 {GX_PNMTX1, -320.0F, 0},
78 {GX_PNMTX2, -300.0F, 0},
79 {GX_PNMTX3, -280.0F, 0},
80 {GX_PNMTX4, -260.0F, 0},
81 {GX_PNMTX5, -240.0F, 0},
82 {GX_PNMTX6, -220.0F, 0},
83 {GX_PNMTX7, -200.0F, 0},
84
85 {GX_PNMTX8, -180.0F, 0},
86
87 {GX_PNMTX9, -160.0F, 0},
88 {GX_PNMTX0, -140.0F, 0},
89 {GX_PNMTX1, -120.0F, 0},
90 {GX_PNMTX2, -100.0F, 0},
91 {GX_PNMTX3, -80.0F, 0},
92 {GX_PNMTX4, -60.0F, 0},
93 {GX_PNMTX5, -40.0F, 0},
94 {GX_PNMTX6, -20.0F, 0},
95
96 {GX_PNMTX7, 0.0F, 0},
97
98 {GX_PNMTX8, 20.0F, 0},
99 {GX_PNMTX9, 40.0F, 0},
100 {GX_PNMTX0, 60.0F, 0},
101 {GX_PNMTX1, 80.0F, 0},
102 {GX_PNMTX2, 100.0F, 0},
103 {GX_PNMTX3, 120.0F, 0},
104 {GX_PNMTX4, 140.0F, 0},
105 {GX_PNMTX5, 160.0F, 0},
106
107 {GX_PNMTX6, 180.0F, 0},
108
109 {GX_PNMTX7, 200.0F, 0},
110 {GX_PNMTX8, 220.0F, 0},
111 {GX_PNMTX9, 240.0F, 0},
112 {GX_PNMTX0, 260.0F, 0},
113 {GX_PNMTX1, 280.0F, 0},
114 {GX_PNMTX2, 300.0F, 0},
115 {GX_PNMTX3, 320.0F, 0},
116 {GX_PNMTX4, 340.0F, 0},
117
118 {GX_PNMTX5, 360.0F, 0},
119
120 {GX_PNMTX6, 380.0F, 0},
121 {GX_PNMTX7, 400.0F, 0},
122 {GX_PNMTX8, 420.0F, 0},
123 {GX_PNMTX9, 440.0F, 0},
124 {GX_PNMTX0, 460.0F, 0},
125 {GX_PNMTX1, 480.0F, 0},
126 {GX_PNMTX2, 500.0F, 0},
127 {GX_PNMTX3, 520.0F, 0},
128
129 {GX_PNMTX4, 540.0F, 0}};
130
131 f32 MyVert[200] ATTRIBUTE_ALIGN(32);
132
133 float rot = 0;
134 float rot2;
135 u8 direction = 0;
136
137 float BallPosition = 800;
138 float BallStep = -10;
139
140 Mtx v; // view matrix
141
142 /*---------------------------------------------------------------------------*/
143 static void ComputeNormalRotMtx ( Segment *seg, u32 idx );
144
145 /*---------------------------------------------------------------------------*
146 Application main loop
147 *---------------------------------------------------------------------------*/
148
main(void)149 void main ( void )
150 {
151 DEMOInit(NULL);
152
153 OSReport("\n\n");
154 OSReport("**********************************************\n");
155 OSReport("tf-stitch: Stitched Object demo\n");
156 OSReport("**********************************************\n");
157 OSReport("To quit hit the start button.\n");
158 OSReport("\n");
159 OSReport("Main stick L/R rotates model.\n");
160 OSReport("**********************************************\n");
161 OSReport("\n\n");
162
163 CameraInit(v); // Initialize the camera.
164 DrawInit(); // Define my vertex formats and set array pointers.
165
166 while(!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
167 {
168 DEMOBeforeRender();
169
170 DrawTick(v); // Draw the model.
171
172 DEMODoneRender();
173
174 DEMOPadRead(); // Update pad status.
175 AnimTick(); // Update animation.
176 }
177
178 OSHalt("End of test");
179 }
180
181
182 /*---------------------------------------------------------------------------*
183 Functions
184 *---------------------------------------------------------------------------*/
185 /*---------------------------------------------------------------------------*
186 Name: CameraInit
187
188 Description: Initialize the projection matrix and load into hardware.
189 Initialize the view matrix.
190
191 Arguments: v view matrix
192
193 Returns: none
194 *---------------------------------------------------------------------------*/
CameraInit(Mtx v)195 static void CameraInit ( Mtx v )
196 {
197 Mtx44 p; // projection matrix
198 Vec up = {0.0F, 1.0F, 0.0F};
199 Vec camLoc = {0.0F, 0.0F, 1200.0F};
200 Vec objPt = {0.0F, 0.0F, 0.0F};
201 f32 left = 240.0F;
202 f32 top = 320.0F;
203 f32 znear = 500.0F;
204 f32 zfar = 2000.0F;
205
206 MTXFrustum(p, left, -left, -top, top, znear, zfar);
207 GXSetProjection(p, GX_PERSPECTIVE);
208
209 MTXLookAt(v, &camLoc, &up, &objPt);
210 }
211
212 /*---------------------------------------------------------------------------*
213 Name: DrawInit
214
215 Description: Initializes the vertex attribute format 0, and sets
216 the array pointers and strides for the indexed data.
217
218 Arguments: none
219
220 Returns: none
221 *---------------------------------------------------------------------------*/
DrawInit(void)222 static void DrawInit( void )
223 {
224 u32 i;
225 f32 a;
226 GXColor c = {255, 255, 255, 255};
227
228 GXSetCullMode(GX_CULL_NONE);
229
230 // for generated models
231 GXSetVtxAttrFmt(GX_VTXFMT3, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
232 GXSetVtxAttrFmt(GX_VTXFMT3, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
233 GXSetVtxAttrFmt(GX_VTXFMT3, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
234
235 GXClearVtxDesc();
236 GXSetVtxDesc(GX_VA_PNMTXIDX, GX_DIRECT);
237 GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
238 GXSetVtxDesc(GX_VA_NRM, GX_INDEX8);
239 GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
240
241 GXSetArray(GX_VA_POS, MyVert, 3*sizeof(f32));
242 GXSetArray(GX_VA_NRM, MyVert, 3*sizeof(f32));
243
244 //
245 // set up light parameters
246 //
247
248 GXInitLightPos(&MyLight, 0.0F, 0.0F, 0.0F);
249 GXInitLightColor(&MyLight, c);
250 GXLoadLightObjImm(&MyLight, GX_LIGHT0);
251
252 c.g = c.b = 0;
253 GXSetChanMatColor(GX_COLOR0, c);
254
255 GXSetNumChans( 1 );
256 GXSetNumTexGens( 0 );
257 GXSetTevOp( GX_TEVSTAGE0, GX_PASSCLR );
258 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
259
260 a = 0.0F;
261 for (i = 0; i < 16; i++)
262 {
263 a = i * 2.0F * PI / 16.0F;
264 MyVert[3*i] = sinf(a); // x
265 MyVert[3*i+1] = cosf(a); // y
266 MyVert[3*i+2] = 0.0F; // z
267 }
268
269 MyVert[3*16] = 0; // x
270 MyVert[3*16+1] = 0; // y
271 MyVert[3*16+2] = 1; // z
272
273 MyVert[3*17] = 0; // x
274 MyVert[3*17+1] = 0; // y
275 MyVert[3*17+2] = -1;// z
276
277 // flush array from CPU $
278 DCFlushRange(MyVert, 54 * sizeof(f32));
279 }
280
281
282 /*---------------------------------------------------------------------------*
283 Name: DrawTick
284
285 Description: Draw the model once.
286 GXInit makes GX_PNMTX0 the default matrix.
287
288 Arguments: v view matrix
289
290 Returns: none
291 *---------------------------------------------------------------------------*/
DrawTick(Mtx v)292 static void DrawTick( Mtx v )
293 {
294 u8 i, j, k;
295 Mtx ms; // Model matrix. scale
296 Mtx mry, mrx; // Model matrix. rotate
297 Mtx mt; // Model matrix. translate
298 Mtx mv; // Modelview matrix.
299 float scale;
300
301
302 GXSetChanCtrl(
303 GX_COLOR0,
304 GX_ENABLE, // enable channel
305 GX_SRC_REG, // amb source
306 GX_SRC_VTX, // mat source
307 GX_LIGHT0, // light mask
308 GX_DF_CLAMP, // diffuse function
309 GX_AF_NONE);
310
311 // build each segment matrix
312 // assumes less than 10 segs for now...
313 for (k = 0; k < 6; k++)
314 {
315 for (i = 0; i < 10; i++)
316 {
317 scale = ComputeScale(segs[(i + (10 * k)) - k].xlate);
318 MTXScale(ms, scale, scale, 100.0F);
319 MTXTrans(mt, 0.0F, 0.0F, segs[(i + (10 * k)) - k].xlate);
320 MTXRotDeg(mry, 'Y', rot);
321 MTXRotDeg(mrx, 'X', rot2 * (segs[(i + (10 * k)) - k].xlate/800.0F));
322
323 MTXConcat(mt, ms, mv);
324 MTXConcat(mrx, mv, mv);
325 MTXConcat(mry, mv, mv);
326 MTXConcat(v, mv, mv);
327 GXLoadPosMtxImm(mv, segs[(i + (10 * k)) - k].mtx);
328
329 if(scale == 100.00F) // segment is not in the bulge, do not adjust normals
330 {
331 MTXInverse(mv, mv);
332 MTXTranspose(mv, mv);
333 segs[(i + (10 * k)) - k].recomputeNormalMtx = 0;
334 GXLoadNrmMtxImm(mv, segs[(i + (10 * k)) - k].mtx);
335 }
336 else
337 segs[(i + (10 * k)) - k].recomputeNormalMtx = scale;
338 }
339
340 // draw each segment
341 // assume number of segs less than matrix memory size for now
342 for (j = 0; j < 9; j++)
343 {
344
345 for (i = 0; i < 16; i++)
346 {
347 if(segs[((j + (10 * k)) - k) + 1].recomputeNormalMtx)
348 ComputeNormalRotMtx(&(segs[((j + (10 * k)) - k) + 1]), i);
349 if(segs[((j + (10 * k)) - k)].recomputeNormalMtx)
350 ComputeNormalRotMtx(&(segs[((j + (10 * k)) - k)]), i);
351 }
352 // finish cylinder
353 if(segs[((j + (10 * k)) - k) + 1].recomputeNormalMtx)
354 ComputeNormalRotMtx(&(segs[((j + (10 * k)) - k) + 1]), 0);
355 if(segs[((j + (10 * k)) - k)].recomputeNormalMtx)
356 ComputeNormalRotMtx(&(segs[((j + (10 * k)) - k)]), 0);
357
358 // make this a function of circle divisions
359 GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT3, 17*2);
360 for (i = 0; i < 16; i++)
361 {
362 GXMatrixIndex1u8(segs[((j + (10 * k)) - k) + 1].mtx);
363 GXPosition1x8(i);
364 GXNormal1x8(i);
365 GXColor1u32(MyColors[k]);
366
367 GXMatrixIndex1u8(segs[((j + (10 * k)) - k)].mtx);
368 GXPosition1x8(i);
369 GXNormal1x8(i);
370 GXColor1u32(MyColors[k]);
371 }
372 // finish cylinder
373 GXMatrixIndex1u8(segs[((j + (10 * k)) - k) + 1].mtx);
374 GXPosition1x8(0);
375 GXNormal1x8(0);
376 GXColor1u32(MyColors[k]);
377
378 GXMatrixIndex1u8(segs[((j + (10 * k)) - k)].mtx);
379 GXPosition1x8(0);
380 GXNormal1x8(0);
381 GXColor1u32(MyColors[k]);
382 GXEnd();
383 }
384 }
385
386 GXSetChanCtrl(
387 GX_COLOR0,
388 GX_ENABLE, // enable channel
389 GX_SRC_REG, // amb source
390 GX_SRC_REG, // mat source
391 GX_LIGHT0, // light mask
392 GX_DF_CLAMP, // diffuse function
393 GX_AF_NONE);
394
395 MTXTrans(mt, 0.0F, 0.0F, BallPosition);
396 MTXRotDeg(mry, 'Y', rot);
397 MTXScale(ms, 125.0F, 125.0F, 125.0F);
398 MTXRotDeg(mrx, 'X', rot2 * (BallPosition/800.0F));
399
400 MTXConcat(mt, ms, mv);
401 MTXConcat(mrx, mv, mv);
402 MTXConcat(mry, mv, mv);
403 MTXConcat(v, mv, mv);
404 GXLoadPosMtxImm(mv, GX_PNMTX0);
405 MTXInverse(mv, mv);
406 MTXTranspose(mv, mv);
407 GXLoadNrmMtxImm(mv, GX_PNMTX0);
408
409 GXSetCurrentMtx(GX_PNMTX0);
410
411 GXDrawSphere1(2);
412 }
413
414 /*---------------------------------------------------------------------------*
415 Name: AnimTick
416
417 Description: Changes scene parameters.
418
419 Arguments: none
420
421 Returns: none
422 *---------------------------------------------------------------------------*/
AnimTick(void)423 static void AnimTick( void )
424 {
425 if (DEMOPadGetStickX(0) > 0)
426 rot += 2;
427 else if (DEMOPadGetStickX(0) < 0)
428 rot -= 2;
429
430 if(direction)
431 {
432 rot2 --;
433 if(rot2 < -30)
434 direction = 0;
435 }
436 else
437 {
438 rot2 ++;
439 if(rot2 > 30)
440 direction = 1;
441 }
442
443 BallPosition += BallStep;
444 if(BallPosition < -800) BallStep = 10;
445 if(BallPosition > 800) BallStep = -10;
446 }
447
448 /*---------------------------------------------------------------------------*/
ComputeScale(float position)449 static float ComputeScale ( float position )
450 {
451 float distance;
452 float scale;
453
454 distance = BallPosition - position;
455
456 if(distance < 0) distance = -distance;
457
458 scale = (150 * 150) - (distance * distance);
459
460 if(scale < 0.0F)
461 return 100.0F;
462
463 scale = sqrtf(scale);
464
465 if(scale < 100.0F)
466 return 100.0F;
467
468 return scale;
469 }
470
471 /*---------------------------------------------------------------------------*/
ComputeNormalRotMtx(Segment * seg,u32 idx)472 static void ComputeNormalRotMtx ( Segment *seg, u32 idx )
473 {
474 Mtx mv, mra, mry, mrx;
475 float scale = seg->recomputeNormalMtx;
476 Vec axis;
477 Vec normal = ((VecPtr)MyVert)[idx];
478
479 if(seg->xlate < BallPosition)
480 axis = ((VecPtr)MyVert)[16];
481 else
482 axis = ((VecPtr)MyVert)[17];
483
484 VECCrossProduct(&axis, &normal, &axis);
485
486 MTXRotAxisDeg(mra, &axis, ((150.0F - scale) / 50.0F) * 70.0F);
487
488 MTXRotDeg(mry, 'Y', rot);
489 MTXRotDeg(mrx, 'X', rot2 * (seg->xlate/800.0F));
490
491 MTXConcat(mrx, mra, mv);
492 MTXConcat(mrx, mv, mv);
493 MTXConcat(mry, mv, mv);
494 MTXConcat(v, mv, mv);
495
496 MTXInverse(mv, mv);
497 MTXTranspose(mv, mv);
498
499 GXLoadNrmMtxImm(mv, seg->mtx);
500 }
501
502 /*===========================================================================*/
503