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 CameraInit(v); // Initialize the camera.
154 DrawInit(); // Define my vertex formats and set array pointers.
155
156 while(!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
157 {
158 DEMOBeforeRender();
159
160 DrawTick(v); // Draw the model.
161
162 DEMODoneRender();
163
164 DEMOPadRead(); // Update pad status.
165 AnimTick(); // Update animation.
166 }
167
168 OSHalt("End of test");
169 }
170
171
172 /*---------------------------------------------------------------------------*
173 Functions
174 *---------------------------------------------------------------------------*/
175 /*---------------------------------------------------------------------------*
176 Name: CameraInit
177
178 Description: Initialize the projection matrix and load into hardware.
179 Initialize the view matrix.
180
181 Arguments: v view matrix
182
183 Returns: none
184 *---------------------------------------------------------------------------*/
CameraInit(Mtx v)185 static void CameraInit ( Mtx v )
186 {
187 Mtx44 p; // projection matrix
188 Vec up = {0.0F, 1.0F, 0.0F};
189 Vec camLoc = {0.0F, 0.0F, 1200.0F};
190 Vec objPt = {0.0F, 0.0F, 0.0F};
191 f32 left = 240.0F;
192 f32 top = 320.0F;
193 f32 znear = 500.0F;
194 f32 zfar = 2000.0F;
195
196 MTXFrustum(p, left, -left, -top, top, znear, zfar);
197 GXSetProjection(p, GX_PERSPECTIVE);
198
199 MTXLookAt(v, &camLoc, &up, &objPt);
200 }
201
202 /*---------------------------------------------------------------------------*
203 Name: DrawInit
204
205 Description: Initializes the vertex attribute format 0, and sets
206 the array pointers and strides for the indexed data.
207
208 Arguments: none
209
210 Returns: none
211 *---------------------------------------------------------------------------*/
DrawInit(void)212 static void DrawInit( void )
213 {
214 u32 i;
215 f32 a;
216 GXColor c = {255, 255, 255, 255};
217
218 GXSetCullMode(GX_CULL_NONE);
219
220 // for generated models
221 GXSetVtxAttrFmt(GX_VTXFMT3, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
222 GXSetVtxAttrFmt(GX_VTXFMT3, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
223 GXSetVtxAttrFmt(GX_VTXFMT3, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
224
225 GXClearVtxDesc();
226 GXSetVtxDesc(GX_VA_PNMTXIDX, GX_DIRECT);
227 GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
228 GXSetVtxDesc(GX_VA_NRM, GX_INDEX8);
229 GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
230
231 GXSetArray(GX_VA_POS, MyVert, 3*sizeof(f32));
232 GXSetArray(GX_VA_NRM, MyVert, 3*sizeof(f32));
233
234 //
235 // set up light parameters
236 //
237
238 GXInitLightPos(&MyLight, 0.0F, 0.0F, 0.0F);
239 GXInitLightColor(&MyLight, c);
240 GXLoadLightObjImm(&MyLight, GX_LIGHT0);
241
242 c.g = c.b = 0;
243 GXSetChanMatColor(GX_COLOR0, c);
244
245 GXSetNumChans( 1 );
246 GXSetNumTexGens( 0 );
247 GXSetTevOp( GX_TEVSTAGE0, GX_PASSCLR );
248 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
249
250 a = 0.0F;
251 for (i = 0; i < 16; i++)
252 {
253 a = i * 2.0F * PI / 16.0F;
254 MyVert[3*i] = sinf(a); // x
255 MyVert[3*i+1] = cosf(a); // y
256 MyVert[3*i+2] = 0.0F; // z
257 }
258
259 MyVert[3*16] = 0; // x
260 MyVert[3*16+1] = 0; // y
261 MyVert[3*16+2] = 1; // z
262
263 MyVert[3*17] = 0; // x
264 MyVert[3*17+1] = 0; // y
265 MyVert[3*17+2] = -1;// z
266
267 // flush array from CPU $
268 DCFlushRange(MyVert, 54 * sizeof(f32));
269 }
270
271
272 /*---------------------------------------------------------------------------*
273 Name: DrawTick
274
275 Description: Draw the model once.
276 GXInit makes GX_PNMTX0 the default matrix.
277
278 Arguments: v view matrix
279
280 Returns: none
281 *---------------------------------------------------------------------------*/
DrawTick(Mtx v)282 static void DrawTick( Mtx v )
283 {
284 u8 i, j, k;
285 Mtx ms; // Model matrix. scale
286 Mtx mry, mrx; // Model matrix. rotate
287 Mtx mt; // Model matrix. translate
288 Mtx mv; // Modelview matrix.
289 float scale;
290
291
292 GXSetChanCtrl(
293 GX_COLOR0,
294 GX_ENABLE, // enable channel
295 GX_SRC_REG, // amb source
296 GX_SRC_VTX, // mat source
297 GX_LIGHT0, // light mask
298 GX_DF_CLAMP, // diffuse function
299 GX_AF_NONE);
300
301 // build each segment matrix
302 // assumes less than 10 segs for now...
303 for (k = 0; k < 6; k++)
304 {
305 for (i = 0; i < 10; i++)
306 {
307 scale = ComputeScale(segs[(i + (10 * k)) - k].xlate);
308 MTXScale(ms, scale, scale, 100.0F);
309 MTXTrans(mt, 0.0F, 0.0F, segs[(i + (10 * k)) - k].xlate);
310 MTXRotDeg(mry, 'Y', rot);
311 MTXRotDeg(mrx, 'X', rot2 * (segs[(i + (10 * k)) - k].xlate/800.0F));
312
313 MTXConcat(mt, ms, mv);
314 MTXConcat(mrx, mv, mv);
315 MTXConcat(mry, mv, mv);
316 MTXConcat(v, mv, mv);
317 GXLoadPosMtxImm(mv, segs[(i + (10 * k)) - k].mtx);
318
319 if(scale == 100.00F) // segment is not in the bulge, do not adjust normals
320 {
321 MTXInverse(mv, mv);
322 MTXTranspose(mv, mv);
323 segs[(i + (10 * k)) - k].recomputeNormalMtx = 0;
324 GXLoadNrmMtxImm(mv, segs[(i + (10 * k)) - k].mtx);
325 }
326 else
327 segs[(i + (10 * k)) - k].recomputeNormalMtx = scale;
328 }
329
330 // draw each segment
331 // assume number of segs less than matrix memory size for now
332 for (j = 0; j < 9; j++)
333 {
334
335 for (i = 0; i < 16; i++)
336 {
337 if(segs[((j + (10 * k)) - k) + 1].recomputeNormalMtx)
338 ComputeNormalRotMtx(&(segs[((j + (10 * k)) - k) + 1]), i);
339 if(segs[((j + (10 * k)) - k)].recomputeNormalMtx)
340 ComputeNormalRotMtx(&(segs[((j + (10 * k)) - k)]), i);
341 }
342 // finish cylinder
343 if(segs[((j + (10 * k)) - k) + 1].recomputeNormalMtx)
344 ComputeNormalRotMtx(&(segs[((j + (10 * k)) - k) + 1]), 0);
345 if(segs[((j + (10 * k)) - k)].recomputeNormalMtx)
346 ComputeNormalRotMtx(&(segs[((j + (10 * k)) - k)]), 0);
347
348 // make this a function of circle divisions
349 GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT3, 17*2);
350 for (i = 0; i < 16; i++)
351 {
352 GXMatrixIndex1u8(segs[((j + (10 * k)) - k) + 1].mtx);
353 GXPosition1x8(i);
354 GXNormal1x8(i);
355 GXColor1u32(MyColors[k]);
356
357 GXMatrixIndex1u8(segs[((j + (10 * k)) - k)].mtx);
358 GXPosition1x8(i);
359 GXNormal1x8(i);
360 GXColor1u32(MyColors[k]);
361 }
362 // finish cylinder
363 GXMatrixIndex1u8(segs[((j + (10 * k)) - k) + 1].mtx);
364 GXPosition1x8(0);
365 GXNormal1x8(0);
366 GXColor1u32(MyColors[k]);
367
368 GXMatrixIndex1u8(segs[((j + (10 * k)) - k)].mtx);
369 GXPosition1x8(0);
370 GXNormal1x8(0);
371 GXColor1u32(MyColors[k]);
372 GXEnd();
373 }
374 }
375
376 GXSetChanCtrl(
377 GX_COLOR0,
378 GX_ENABLE, // enable channel
379 GX_SRC_REG, // amb source
380 GX_SRC_REG, // mat source
381 GX_LIGHT0, // light mask
382 GX_DF_CLAMP, // diffuse function
383 GX_AF_NONE);
384
385 MTXTrans(mt, 0.0F, 0.0F, BallPosition);
386 MTXRotDeg(mry, 'Y', rot);
387 MTXScale(ms, 125.0F, 125.0F, 125.0F);
388 MTXRotDeg(mrx, 'X', rot2 * (BallPosition/800.0F));
389
390 MTXConcat(mt, ms, mv);
391 MTXConcat(mrx, mv, mv);
392 MTXConcat(mry, mv, mv);
393 MTXConcat(v, mv, mv);
394 GXLoadPosMtxImm(mv, GX_PNMTX0);
395 MTXInverse(mv, mv);
396 MTXTranspose(mv, mv);
397 GXLoadNrmMtxImm(mv, GX_PNMTX0);
398
399 GXSetCurrentMtx(GX_PNMTX0);
400
401 GXDrawSphere1(2);
402 }
403
404 /*---------------------------------------------------------------------------*
405 Name: AnimTick
406
407 Description: Changes scene parameters.
408
409 Arguments: none
410
411 Returns: none
412 *---------------------------------------------------------------------------*/
AnimTick(void)413 static void AnimTick( void )
414 {
415 if (DEMOPadGetStickX(0) > 0)
416 rot += 2;
417 else if (DEMOPadGetStickX(0) < 0)
418 rot -= 2;
419
420 if(direction)
421 {
422 rot2 --;
423 if(rot2 < -30)
424 direction = 0;
425 }
426 else
427 {
428 rot2 ++;
429 if(rot2 > 30)
430 direction = 1;
431 }
432
433 BallPosition += BallStep;
434 if(BallPosition < -800) BallStep = 10;
435 if(BallPosition > 800) BallStep = -10;
436 }
437
438 /*---------------------------------------------------------------------------*/
ComputeScale(float position)439 static float ComputeScale ( float position )
440 {
441 float distance;
442 float scale;
443
444 distance = BallPosition - position;
445
446 if(distance < 0) distance = -distance;
447
448 scale = (150 * 150) - (distance * distance);
449
450 if(scale < 0.0F)
451 return 100.0F;
452
453 scale = sqrtf(scale);
454
455 if(scale < 100.0F)
456 return 100.0F;
457
458 return scale;
459 }
460
461 /*---------------------------------------------------------------------------*/
ComputeNormalRotMtx(Segment * seg,u32 idx)462 static void ComputeNormalRotMtx ( Segment *seg, u32 idx )
463 {
464 Mtx mv, mra, mry, mrx;
465 float scale = seg->recomputeNormalMtx;
466 Vec axis;
467 Vec normal = ((VecPtr)MyVert)[idx];
468
469 if(seg->xlate < BallPosition)
470 axis = ((VecPtr)MyVert)[16];
471 else
472 axis = ((VecPtr)MyVert)[17];
473
474 VECCrossProduct(&axis, &normal, &axis);
475
476 MTXRotAxisDeg(mra, &axis, ((150.0F - scale) / 50.0F) * 70.0F);
477
478 MTXRotDeg(mry, 'Y', rot);
479 MTXRotDeg(mrx, 'X', rot2 * (seg->xlate/800.0F));
480
481 MTXConcat(mrx, mra, mv);
482 MTXConcat(mrx, mv, mv);
483 MTXConcat(mry, mv, mv);
484 MTXConcat(v, mv, mv);
485
486 MTXInverse(mv, mv);
487 MTXTranspose(mv, mv);
488
489 GXLoadNrmMtxImm(mv, seg->mtx);
490 }
491
492 /*===========================================================================*/
493