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