1 /*---------------------------------------------------------------------------*
2 Project: Dolphin/Revolution gx demo
3 File: smp-toy-draw.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 "toy-stick.h"
16 #include "toy-anim.h"
17
18
19 #define MAX_SCOORD 0x4000 // for 16b, 2.14 fixed point format
20 #define MAX_TCOORD 0x4000 // for 16b, 2.14 fixed point format
21 #define STEP_SCOORD 4
22 #define STEP_TCOORD 5
23
24 #define TILTX_SCALE 10.0F
25 #define TILTZ_SCALE 10.0F
26 #define BOX_CENTROIDX 70.0F
27 #define BOX_CENTROIDZ 70.0F
28
29 #define WATER1_TEX_ID 3
30 #define BALL32_TEX_ID 7
31
32 /*---------------------------------------------------------------------------*
33 Model Data
34 *---------------------------------------------------------------------------*/
35
36 /*---------------------------------------------------------------------------*
37 It IS NOT necessary to align attribute arrays to 32B, but doing so may
38 result in a slight performance improvement.
39 The macro ATTRIBUTE_ALIGN provides a convenient way to align initialized
40 arrays.
41 *---------------------------------------------------------------------------*/
42
43 static s16 TopVerts[] ATTRIBUTE_ALIGN(32) =
44 {
45 0, 0, 0, // 0
46 140, 0, 0, // 1
47 0, 0, 140, // 2
48 140, 0, 140, // 3
49 20, 0, 20, // 4
50 120, 0, 20, // 5
51 20, 0, 120, // 6
52 120, 0, 120, // 7
53 40, 0, 20, // 8
54 60, 0, 20, // 9
55 80, 0, 20, // 10
56 100, 0, 20, // 11
57 80, 0, 40, // 12
58 100, 0, 40, // 13
59 60, 0, 60, // 14
60 100, 0, 60, // 15
61 40, 0, 80, // 16
62 80, 0, 80, // 17
63 40, 0, 100, // 18
64 60, 0, 100, // 19
65 40, 0, 120, // 20
66 60, 0, 120, // 21
67 80, 0, 120, // 22
68 100, 0, 120, // 23
69 0, -70, 0, // 24
70 140, -70, 0, // 25
71 0, -70, 140, // 26
72 140, -70, 140, // 27
73 20, -10, 20, // 28
74 60, -10, 20, // 29
75 60, -10, 60, // 30
76 100, -10, 60, // 31
77 100, -10, 120, // 32
78 60, -10, 20, // 33
79 100, -10, 20, // 34
80 100, -10, 45, // 35
81 60, -10, 105, // 36
82 60, -10, 120, // 37
83 100, -10, 20, // 38
84 120, -10, 20, // 39
85 120, -10, 120, // 40
86 80, -10, 120, // 41
87 40, -10, 120, // 42
88 20, -10, 120 // 43
89 };
90
91
92 static u8 TexCoords_u8[] ATTRIBUTE_ALIGN(32) =
93 {
94 // s, t (8.0 fixed point)
95 0x00, 0x00, // 0
96 0x01, 0x00, // 1
97 0x01, 0x01, // 2
98 0x00, 0x01 // 3
99 };
100
101 static u8 Colors[] ATTRIBUTE_ALIGN(32) =
102 {
103 // r g b a
104 255, 255, 255, 255, // 0
105 124, 120, 128, 255, // 1
106 60, 60, 64, 255, // 2
107 200, 200, 200, 255, // 3
108 95, 95, 100, 255, // 4
109 54, 54, 58, 255 // 5
110 };
111
112 static GXTexObj WaterTexObj;
113 static GXTexObj BallTexObj;
114
115 static TPLPalettePtr tpl = 0;
116
117 /*---------------------------------------------------------------------------*
118 Forward references
119 *---------------------------------------------------------------------------*/
120
121 void main ( void );
122 static void CameraInit ( Mtx v );
123 static void DrawInit ( void );
124 static void DrawTick ( Mtx v );
125
126 /*---------------------------------------------------------------------------*
127 Application main loop
128 *---------------------------------------------------------------------------*/
129
main(void)130 void main ( void )
131 {
132 Mtx v; // view matrix
133
134 DEMOInit(NULL); // init os, pad, gx, vi
135
136 CameraInit(v); // Initialize the camera.
137 DrawInit(); // Define my vertex formats and set array pointers.
138
139 OSReport("***************************************\n");
140 OSReport("to play:\n");
141 OSReport(" Use the STICK X/Y to tilt the table and roll the ball.\n");
142 OSReport("***************************************\n\n");
143
144 while(!StickDone())
145 {
146 DEMOBeforeRender();
147 DrawTick(v); // Draw the model.
148 DEMODoneRender();
149 StickTick(); // Read controller
150 AnimTick(); // Update animation.
151 }
152
153 OSHalt("End of demo");
154 }
155
156 /*---------------------------------------------------------------------------*
157 Functions
158 *---------------------------------------------------------------------------*/
159
160 /*---------------------------------------------------------------------------*
161 Name: CameraInit
162
163 Description: Initialize the projection matrix and load into hardware.
164 Initialize the view matrix.
165
166 Arguments: v view matrix
167
168 Returns: none
169 *---------------------------------------------------------------------------*/
CameraInit(Mtx v)170 static void CameraInit ( Mtx v )
171 {
172 Mtx44 p; // projection matrix
173 Vec up = {0.0F, 0.0F, 1.0F};
174 Vec camLoc = {155.0F, 200.0F, -5.0F};
175 Vec objPt = {70.0F, 0.0F, 70.0F};
176 f32 top = 24.0F;
177 f32 bot = -top;
178 f32 right = 32.0F;
179 f32 left = -right;
180 f32 znear = 50.0F;
181 f32 zfar = 2000.0F;
182
183 MTXFrustum(p, top, bot, left, right, znear, zfar);
184 GXSetProjection(p, GX_PERSPECTIVE);
185
186 MTXLookAt(v, &camLoc, &up, &objPt);
187 }
188
189 /*---------------------------------------------------------------------------*
190 Name: DrawInit
191
192 Description: Initializes vertex attribute formats, and sets
193 the array pointers and strides for the indexed data. Also
194 sets some default state for this app.
195
196 Arguments: none
197
198 Returns: none
199 *---------------------------------------------------------------------------*/
DrawInit(void)200 static void DrawInit( void )
201 {
202 GXColor black = {0, 0, 0, 0};
203
204 GXSetCopyClear(black, 0x0FFFFFF);
205
206 // show inside walls of box
207 GXSetCullMode(GX_CULL_NONE);
208
209 /*
210 Vertex Attribute Format 0
211
212 */
213 // Position has 3 elements (x,y,z), each of type s16,
214 // no fractional bits (integers)
215 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 0);
216 // Clr0 has 4 components (r, g, b, a), each component is 8b.
217 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
218 // Texture coordinate is 16-bit fixed-point, with 14 fractional bits
219 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_U16, 14);
220
221 /*
222 Vertex Attribute Format 1
223 */
224 GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
225 GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
226 GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_U8, 0);
227
228 /*
229 Set Array Pointers and Strides
230 */
231 // stride = 3 elements (x,y,z) each of type s16
232 GXSetArray(GX_VA_POS, TopVerts, 3*sizeof(s16));
233 // stride = 2 elements (s,t) each of type u8
234 GXSetArray(GX_VA_CLR0, Colors, 4*sizeof(u8));
235 // Texture coordinate has 2 components (s,t), each component is 8b
236 GXSetArray(GX_VA_TEX0, TexCoords_u8, 2*sizeof(u8));
237
238 /*
239 Init texture objects, from gxTextrs.tpl
240 */
241 TPLGetPalette(&tpl, "gxTextrs.tpl");
242 // Initialize a texture object to contain the correct texture
243 TPLGetGXTexObjFromPalette(tpl, &WaterTexObj, WATER1_TEX_ID);
244 TPLGetGXTexObjFromPalette(tpl, &BallTexObj, BALL32_TEX_ID);
245 }
246
247 /*---------------------------------------------------------------------------*
248 Name: VertexC
249
250 Description: Draw a vertex with color
251
252 Arguments: v 8-bit position index
253 c 8-bit color index
254
255 Returns: none
256 *---------------------------------------------------------------------------*/
VertexC(u8 v,u8 c)257 static inline void VertexC( u8 v, u8 c )
258 {
259 GXPosition1x8(v);
260 GXColor1x8(c);
261 }
262
263 /*---------------------------------------------------------------------------*
264 Name: VertexT
265
266 Description: Draw a vertex with texture, direct data
267
268 Arguments: v 8-bit position index
269 s, t 16-bit tex coord
270
271 Returns: none
272 *---------------------------------------------------------------------------*/
VertexT(u8 v,u16 s,u16 t)273 static inline void VertexT( u8 v, u16 s, u16 t )
274 {
275 GXPosition1x8(v);
276 GXTexCoord2u16(s, t);
277 }
278
279 /*---------------------------------------------------------------------------*
280 Name: DrawTexQuad
281
282 Description: Draw a textured quad. Map extends to corners of the quad.
283 MAX_SCOORD is the value of 1.0 in the fixed point format.
284
285 Arguments: v0 8-bit position
286 v1 8-bit position
287 v2 8-bit position
288 v3 8-bit position
289 s0 16-bit s tex coord at v0
290 t0 16-bit t tex coord at v0
291
292 Returns: none
293 *---------------------------------------------------------------------------*/
DrawTexQuad(u8 v0,u8 v1,u8 v2,u8 v3,u16 s0,u16 t0)294 static inline void DrawTexQuad(
295 u8 v0,
296 u8 v1,
297 u8 v2,
298 u8 v3,
299 u16 s0,
300 u16 t0 )
301 {
302 VertexT(v0, s0, t0);
303 VertexT(v1, (u16)(s0+MAX_SCOORD), (u16)t0);
304 VertexT(v2, (u16)(s0+MAX_SCOORD), (u16)(t0+MAX_TCOORD));
305 VertexT(v3, (u16)s0, (u16)(t0+MAX_TCOORD));
306 }
307
308 /*---------------------------------------------------------------------------*
309 Name: DrawFSQuad
310
311 Description: Draw a flat shaded quad.
312
313 Arguments: v0 8-bit position
314 v1 8-bit position
315 v2 8-bit position
316 v3 8-bit position
317 c color
318
319 Returns: none
320 *---------------------------------------------------------------------------*/
DrawFSQuad(u8 v0,u8 v1,u8 v2,u8 v3,u8 c)321 static inline void DrawFSQuad(
322 u8 v0,
323 u8 v1,
324 u8 v2,
325 u8 v3,
326 u8 c )
327 {
328 VertexC(v0, c);
329 VertexC(v1, c);
330 VertexC(v2, c);
331 VertexC(v3, c);
332 }
333
334 /*---------------------------------------------------------------------------*
335 Name: DrawSSQuad
336
337 Description: Draw a smooth shaded quad.
338
339 Arguments: v0 8-bit position
340 c0 color at v0
341 v1 8-bit position
342 c1 color at v1
343 v2 8-bit position
344 c2 color at v2
345 v3 8-bit position
346 c3 color at v3
347
348 Returns: none
349 *---------------------------------------------------------------------------*/
DrawSSQuad(u8 v0,u8 c0,u8 v1,u8 c1,u8 v2,u8 c2,u8 v3,u8 c3)350 static inline void DrawSSQuad(
351 u8 v0, u8 c0,
352 u8 v1, u8 c1,
353 u8 v2, u8 c2,
354 u8 v3, u8 c3 )
355 {
356 VertexC(v0, c0);
357 VertexC(v1, c1);
358 VertexC(v2, c2);
359 VertexC(v3, c3);
360 }
361
362 /*---------------------------------------------------------------------------*
363 Name: DrawBall
364
365 Description: Draw texture image of a ball at the given position.
366 Uses Direct data for x,y,z. Uses indexed data for
367 texture coordinates.
368
369 Arguments: x,y,z position to draw ball
370
371 Returns: none
372 *---------------------------------------------------------------------------*/
DrawBall(f32 x,f32 y,f32 z)373 static void DrawBall( f32 x, f32 y, f32 z )
374 {
375 // set Tev to pass texture color and alpha
376 GXSetNumChans( 0 );
377 GXSetNumTexGens( 1 );
378 GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE);
379 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
380 // set texture object
381 GXLoadTexObj(&BallTexObj, GX_TEXMAP0);
382 // enable alpha blending
383 GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA,
384 GX_LO_CLEAR);
385 // set vertex descriptor
386 GXClearVtxDesc();
387 GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
388 GXSetVtxDesc(GX_VA_TEX0, GX_INDEX8);
389
390 // draw ball texture
391 GXBegin(GX_QUADS, GX_VTXFMT1, 4);
392 GXPosition3f32( x - BALL_SIZEX, y, z - BALL_SIZEZ );
393 GXTexCoord1x8(2);
394 GXPosition3f32( x + BALL_SIZEX, y, z - BALL_SIZEZ );
395 GXTexCoord1x8(3);
396 GXPosition3f32( x + BALL_SIZEX, y, z + BALL_SIZEZ );
397 GXTexCoord1x8(0);
398 GXPosition3f32( x - BALL_SIZEX, y, z + BALL_SIZEZ );
399 GXTexCoord1x8(1);
400 GXEnd();
401
402 // restore default value, disable blending
403 GXSetBlendMode(GX_BM_NONE, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA,
404 GX_LO_CLEAR);
405 }
406
407 /*---------------------------------------------------------------------------*
408 Name: DrawBottom
409
410 Description: Draw bottom of box model. Animates a texture along the
411 bottom of the box. The order the parts are drawn is
412 important since z- buffering is turned off.
413
414 Arguments: none
415
416 Returns: none
417 *---------------------------------------------------------------------------*/
DrawBottom(void)418 static void DrawBottom( void )
419 {
420 static u16 s = 0;
421 static u16 t = 0;
422
423 // use texture in Tev
424 GXSetNumChans( 0 );
425 GXSetNumTexGens( 1 );
426 GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE);
427 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
428 // set texture object
429 GXLoadTexObj(&WaterTexObj, GX_TEXMAP0);
430 // set vertex descriptor
431 GXClearVtxDesc();
432 GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
433 GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
434
435 // draw water texture on bottom of box
436 GXBegin(GX_QUADS, GX_VTXFMT0, 4);
437 DrawTexQuad(25, 27, 26, 24, s, t);
438 GXEnd();
439
440 // translate s, t coordinates
441 s += STEP_SCOORD;
442 t += STEP_TCOORD;
443 if (s > MAX_SCOORD) s = 0;
444 if (t > MAX_TCOORD) t = 0;
445
446 // select Color0 in Tev
447 GXSetNumChans( 1 );
448 GXSetNumTexGens( 0 );
449 GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
450 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
451
452 // change vertex descriptor
453 GXClearVtxDesc();
454 GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
455 GXSetVtxDesc(GX_VA_CLR0, GX_INDEX8);
456
457 GXBegin(GX_QUADS, GX_VTXFMT0, 44);
458 // sides of cube
459 DrawFSQuad(2, 26, 24, 0, 5);
460 DrawFSQuad(24, 25, 1, 0, 1);
461 DrawFSQuad(3, 27, 26, 2, 4);
462 DrawFSQuad(27, 3, 1, 25, 2);
463 // misc edges
464 DrawFSQuad(40, 7, 23, 32, 1);
465 DrawFSQuad(41, 23, 21, 37, 1);
466 DrawFSQuad(42, 20, 6, 43, 1);
467 DrawFSQuad(43, 6, 4, 28, 2);
468 // bottom bridge
469 DrawSSQuad(12, 1, 13, 1, 19, 3, 18, 3);
470 DrawFSQuad(10, 11, 13, 12, 0);
471 DrawFSQuad(18, 19, 21, 20, 0);
472 GXEnd();
473
474 // bottom bridge, side
475 GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT0, 8);
476 VertexC(37, 2);
477 VertexC(21, 2);
478 VertexC(36, 2);
479 VertexC(19, 2);
480 VertexC(35, 2);
481 VertexC(13, 2);
482 VertexC(34, 2);
483 VertexC(11, 2);
484 GXEnd();
485
486 }
487
488 /*---------------------------------------------------------------------------*
489 Name: DrawTop
490
491 Description: Draw top of box model. The order the parts are drawn is
492 important since z- buffering is turned off.
493
494 Arguments: none
495
496 Returns: none
497 *---------------------------------------------------------------------------*/
DrawTop(void)498 static void DrawTop( void )
499 {
500 // set Tev to use vertex color
501 GXSetNumChans( 1 );
502 GXSetNumTexGens( 0 );
503 GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
504 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
505 // set vertex descriptor
506 GXClearVtxDesc();
507 GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
508 GXSetVtxDesc(GX_VA_CLR0, GX_INDEX8);
509
510 GXBegin(GX_QUADS, GX_VTXFMT0, 8);
511 // top, left and right
512 DrawFSQuad(0, 4, 6, 2, 0);
513 DrawFSQuad(3, 7, 5, 1, 0);
514 GXEnd();
515
516 // top bridge, side
517 GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT0, 8);
518 VertexC(32, 2);
519 VertexC(23, 2);
520 VertexC(31, 2);
521 VertexC(15, 2);
522 VertexC(30, 2);
523 VertexC(14, 2);
524 VertexC(29, 2);
525 VertexC( 9, 2);
526 GXEnd();
527
528 // top bridge
529 GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT0, 8);
530 VertexC(8, 0);
531 VertexC(9, 0);
532 VertexC(16, 0);
533 VertexC(14, 0);
534 VertexC(17, 0);
535 VertexC(15, 0);
536 VertexC(22, 0);
537 VertexC(23, 0);
538 GXEnd();
539
540 // Use fans here so no T-junctions
541 // top, bottom edge
542 //
543 GXBegin(GX_TRIANGLEFAN, GX_VTXFMT0, 8);
544 VertexC( 7, 0);
545 VertexC( 3, 0);
546 VertexC( 2, 0);
547 VertexC( 6, 0);
548 VertexC(20, 0);
549 VertexC(21, 0);
550 VertexC(22, 0);
551 VertexC(23, 0);
552 GXEnd();
553
554 // top, top edge
555 GXBegin(GX_TRIANGLEFAN, GX_VTXFMT0, 8);
556 VertexC(4, 0);
557 VertexC(0, 0);
558 VertexC(1, 0);
559 VertexC(5, 0);
560 VertexC(11, 0);
561 VertexC(10, 0);
562 VertexC(9, 0);
563 VertexC(8, 0);
564 GXEnd();
565 }
566
567 /*---------------------------------------------------------------------------*
568 Name: DrawTick
569
570 Description: Draw the entire model once. Draws the bottom box, ball,
571 and top box. Translate ball when on slope. This is
572 done because the collision detection thinks the slope
573 is really straight. See toy-anim.c.
574
575 Arguments: v view matrix
576
577 Returns: none
578 *---------------------------------------------------------------------------*/
DrawTick(Mtx v)579 static void DrawTick(Mtx v)
580 {
581 Mtx m; // Model matrix.
582 Mtx mv; // Modelview matrix.
583 f32 x; // translate ball when on slope
584 Vec curpos; // current position
585
586 // turn off z-buffering, since viewpoint is controlled
587 GXSetZMode(GX_FALSE, GX_ALWAYS, GX_FALSE);
588
589 // tilt the box around its centroid
590 MTXTrans(m, BOX_CENTROIDX, 0.0F, BOX_CENTROIDX);
591 MTXConcat(v, m, mv);
592 MTXRotDeg(m, 'x', GetAnalogY()*TILTX_SCALE);
593 MTXConcat(mv, m, mv);
594 MTXRotDeg(m, 'z', GetAnalogX()*TILTZ_SCALE);
595 MTXConcat(mv, m, mv);
596 MTXTrans(m, -BOX_CENTROIDX, 0.0F, -BOX_CENTROIDX);
597 MTXConcat(mv, m, mv);
598 GXLoadPosMtxImm(mv, GX_PNMTX0);
599
600 DrawBottom();
601
602 curpos = GetCurPos();
603 if (OnSlope() && !DoTeleport()) {
604 x = curpos.x - ((curpos.z - SLOPE_ZSTART) * SLOPE_SLOPE);
605 DrawBall(x, 0.0F, curpos.z);
606 DrawTop();
607 } else {
608 DrawTop();
609 DrawBall(curpos.x, 0.0F, curpos.z);
610 }
611 }
612
613