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