1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin/Revolution gx demo
3   File:     cul-faces.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 #include <demo.h>
14 #include <math.h>
15 #include "cmn-model.h"
16 
17 #define SCREEN_WD       1       // Dummy - actual value filled at runtime
18 #define SCREEN_HT       1       // Dummy - actual value filled at runtime
19 #define SCREEN_DEPTH    128.0f
20 #define SCREEN_ZNEAR    0.0f    // near plane Z in screen coordinates
21 #define SCREEN_ZFAR 1.0f    // far  plane Z in screen coordinates
22 #define ZBUFFER_MAX 0x00ffffff
23 
24 /*---------------------------------------------------------------------------*
25    Typedefs
26  *---------------------------------------------------------------------------*/
27 typedef struct
28 {
29     Camera*     camera;
30     ViewPort*   viewport;
31     GXCullMode  cullmode;
32     u32         flag;
33 }   Scene;
34 
35 #define SCENE_DRAWN (1<<0)
36 
37 typedef struct
38 {
39     u32         modelId;
40     u32         numScene;
41     Scene*      scene;
42     u32         screen_wd;
43     u32         screen_ht;
44 }   GlobalScene;
45 
46 /*---------------------------------------------------------------------------*
47    Forward references
48  *---------------------------------------------------------------------------*/
49 static void    GlobalSceneDraw( GlobalScene* );
50 static void    SceneDraw      ( GlobalScene*, Scene* );
51 static void    SceneDrawInfo  ( Scene* );
52 static void    SceneControl   ( GlobalScene* );
53 static void    myDrawModel    ( GlobalScene*, Camera* );
54 static void    PrintIntro     ( void );
55 
56 /*---------------------------------------------------------------------------*
57    Rendering parameters
58  *---------------------------------------------------------------------------*/
59 Camera   myCamera =
60 {
61     { 0.0f,   0.0f, 0.0f }, // position
62     { 0.0f,1000.0f, 0.0f }, // target
63     { 0.0f,   0.0f, 1.0f }, // upVec
64        33.3f,               // fovy
65        16.0f,               // near plane Z in camera coordinates
66      1024.0f,               // far  plane Z in camera coordinates
67 };
68 
69 ViewPort myViewPort[] =
70 {
71     // quarter size (these are adjusted in main)
72     { 0,         0,         SCREEN_WD, SCREEN_HT },
73     { 0,         SCREEN_HT, SCREEN_WD, SCREEN_HT },
74     { SCREEN_WD, 0,         SCREEN_WD, SCREEN_HT },
75     { SCREEN_WD, SCREEN_HT, SCREEN_WD, SCREEN_HT },
76 };
77 
78 GXColor  myBgColor  = { 32, 32, 128,255};
79 
80 Scene    myScene[] =
81 {
82     { &myCamera, &myViewPort[0], GX_CULL_NONE,  SCENE_DRAWN },
83     { &myCamera, &myViewPort[1], GX_CULL_BACK,  SCENE_DRAWN },
84     { &myCamera, &myViewPort[2], GX_CULL_FRONT, SCENE_DRAWN },
85     { &myCamera, &myViewPort[3], GX_CULL_ALL,   SCENE_DRAWN },
86 };
87 
88 GlobalScene myGlobal =
89 {
90     0,
91     (sizeof(myScene)/sizeof(Scene)),
92     myScene,
93     SCREEN_WD,
94     SCREEN_HT,
95 };
96 
97 /*---------------------------------------------------------------------------*
98    Application main loop
99  *---------------------------------------------------------------------------*/
main(void)100 void    main ( void )
101 {
102     GXRenderModeObj *rmp;
103     int i;
104 
105     // initialize render settings and set clear color for first frame
106     DEMOInit(NULL);
107 
108     PrintIntro();
109 
110     // Perform dummy copy to clear EFB by specified color
111     GXSetCopyClear( myBgColor, GX_MAX_Z24 );
112     GXCopyDisp( DEMOGetCurrentBuffer(), GX_TRUE );
113 
114     rmp = DEMOGetRenderModeObj();
115     myGlobal.screen_wd = rmp->fbWidth;
116     myGlobal.screen_ht = rmp->efbHeight;
117 
118     for(i = 0; i < 4; i++)
119     {
120         myViewPort[i].xorg   *= myGlobal.screen_wd/2;
121         myViewPort[i].yorg   *= myGlobal.screen_ht/2;
122         myViewPort[i].width  *= myGlobal.screen_wd/2;
123         myViewPort[i].height *= myGlobal.screen_ht/2;
124     }
125 
126     while ( ! ( DEMOPadGetButton(0) & PAD_BUTTON_MENU ) )
127     {
128         // get pad status
129         DEMOPadRead( );
130 
131         // General control & model animation
132         SceneControl( &myGlobal );
133         // No animation for this model.
134 
135         // Draw scene
136         DEMOBeforeRender( );
137         GlobalSceneDraw( &myGlobal );
138         DEMODoneRender( );
139     }
140 
141     OSHalt("End of demo");
142 }
143 
144 /*---------------------------------------------------------------------------*
145    Functions
146  *---------------------------------------------------------------------------*/
147 
148 //============================================================================
149 //  Global Scene
150 //============================================================================
151 static void    myDrawTriangles     ( s32 );
152 static void    myDrawQuads         ( s32 );
153 static void    myDrawTriangleStrip ( s32 );
154 static void    myDrawTriangleFan   ( s32 );
155 
156 typedef struct
157 {
158     void    (*draw)();
159     char*   name;
160 }   MyModel;
161 
162 MyModel     myModel[] =
163 {
164  { myDrawTriangles,      "Triangles"      },
165  { myDrawTriangleStrip,  "Triangle Strip" },
166  { myDrawTriangleFan,    "Triangle Fan"   },
167  { myDrawQuads,          "Quads"          },
168 };
169 
170 #define NUMMODELS   (sizeof(myModel)/sizeof(MyModel))
171 
172 static
GlobalSceneDraw(GlobalScene * g)173 void    GlobalSceneDraw( GlobalScene* g )
174 {
175     u32     i;
176 
177     for ( i = 0; i < g->numScene; i ++ )
178     {
179     SceneDraw( g, &g->scene[i] );
180     }
181 
182     // Draw primitive name onto the window
183     GXSetViewport( 0, 0, (f32) g->screen_wd, (f32) g->screen_ht,
184                    SCREEN_ZNEAR, SCREEN_ZFAR );
185     GXSetScissor( 0, 0, g->screen_wd, g->screen_ht );
186     DEMOInitCaption( DM_FT_XLU, (s32) g->screen_wd, (s32) g->screen_ht );
187     DEMOPrintf( 10, 12, 0, myModel[g->modelId].name );
188 
189     return;
190 }
191 
192 //============================================================================
193 //  Scene
194 //============================================================================
195 typedef struct
196 {
197     GXCullMode  mode;
198     char*       name;
199 }   CullMode;
200 
201 CullMode    myCullMode[] =
202 {
203  { GX_CULL_NONE,    "CULL NONE"  },
204  { GX_CULL_FRONT,   "CULL FRONT" },
205  { GX_CULL_BACK,    "CULL BACK"  },
206  { GX_CULL_ALL,     "CULL ALL"   },
207 };
208 
209 #define NUMCULLMODES    (sizeof(myCullMode)/sizeof(CullMode))
210 
211 /*---------------------------------------------------------------------------*
212     Name:           SceneDraw
213     Description:    Draw model
214     Arguments:      Scene* s
215     Returns:        none
216  *---------------------------------------------------------------------------*/
217 static
SceneDraw(GlobalScene * g,Scene * s)218 void    SceneDraw( GlobalScene* g, Scene* s )
219 {
220     Camera* c = s->camera;
221     ViewPort*   v = s->viewport;
222     float       aspect = (float) (10.0 / 7.0);
223 
224     // Check if drawn flag
225     if ( !(s->flag & SCENE_DRAWN) ) return;
226 
227     // Set Perspective Viewing frustum
228     MTXPerspective( c->projMtx, c->fovy, aspect, c->znear, c->zfar );
229     GXSetProjection( c->projMtx, GX_PERSPECTIVE );
230 
231     // Set CameraView matrix
232     MTXLookAt( c->viewMtx, &c->position, &c->up, &c->target );
233 
234     // Set Viewport
235     GXSetViewport( v->xorg, v->yorg, v->width, v->height,
236                SCREEN_ZNEAR, SCREEN_ZFAR );
237     GXSetScissor( (u32)v->xorg, (u32)v->yorg, (u32)v->width, (u32)v->height );
238 
239     // Pixel processing mode
240     GXSetBlendMode( GX_BM_BLEND, GX_BL_ONE, GX_BL_ZERO, GX_LO_CLEAR );
241     GXSetZMode( GX_TRUE, GX_ALWAYS, GX_TRUE );
242 
243     // Culling mode
244     GXSetCullMode( s->cullmode );
245 
246     // Draw objects
247     myDrawModel( g, c );
248 
249     // draw information
250     SceneDrawInfo( s );
251     return;
252 }
253 
254 /*---------------------------------------------------------------------------*
255     Name:           SceneDrawInfo
256     Description:    Draw scene information
257     Arguments:
258     Returns:        none
259  *---------------------------------------------------------------------------*/
260 static
SceneDrawInfo(Scene * s)261 void    SceneDrawInfo( Scene* s )
262 {
263     ViewPort*   v = s->viewport;
264     u32     lid;
265     s16     sx, sy;
266 
267     // Draw parameters to the window
268     DEMOInitCaption( DM_FT_XLU, v->width, v->height );
269 
270     // Temporary cullmode for displaying captions
271     GXSetCullMode( GX_CULL_NONE );
272 
273     // get cullmode id
274     for ( lid = NUMCULLMODES-1; lid > 0; lid -- )
275     {
276         if ( s->cullmode == myCullMode[lid].mode ) break;
277     }
278     sx = (s16)( v->width / 2 - 36 );
279     sy = (s16)( v->height * 0.9 );
280     DEMOPrintf( sx, sy, 0, myCullMode[lid].name );
281 
282     return;
283 }
284 
285 /*---------------------------------------------------------------------------*
286     Name:           SceneControl
287     Description:    user interface for parameter control
288     Arguments:
289     Returns:        none
290  *---------------------------------------------------------------------------*/
291 static
SceneControl(GlobalScene * g)292 void    SceneControl( GlobalScene* g )
293 {
294     // Change model by Button A
295     if ( DEMOPadGetButtonDown(0) & PAD_BUTTON_A )
296     {
297         g->modelId = ( g->modelId + 1 ) % NUMMODELS;
298     }
299     return;
300 }
301 
302 //============================================================================
303 //  Model
304 //  Rectangles
305 //============================================================================
306 typedef struct
307 {
308     s16  x, z;
309     u8   r, g, b;
310 }   MyVtx;
311 
312 #define RSIZE    50
313 #define RPOSX    70
314 #define RPOSY   500 // direction for depth constant
315 #define RPOSZ     0
316 
317 static void    myDrawArrow( MyVtx *v, s32, s32 );
318 static void    mySendVtx( MyVtx*, s32, s32 );
319 
320 /*---------------------------------------------------------------------------*
321     Name:           myDrawModel
322     Description:    draw model
323     Arguments:      Camera *c
324     Returns:        none
325  *---------------------------------------------------------------------------*/
326 static
myDrawModel(GlobalScene * g,Camera * c)327 void    myDrawModel( GlobalScene* g, Camera *c )
328 {
329     // set modelview matrix
330     GXSetCurrentMtx( GX_PNMTX0 );
331     GXLoadPosMtxImm( c->viewMtx, GX_PNMTX0 );
332 
333     // use constant material color
334     GXSetNumChans( 1 );         // # of color channels
335     GXSetChanCtrl( GX_COLOR0,
336                GX_FALSE,        // enable Channel
337                GX_SRC_REG,      // amb source       (Don't care)
338                GX_SRC_VTX,      // mat source
339                GX_LIGHT0,       // light mask       (Don't care)
340                GX_DF_NONE,      // diffuse function (Don't care)
341                GX_AF_NONE );    // atten   function (Don't care)
342 
343     // Set material color to go through PE stage.
344     GXSetNumTexGens( 0 );       // # of Tex gen
345     GXSetNumTevStages( 1 );     // # of Tev Stage
346     GXSetTevOrder( GX_TEVSTAGE0,
347                    GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0 );
348     GXSetTevOp( GX_TEVSTAGE0, GX_PASSCLR );
349 
350     // Set vtx desc
351     GXClearVtxDesc( );
352     GXSetVtxDesc( GX_VA_POS,  GX_DIRECT );
353     GXSetVtxDesc( GX_VA_CLR0, GX_DIRECT );
354     GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_POS,  GX_POS_XYZ, GX_S16,  0 );
355     GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGB, GX_RGB8, 0 );
356 
357     // Draw primitives
358     myModel[g->modelId].draw(  1 );
359     myModel[g->modelId].draw( -1 );
360 
361     return;
362 }
363 
364 /*---------------------------------------------------------------------------*
365     Name:           myDrawTriangles
366     Description:    draw triangles
367     Arguments:      s32 xflip
368     Returns:        none
369  *---------------------------------------------------------------------------*/
370 static
371 MyVtx  myTri[] =
372 {
373     {  1,  2,  255,  0,  0 },
374     { -1,  2,    0,255,  0 },
375     {  1,  0,    0,  0,255 },
376     { -1,  0,  255,255,  0 },
377     { -1, -2,    0,255,255 },
378     {  1, -2,  255,  0,255 },
379 };
380 
381 static
myDrawTriangles(s32 xflip)382 void    myDrawTriangles( s32 xflip )
383 {
384     // Draw rectangle
385     GXBegin( GX_TRIANGLES, GX_VTXFMT0, 6 );
386         mySendVtx( myTri, 6, xflip );
387     GXEnd( );
388 
389     // Draw arrow
390     myDrawArrow( myTri+0, 3, xflip );
391     myDrawArrow( myTri+3, 3, xflip );
392 
393     return;
394 }
395 
396 /*---------------------------------------------------------------------------*
397     Name:           myDrawQuads
398     Description:    draw quad
399     Arguments:      s32 xflip
400     Returns:        none
401  *---------------------------------------------------------------------------*/
402 static
403 MyVtx  myQuad[] =
404 {
405     {  1,  2,  255,  0,  0 },
406     { -1,  2,    0,255,  0 },
407     { -1,  0,  255,  0,255 },
408     {  1,  0,    0,  0,255 },
409     {  0, -2,  255,255,  0 },
410     {  1, -1,    0,255,255 },
411     {  0,  0,  128,  0,255 },
412     { -1, -1,    0,128,255 },
413 };
414 
415 static
myDrawQuads(s32 xflip)416 void    myDrawQuads( s32 xflip )
417 {
418     // Draw rectangle
419     GXBegin( GX_QUADS, GX_VTXFMT0, 8 );
420         mySendVtx( myQuad, 8, xflip );
421     GXEnd( );
422 
423     // Draw arrow
424     myDrawArrow( myQuad+0, 4, xflip );
425     myDrawArrow( myQuad+4, 4, xflip );
426 
427     return;
428 }
429 
430 /*---------------------------------------------------------------------------*
431     Name:           myDrawTriangleStrip
432     Description:    draw triangle strip
433     Arguments:      s32 xflip
434     Returns:        none
435  *---------------------------------------------------------------------------*/
436 static
437 MyVtx  myTriStrip[] =
438 {
439     {  1,  2,  255,  0,  0 },
440     { -1,  2,    0,255,  0 },
441     {  1,  0,    0,  0,255 },
442     { -1,  0,  255,255,  0 },
443     { -1, -2,    0,255,255 },
444     {  1, -2,  255,  0,255 },
445 };
446 
447 static
myDrawTriangleStrip(s32 xflip)448 void    myDrawTriangleStrip( s32 xflip )
449 {
450     // Draw rectangle
451     GXBegin( GX_TRIANGLESTRIP, GX_VTXFMT0, 6 );
452     mySendVtx( myTriStrip, 6, xflip );
453     GXEnd( );
454 
455     // Draw arrow
456     myDrawArrow( myTriStrip, 6, xflip );
457 
458     return;
459 }
460 
461 /*---------------------------------------------------------------------------*
462     Name:           myDrawTriangleFan
463     Description:    draw triangle fan
464     Arguments:      s32 xflip
465     Returns:        none
466  *---------------------------------------------------------------------------*/
467 static
468 MyVtx  myTriFan[] =
469 {
470     {  1,  0,  255,  0,  0 },
471     {  1,  2,    0,255,  0 },
472     { -1,  2,    0,  0,255 },
473     { -1,  0,  255,255,  0 },
474     {  1, -2,    0,255,255 },
475     { -1, -2,  255,  0,255 },
476 };
477 
478 static
myDrawTriangleFan(s32 xflip)479 void    myDrawTriangleFan( s32 xflip )
480 {
481     // Draw rectangle
482     GXBegin( GX_TRIANGLEFAN, GX_VTXFMT0, 6 );
483     mySendVtx( myTriFan, 6, xflip );
484     GXEnd( );
485 
486     // Draw arrow
487     myDrawArrow( myTriFan, 6, xflip );
488 
489     return;
490 }
491 
492 /*---------------------------------------------------------------------------*
493     Name:           myDrawArrow
494     Description:    draw arrow
495     Arguments:      MyVtx *v, s32 nvtx, s32 xflip
496     Returns:        none
497  *---------------------------------------------------------------------------*/
498 #define ARROWSIZE   10
499 #define COS30       (1.7320508f/2.0f)
500 #define SIN30       (1.0000000f/2.0f)
501 
502 static
myDrawArrow(MyVtx * v,s32 nvtx,s32 xflip)503 void    myDrawArrow( MyVtx *v, s32 nvtx, s32 xflip )
504 {
505     u32     i;
506     s32     xs, zs, x0, z0, x1, z1;
507     f32     d, c, s;
508 
509     // Draw arrow
510     GXSetBlendMode( GX_BM_BLEND, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR );
511     GXBegin( GX_LINESTRIP, GX_VTXFMT0, (u8)(nvtx + 3) );
512     for ( i = 0; i < nvtx; i ++ )
513     {
514         xs = ( RPOSX + v[i].x * RSIZE ) * xflip;
515         zs =   RPOSZ + v[i].z * RSIZE;
516         GXPosition3s16( (s16)xs, RPOSY, (s16)zs );
517         GXColor3u8( 255, 255, 255 );
518     }
519     c = (float)( ( v[i-2].x - v[i-1].x ) * xflip );
520     s = (float)  ( v[i-2].z - v[i-1].z );
521     d = (float)ARROWSIZE / sqrtf( c * c + s * s );
522     c *= d;
523     s *= d;
524     x0 = (s32)(  c * COS30 - s * SIN30 + 0.5f );
525     z0 = (s32)(  c * SIN30 + s * COS30 + 0.5f );
526     x1 = (s32)(  c * COS30 + s * SIN30 + 0.5f );
527     z1 = (s32)(- c * SIN30 + s * COS30 + 0.5f );
528     GXPosition3s16( (s16)( xs + x0 ), RPOSY, (s16)( zs + z0 ) );
529     GXColor3u8( 255, 255, 255 );
530     GXPosition3s16( (s16)xs, RPOSY, (s16)zs );
531     GXColor3u8( 255, 255, 255 );
532     GXPosition3s16( (s16)( xs + x1 ), RPOSY, (s16)( zs + z1 ) );
533     GXColor3u8( 255, 255, 255 );
534     GXEnd( );
535     GXSetBlendMode( GX_BM_BLEND, GX_BL_ONE, GX_BL_ZERO, GX_LO_CLEAR );
536 
537     return;
538 }
539 
540 /*---------------------------------------------------------------------------*
541     Name:           mySendVtx
542     Description:    send vertex into pipeline
543     Arguments:      MyVtx* v, s32 nvtx, s32 xflip
544     Returns:        none
545  *---------------------------------------------------------------------------*/
546 static
mySendVtx(MyVtx * v,s32 nvtx,s32 xflip)547 void    mySendVtx( MyVtx* v, s32 nvtx, s32 xflip )
548 {
549     u32     i;
550     s32     xs, zs;
551 
552     for ( i = 0; i < nvtx; i ++ )
553     {
554     xs = ( RPOSX + v[i].x * RSIZE ) * xflip;
555     zs =   RPOSZ + v[i].z * RSIZE;
556     GXPosition3s16( (s16)xs, RPOSY, (s16)zs );
557     GXColor3u8( v[i].r, v[i].g, v[i].b );
558     }
559 
560     return;
561 }
562 
563 
564 /*---------------------------------------------------------------------------*
565     Name:           PrintIntro
566     Description:    Print directions on how to use this demo
567     Arguments:      none
568     Returns:        none
569  *---------------------------------------------------------------------------*/
PrintIntro(void)570 static void PrintIntro( void )
571 {
572     OSReport("\n\n");
573     OSReport("************************************************\n");
574     OSReport("cul-faces: show different culling modes\n");
575     OSReport("************************************************\n");
576     OSReport("to quit hit the start button\n");
577     OSReport("\n");
578     OSReport("Button A     : change model\n");
579 }
580 
581 /*======== End of cul-faces.c ========*/
582