1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin/Revolution gx demo
3   File:     frb-fld-dbs-aa.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 
18 #define OCT_DEPTH_MIN  1 // min octahedron recursion depth
19 #define OCT_DEPTH_MAX  6 // max octahedron recursion depth
20 
21 // Octahedron vertices
22 static f32 vertNorth[] = { 0.0f, 0.0f, 1.0f };
23 static f32 vertSouth[] = { 0.0f, 0.0f, -1.0f };
24 static f32 vertEquator[] =
25 {
26     1.0f, 0.0f, 0.0f,
27     0.0f, 1.0f, 0.0f,
28     -1.0f, 0.0f, 0.0f,
29     0.0f, -1.0f, 0.0f
30 };
31 
32 // An alternate sample pattern & filter to try out
33 static u8  mySamples[12][2] = {
34     3,  3, 10,  5,  5, 10,
35     7,  2,  2,  7,  9,  9,
36     7,  2,  2,  7,  9,  9,
37     3,  3, 10,  5,  5, 10,
38 };
39 
40 static u8  myFilter[7] = {
41     0, 8, 16, 16, 16, 8, 0
42 };
43 
44 static u32 Ticks    = 0;  // time counter
45 static u8  animMode = 1;  // whether animation is going or stopped
46 static u8  drawMode = 0;  // which pattern to draw
47 static u8  aaMode   = 0;  // which filters to use
48 
49 static u32 octDepth = 3;
50 
51 GXRenderModeObj *rMode;
52 
53 /*---------------------------------------------------------------------------*
54    Forward references
55  *---------------------------------------------------------------------------*/
56 
57 void        main        ( void );
58 static void CameraInit  ( Mtx v );
59 static void DrawInit    ( void );
60 static void DrawTick    ( Mtx v );
61 static void AnimTick    ( void );
62 static void PrintIntro  ( void );
63 static void Tri         (f32 *v0, f32 *v1, f32 *v2, u8 color, u32 depth);
64 
65 /*---------------------------------------------------------------------------*
66    Application main loop
67  *---------------------------------------------------------------------------*/
68 
main(void)69 void main ( void )
70 {
71     Mtx         v;   // view matrix
72 
73     rMode = &GXNtsc240DsAa;
74 
75     DEMOInit(rMode);    // Init os, pad, gx, vi
76 
77     CameraInit(v); // Initialize the camera.
78     DrawInit();    // Define my vertex formats and set array pointers.
79 
80     PrintIntro(); // Print demo directions
81 
82     while(!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
83     {
84         DEMOBeforeRender();
85         DrawTick(v);        // Draw the model.
86         DEMODoneRender();
87 
88         DEMOPadRead();
89         AnimTick();         // Update animation.
90     }
91 
92     OSHalt("End of test");
93 }
94 
95 
96 /*---------------------------------------------------------------------------*
97    Functions
98  *---------------------------------------------------------------------------*/
99 
100 /*---------------------------------------------------------------------------*
101     Name:           CameraInit
102 
103     Description:    Initialize the projection matrix and load into hardware.
104                     Initialize the view matrix.
105 
106     Arguments:      v       view matrix
107 
108     Returns:        none
109  *---------------------------------------------------------------------------*/
CameraInit(Mtx v)110 static void CameraInit ( Mtx v )
111 {
112     Mtx44   p;      // projection matrix
113     Vec     up      = {0.0F, 0.0F, 1.0F};
114     Vec     camLoc  = {0.25F, 3.0F, 0.5F};
115     Vec     objPt   = {0.0F, 0.0F, 0.0F};
116     f32     left    = 0.0375F;
117     f32     top     = 0.050F;
118     f32     znear   = 0.1F;
119     f32     zfar    = 10.0F;
120 
121     MTXFrustum(p, left, -left, -top, top, znear, zfar);
122     GXSetProjection(p, GX_PERSPECTIVE);
123 
124     MTXLookAt(v, &camLoc, &up, &objPt);
125 }
126 
127 /*---------------------------------------------------------------------------*
128     Name:           DrawInit
129 
130     Description:    Initializes the vertex attribute format 0, and sets
131                     the array pointers and strides for the indexed data.
132 
133     Arguments:      none
134 
135     Returns:        none
136  *---------------------------------------------------------------------------*/
DrawInit(void)137 static void DrawInit( void )
138 {
139     GXColor blue = {0, 0, 255, 0};
140 
141     GXSetCopyClear(blue, 0x00ffffff);
142 
143     // Need to clear background by specified color
144     // since the clear color is different than DEMOInit default
145     // The clear operation can be done by dummy display copy
146     GXCopyDisp(DEMOGetCurrentBuffer(), GX_TRUE);
147 
148     // Set current vertex descriptor to enable position and color0.
149     // Both use 8b index to access their data arrays.
150     GXClearVtxDesc();
151     GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
152     GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
153 
154     // Position has 3 elements (x,y,z), each of type f32
155     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
156 
157     // Color 0 has 4 components (r, g, b, a), each component is 8b.
158     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
159 
160     // Initialize lighting, texgen, and tev parameters
161     GXSetNumChans(1); // default, color = vertex color
162     GXSetNumTexGens(0); // no texture in this demo
163     GXSetNumTevStages( 1 );
164     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
165     GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
166 }
167 
168 /*---------------------------------------------------------------------------*
169     Name:           Tri
170 
171     Description:    Recursively draw a triangle while alternating colors.
172 
173     Arguments:      v0        vertex 0
174                     v1        vertex 1
175                     v2        vertex 2
176                     color     color of triangle
177                     depth     recursion depth
178 
179     Returns:        none
180  *---------------------------------------------------------------------------*/
Tri(f32 * v0,f32 * v1,f32 * v2,u8 color,u32 depth)181 static void Tri (f32 *v0, f32 *v1, f32 *v2, u8 color, u32 depth)
182 {
183     f32 vertMid01[3];  // midpoint between v0 and v1
184     f32 vertMid12[3];  // midpoint between v1 and v2
185     f32 vertMid20[3];  // midpoint between v2 and v0
186 
187     // if more recursion depth to go, ...
188     if (depth > 0)
189     {
190         // compute triangle midpoints on unit spheres
191         VECAdd((VecPtr) v0, (VecPtr) v1, (VecPtr) vertMid01);
192         VECScale((VecPtr) vertMid01, (VecPtr) vertMid01, 0.5f);
193         VECNormalize((VecPtr) vertMid01, (VecPtr) vertMid01);
194 
195         VECAdd((VecPtr) v1, (VecPtr) v2, (VecPtr) vertMid12);
196         VECScale((VecPtr) vertMid12, (VecPtr) vertMid12, 0.5f);
197         VECNormalize((VecPtr) vertMid12, (VecPtr) vertMid12);
198 
199         VECAdd((VecPtr) v2, (VecPtr) v0, (VecPtr) vertMid20);
200         VECScale((VecPtr) vertMid20, (VecPtr) vertMid20, 0.5f);
201         VECNormalize((VecPtr) vertMid20, (VecPtr) vertMid20);
202 
203         // draw three outer triangles in same color as parent
204         Tri(v0, vertMid01, vertMid20, color, depth - 1);
205         Tri(v1, vertMid12, vertMid01, color, depth - 1);
206         Tri(v2, vertMid20, vertMid12, color, depth - 1);
207 
208         // draw inner triangle in complementary color
209         Tri(vertMid01, vertMid12, vertMid20, (u8) ~color, depth - 1);
210     }
211     else // at bottom of recursion
212     {
213         // draw the triangle
214         GXBegin(GX_TRIANGLES, GX_VTXFMT0, 3);
215             // vertex 0
216             GXPosition3f32( v0[0], v0[1], v0[2] );
217             GXColor4u8( color, color, color, 255 );
218 
219             // vertex 1
220             GXPosition3f32( v1[0], v1[1], v1[2] );
221             GXColor4u8( color, color, color, 255 );
222 
223             // vertex 2
224             GXPosition3f32( v2[0], v2[1], v2[2] );
225             GXColor4u8( color, color, color, 255 );
226         GXEnd();
227     }
228 }
229 
230 /*---------------------------------------------------------------------------*
231     Name:           DrawTick
232 
233     Description:    Draw the model once.
234 
235     Arguments:      v       view matrix
236 
237     Returns:        none
238  *---------------------------------------------------------------------------*/
DrawTick(Mtx v)239 static void DrawTick( Mtx v )
240 {
241     Mtx m;  // Model matrix.
242     Mtx mv; // Modelview matrix.
243 
244     switch(aaMode)
245     {
246       case 0:
247         GXSetCopyFilter(GX_TRUE, rMode->sample_pattern,
248                         GX_TRUE, rMode->vfilter);
249         break;
250       case 1:
251         GXSetCopyFilter(GX_TRUE, mySamples,
252                         GX_TRUE, myFilter);
253         break;
254       case 2:
255         GXSetCopyFilter(GX_FALSE, NULL,
256                         GX_TRUE, myFilter);
257         break;
258       case 3:
259         GXSetCopyFilter(GX_FALSE, NULL,
260                         GX_FALSE, NULL);
261         break;
262       default:
263         OSHalt("bad aaMode case");
264     }
265 
266     // model has a rotation about z axis
267     MTXRotDeg(m, 'z', Ticks);
268     MTXConcat(v, m, mv);
269     GXLoadPosMtxImm(mv, GX_PNMTX0);
270 
271     if (drawMode == 0)
272     {
273         // draw octahedron to recursion depth of octDepth
274         // draw northern hemisphere
275         Tri(&vertEquator[3], &vertEquator[0], vertNorth, 0,   octDepth);
276         Tri(&vertEquator[6], &vertEquator[3], vertNorth, 255, octDepth);
277         Tri(&vertEquator[9], &vertEquator[6], vertNorth, 0,   octDepth);
278         Tri(&vertEquator[0], &vertEquator[9], vertNorth, 255, octDepth);
279 
280         // draw southern hemisphere
281         Tri(&vertEquator[0], &vertEquator[3], vertSouth, 255, octDepth);
282         Tri(&vertEquator[3], &vertEquator[6], vertSouth, 0,   octDepth);
283         Tri(&vertEquator[6], &vertEquator[9], vertSouth, 255, octDepth);
284         Tri(&vertEquator[9], &vertEquator[0], vertSouth, 0,   octDepth);
285     }
286     if (drawMode == 1)
287     {
288         int i;
289         f32 x, y;
290 
291         GXBegin(GX_LINES, GX_VTXFMT0, 30*2);
292         for(i=0; i<30; i++)
293         {
294             x = cosf(i/15.0F * 3.1415926535F);
295             y = sinf(i/15.0F * 3.1415926535F);
296 
297             // vertex 0
298             GXPosition3f32( 0.0F, 0.0F, 0.0F );
299             GXColor4u8( 255, 255, 255, 255 );
300 
301             // vertex 1
302             GXPosition3f32( x, y, 0.0F );
303             GXColor4u8( 255, 255, 255, 255 );
304         }
305         GXEnd();
306     }
307 }
308 
309 /*---------------------------------------------------------------------------*
310     Name:           AnimTick
311 
312     Description:    Computes next time step.
313 
314     Arguments:      none
315 
316     Returns:        none
317  *---------------------------------------------------------------------------*/
AnimTick(void)318 static void AnimTick( void )
319 {
320     u8  oldaaMode = aaMode;
321     u16 down = DEMOPadGetButtonDown(0);
322 
323     if (down & PAD_BUTTON_X)
324     {
325         animMode = ! animMode;
326     }
327 
328     if (down & PAD_BUTTON_Y)
329     {
330         drawMode = ! drawMode;
331     }
332 
333     if (DEMOPadGetButton(0) & PAD_BUTTON_A)
334     {
335         aaMode |= 1;
336     }
337     else
338     {
339         aaMode &= ~1;
340     }
341 
342     if (down & PAD_BUTTON_B)
343     {
344         aaMode+=2;
345         if (aaMode > 3)
346             aaMode = 0;
347     }
348 
349     if (down & PAD_TRIGGER_R)
350     {
351     	octDepth++;
352         if (octDepth > OCT_DEPTH_MAX)
353             octDepth = OCT_DEPTH_MAX;
354     }
355 
356     if (down & PAD_TRIGGER_L)
357     {
358     	octDepth--;
359         if (octDepth < OCT_DEPTH_MIN)
360             octDepth = OCT_DEPTH_MIN;
361     }
362 
363     if (animMode)
364     {
365         Ticks++;
366     }
367 
368     if (aaMode != oldaaMode)
369     {
370         switch(aaMode)
371         {
372           case 0:  OSReport("Regular filter\n"); break;
373           case 1:  OSReport("Modified filter\n"); break;
374           case 2:  OSReport("AA off, deflicker on\n"); break;
375           case 3:  OSReport("AA off, deflicker off\n"); break;
376           default: OSHalt("bad aaMode case\n");
377         }
378     }
379 }
380 
381 /*---------------------------------------------------------------------------*
382     Name:           PrintIntro
383 
384     Description:    Prints the directions on how to use this demo.
385 
386     Arguments:      none
387 
388     Returns:        none
389  *---------------------------------------------------------------------------*/
PrintIntro(void)390 static void PrintIntro( void )
391 {
392     OSReport("\n\n*************************************************\n");
393     OSReport("frb-fld-dbs-aa: demonstrate double-strike field antialiasing\n");
394     OSReport("Button A - hold to show alternate AA mode\n");
395     OSReport("Button B - press to toggle AA on/off\n\n");
396     OSReport("Button X - press to toggle animation on/off\n");
397     OSReport("Button Y - press to toggle drawing mode\n");
398     OSReport("Triggers - press to change levels of recursive subdivision\n");
399     OSReport("\nTo quit:\n");
400     OSReport("     press the start/pause button\n");
401     OSReport("***************************************************\n");
402 }
403