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