1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin/Revolution gx demo
3   File:     tev-outline.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    tev-outline
15        Cartoon outline effects by using alpha plane copy and TEV features
16  *---------------------------------------------------------------------------*
17 
18    Overview of this method:
19 
20        (1st. pass) Render the entire scene as usual. At this time,
21        paint each object part by its individual ID number which is
22        drawn into alpha plane. It doesn't affect the result image
23        in color buffer.
24 
25        Then copy the entire alpha plane into a texture (ID map).
26        The framebuffer is not cleared by this operation.
27 
28        (2nd. pass) Render a screen-sized quad with ID map. Then,
29        generate two texcoords to lookup this map. One exactly
30        matches screen-space coordinate, and another is perturbed
31        by just one pixel width horizontally (or vertically).
32        Then compare texel values from these two texcoords each
33        other. The comparison can be done by some TEV stages and
34        alpha compare feature. If two ID values are not similar,
35        it means the part is a border of two different objects,
36        hence should be outlined.
37 
38        Since this demo sets the tolerance value of comparison
39        as more than 1, no outline will be generated between two
40        adjacent ID numbers. It will help outlining self-intersection
41        of soft objects.
42 
43        This demo draws horizontal/vertical outlines separately.
44 
45  *---------------------------------------------------------------------------*/
46 
47 /*---------------------------------------------------------------------------*
48    Header files
49  *---------------------------------------------------------------------------*/
50 #include <demo.h>
51 #include <math.h>
52 
53 /*---------------------------------------------------------------------------*
54    Macro definitions
55  *---------------------------------------------------------------------------*/
56 #define SCREEN_WD_MAX   640
57 #define SCREEN_HT_MAX   480
58 
59 #define VP_ASPECT   ((float)SCREEN_WD_MAX/(float)SCREEN_HT_MAX)
60 #define VP_FOVY       33.3f
61 #define VP_NEAR       16.0f     // near plane Z in view coordinates
62 #define VP_FAR      1024.0f     // far  plane Z in view coordinates
63 
64 #define SCREEN_ZNEAR    0.0f        // near plane Z in screen coordinates
65 #define SCREEN_ZFAR     1.0f        // far  plane Z in screen coordinates
66 #define ZBUFFER_MAX     0x00ffffff
67 
68 #define ASFT(x)         ((x)<<2)    // ID step size ( 6bit alpha )
69 
70 
71 #define Clamp(val,min,max) \
72     ((val) = (((val) < (min)) ? (min) : ((val) > (max)) ? (max) : (val)))
73 
74 /*---------------------------------------------------------------------------*
75    Forward references
76  *---------------------------------------------------------------------------*/
77 void  DrawInit ( void );
78 void  DrawScene( void );
79 void  myCreateModel( void );
80 void  myDrawModel( void );
81 void  myAnimeModel( void );
82 void  PrintIntro( void );
83 
84 void  DrawCartoonOutline( void );
85 
86 
87 /*---------------------------------------------------------------------------*
88    Global Variables
89  *---------------------------------------------------------------------------*/
90 u16 screen_wd;
91 u16 screen_ht;
92 
93 /*---------------------------------------------------------------------------*
94    Rendering parameters
95  *---------------------------------------------------------------------------*/
96 typedef struct
97 {
98     Point3d   position;
99     Point3d   target;
100     Vec       up;
101     f32       fovy;
102     f32       znear;
103     f32       zfar;
104     Mtx       viewMtx;
105 }   Camera;
106 
107 Camera  myCamera =
108 {
109     { 0.0f, -400.0f, 0.0f },   // position
110     { 0.0f,    0.0f, 0.0f },   // target
111     { 0.0f,    0.0f, 1.0f },   // upVec
112        33.3f,                  // fovy
113       128.0f,                  // near plane Z in camera coordinates
114      2048.0f,                  // far  plane Z in camera coordinates
115 };
116 
117 /*---------------------------------------------------------------------------*
118    Application main loop
119  *---------------------------------------------------------------------------*/
main(void)120 void  main ( void )
121 {
122     GXRenderModeObj *rmp;
123 
124     // initialize render settings and set clear color for first frame
125     DEMOInit( NULL );  // Defined in $(REVOLUTION_SDK_ROOT)/build/libraries/demo/src/DEMOInit.c
126 
127     rmp = DEMOGetRenderModeObj();
128     screen_wd = rmp->fbWidth;
129     screen_ht = rmp->efbHeight;
130 
131     PrintIntro( );  // Print demo directions
132 
133     DrawInit( );
134 
135     while ( ! ( DEMOPadGetButton(0) & PAD_BUTTON_MENU ) )
136     {
137         // get pad status
138         DEMOPadRead( );
139 
140         // General control & model animation
141         myAnimeModel( );
142 
143         // Draw scene
144         DEMOBeforeRender( );
145 
146         DrawScene( );
147         DrawCartoonOutline( );
148         DEMODoneRender( );
149     }
150 
151     OSHalt("End of demo");
152 }
153 
154 //---------------------------------------------------------------------------
155 // Cartoon outline settings
156 //---------------------------------------------------------------------------
157 
158 /*---------------------------------------------------------------------------*/
159 
160 /*---------------------------------------------------------------------------*
161    Draw Cartoon outline for real HW
162  *---------------------------------------------------------------------------*/
DrawCartoonOutline(void)163 void  DrawCartoonOutline( void )
164 {
165     static u16      *alphaBuffer;
166     static GXTexObj eFBTexObj;
167     static Mtx      texMtx1, texMtx2;
168     static Mtx      mtxUnit;
169     static Mtx44    mtxProj;
170     static s32      initialized = 0;
171     f32 zMid;
172 
173     if ( !initialized )
174     {
175         alphaBuffer = MEMAllocFromAllocator(&DemoAllocator1, screen_wd*screen_ht*sizeof(u16));
176         ASSERT( alphaBuffer != NULL );
177 
178         MTXIdentity(mtxUnit);
179         MTXOrtho(mtxProj, 0.0f, (f32) screen_ht, 0.0f, (f32) screen_wd, SCREEN_ZNEAR, SCREEN_ZFAR);
180 
181         // set up texture offset matrices
182         MTXIdentity(texMtx1);
183         MTXRowCol(texMtx1, 0, 3) = 1.0f / (f32)screen_wd;
184         MTXIdentity(texMtx2);
185         MTXRowCol(texMtx2, 1, 3) = 1.0f / (f32)screen_ht;
186 
187         GXInitTexObj( &eFBTexObj, alphaBuffer, screen_wd, screen_ht,
188                       GX_TF_I8, GX_CLAMP, GX_CLAMP, GX_DISABLE );
189         GXInitTexObjLOD( &eFBTexObj, GX_NEAR, GX_NEAR, 0.0f, 0.0f, 0.0f,
190                          GX_DISABLE, GX_DISABLE, GX_ANISO_1 );
191         initialized = 1;
192     }
193 
194     // Copy out eFB alpha plane as I8 texture format
195     GXSetTexCopySrc( 0, 0, screen_wd, screen_ht );
196     GXSetTexCopyDst(screen_wd, screen_ht, GX_TF_A8, GX_DISABLE );
197     GXCopyTex( alphaBuffer, GX_DISABLE );
198 
199     // Be sure texture is completely copied out
200     GXPixModeSync();
201 
202     // flush texture cache
203     GXInvalidateTexAll();
204 
205     // Load the bitmap into TMEM
206     GXLoadTexObj( &eFBTexObj, GX_TEXMAP0 );
207 
208     // Setup for outline drawing
209     GXSetNumTexGens  ( 2 );
210     GXSetNumChans    ( 0 );
211     GXSetNumTevStages( 2 );
212 
213     // first TEV stage just gets texture lookup value
214     GXSetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL );
215     GXSetTevOp( GX_TEVSTAGE0, GX_REPLACE );
216 
217     // second stage does the subtract (in alpha; colors gets zero)
218     // clamping turned off (in alpha) to allow wrapped "negative" values
219     GXSetTevOrder( GX_TEVSTAGE1, GX_TEXCOORD1, GX_TEXMAP0, GX_COLOR_NULL );
220     GXSetTevColorIn( GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_ZERO,
221                      GX_CC_ZERO, GX_CC_ZERO );
222     GXSetTevColorOp( GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1,
223                      GX_ENABLE, GX_TEVPREV );
224     GXSetTevAlphaIn( GX_TEVSTAGE1, GX_CA_TEXA, GX_CA_ZERO,
225                      GX_CA_ZERO, GX_CA_APREV );
226     GXSetTevAlphaOp( GX_TEVSTAGE1, GX_TEV_SUB, GX_TB_ZERO, GX_CS_SCALE_1,
227                      GX_DISABLE, GX_TEVPREV );
228 
229     // only write pixels that pass alpha test
230     GXSetAlphaCompare( GX_GREATER, ASFT(1), GX_AOP_AND, GX_LESS, 256-ASFT(1) );
231 
232     // always draw regardless of Z
233     GXSetZMode( GX_TRUE, GX_ALWAYS, GX_TRUE );
234 
235     // load matrices
236     GXSetCurrentMtx(GX_PNMTX0);
237     GXLoadPosMtxImm(mtxUnit, GX_PNMTX0);
238     GXSetProjection(mtxProj, GX_ORTHOGRAPHIC);
239 
240     GXLoadTexMtxImm(mtxUnit, GX_TEXMTX0, GX_MTX2x4);
241     GXLoadTexMtxImm(texMtx1, GX_TEXMTX1, GX_MTX2x4);
242     GXLoadTexMtxImm(texMtx2, GX_TEXMTX2, GX_MTX2x4);
243 
244     // vertex descriptor settings
245     GXClearVtxDesc( );
246     GXSetVtxDesc( GX_VA_POS, GX_DIRECT );
247     GXSetVtxDesc( GX_VA_TEX0, GX_DIRECT );
248     GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );
249     GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 );
250 
251     zMid = -0.5f * (SCREEN_ZNEAR + SCREEN_ZFAR);
252 
253     GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX0);
254     GXSetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX1);
255 
256     // draw with texture offset in S
257     GXBegin(GX_QUADS, GX_VTXFMT0, 4);
258         GXPosition3f32(0.0F, 0.0F, zMid);
259         GXTexCoord2f32(0.0F, 0.0F);
260         GXPosition3f32((f32) screen_wd, 0.0F, zMid);
261         GXTexCoord2f32(1.0F, 0.0F);
262         GXPosition3f32((f32) screen_wd, (f32) screen_ht, zMid);
263         GXTexCoord2f32(1.0F, 1.0F);
264         GXPosition3f32(0.0F, (f32) screen_ht, zMid);
265         GXTexCoord2f32(0.0F, 1.0F);
266     GXEnd();
267 
268     GXSetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX2);
269 
270     // draw with texture offset in T
271     GXBegin(GX_QUADS, GX_VTXFMT0, 4);
272         GXPosition3f32(0.0F, 0.0F, zMid);
273         GXTexCoord2f32(0.0F, 0.0F);
274         GXPosition3f32((f32) screen_wd, 0.0F, zMid);
275         GXTexCoord2f32(1.0F, 0.0F);
276         GXPosition3f32((f32) screen_wd, (f32) screen_ht, zMid);
277         GXTexCoord2f32(1.0F, 1.0F);
278         GXPosition3f32(0.0F, (f32) screen_ht, zMid);
279         GXTexCoord2f32(0.0F, 1.0F);
280     GXEnd();
281 
282     return;
283 }
284 
285 //---------------------------------------------------------------------------
286 //  Model settings
287 //---------------------------------------------------------------------------
288 #define MYDLBUFSIZE      1024
289 
290 #define VTXINRING        12
291 #define NUMRINGS         6
292 
293 #define PIPELID0_NRM     12
294 #define PIPELID1_NRM     13
295 #define PIPELID0_CLR     (NUMRINGS-1)
296 #define PIPELID1_CLR     (NUMRINGS)
297 
298 typedef  struct {
299    s8  x,  y;
300    s8  nx, ny, nz, pad;
301 }  MyVertex;
302 
303 static MyVertex ringVtx[] ATTRIBUTE_ALIGN(32) =
304 {
305     //  x,   y,    nx,  ny,  nz,  pad
306     { 100,   0,    64,   0,   0,    0 }, /*   0 */
307     {  87,  50,    55,  32,   0,    0 }, /*  30 */
308     {  50,  87,    32,  55,   0,    0 }, /*  60 */
309     {   0, 100,     0,  60,   0,    0 }, /*  90 */
310     { -50,  87,   -32,  55,   0,    0 }, /* 120 */
311     { -87,  50,   -55,  32,   0,    0 }, /* 150 */
312     {-100,   0,   -64,   0,   0,    0 }, /* 180 */
313     { -87, -50,   -55, -32,   0,    0 }, /* 210 */
314     { -50, -87,   -32, -55,   0,    0 }, /* 240 */
315     {   0,-100,     0, -64,   0,    0 }, /* 270 */
316     {  50, -87,    32, -55,   0,    0 }, /* 300 */
317     {  87, -50,    55, -32,   0,    0 }, /* 330 */
318 
319     {   0,   0,     0,   0, -60,    0 }, /* center of lid */
320     {   0,   0,     0,   0,  60,    0 }, /* center of lid */
321 };
322 
323 static GXColor pipeClr[] ATTRIBUTE_ALIGN(32) =
324 {
325     //  R,   G,   B,   A(ID)
326     {  64, 128, 255, ASFT(4) }, // for pipe
327     {  64, 128, 255, ASFT(5) },
328     {  64, 128, 255, ASFT(5) },
329     {  64, 128, 255, ASFT(5) },
330     {  64, 128, 255, ASFT(6) },
331     {  64, 128, 255, ASFT(2) }, // for lid0
332     {  64, 128, 255, ASFT(8) }, // for lid1
333 };
334 
335 struct {
336    f32  rot;
337    f32  length;
338 }
339 pipe[NUMRINGS-1] =
340 {
341     {  0.0f, 400.0f },
342     { 20.0f,  50.0f },
343     { 20.0f,  50.0f },
344     { 20.0f,  50.0f },
345     {  0.0f, 400.0f },
346 };
347 
348 Mtx pipeLocalMtx =
349 { { 0.0646906f, 0.0760343f, 0.0058220f, 0.0f },
350   {-0.0740718f, 0.0608390f, 0.0284950f, 0.0f },
351   { 0.0181239f,-0.0227461f, 0.0956772f, 0.0f } };
352 
353 Mtx pipeMtx[NUMRINGS] ATTRIBUTE_ALIGN(32);
354 
355 // display list
356 u8*             myDisplayList = NULL;
357 u32             myDLSize;
358 GXVtxDescList   myDLVcd[GX_MAX_VTXDESCLIST_SZ];
359 
360 //---------------------------------------------------------------------------
361 //  Init scene
362 //---------------------------------------------------------------------------
DrawInit(void)363 void    DrawInit( void )
364 {
365     GXColor color = {160,160,160,0};
366     // need an alpha channel
367     GXSetPixelFmt(GX_PF_RGBA6_Z24, GX_ZC_LINEAR);
368     GXSetCopyClear( color , GX_MAX_Z24 );
369     // clear framebuffer because eFB format is changed
370     GXCopyDisp(DEMOGetCurrentBuffer(), GX_TRUE);
371 
372     // We're using alpha compare, so we must compare z AFTER texturing
373     GXSetZCompLoc( GX_DISABLE );
374 
375     // update both color and alpha
376     GXSetAlphaUpdate(GX_TRUE);
377     GXSetColorUpdate(GX_TRUE);
378 
379     // create the model data
380     myCreateModel();
381 }
382 
383 //---------------------------------------------------------------------------
384 //  Draw entire scene
385 //---------------------------------------------------------------------------
DrawScene(void)386 void    DrawScene( void )
387 {
388     Mtx44    projMtx;
389     Camera*  c = &myCamera;
390 
391     // Set projection matrix
392     MTXPerspective( projMtx, c->fovy, VP_ASPECT, c->znear, c->zfar );
393     GXSetProjection( projMtx, GX_PERSPECTIVE );
394 
395     // Set Viewport
396     GXSetViewport( 0, 0, screen_wd, screen_ht, SCREEN_ZNEAR, SCREEN_ZFAR );
397     GXSetScissor ( 0, 0, screen_wd, screen_ht );
398 
399     // Set rendering mode
400     GXSetBlendMode( GX_BM_BLEND, GX_BL_ONE, GX_BL_ZERO, GX_LO_CLEAR );
401     GXSetZMode( GX_TRUE, GX_LESS, GX_TRUE );
402 
403     // Set rendering mode
404     GXSetCullMode( GX_CULL_BACK );
405 
406     // Draw objects
407     myDrawModel( );
408 
409     return;
410 }
411 
412 //---------------------------------------------------------------------------
413 //  Animate model
414 //---------------------------------------------------------------------------
415 #  define MOVE_SCALE    1.0f
416 
myAnimeModel(void)417 void  myAnimeModel( void )
418 {
419     static f32  angle = 60.0f;
420     Camera*     c = &myCamera;
421     Mtx         localMtx, tmpMtx;
422     Vec         axis;
423     s32         i;
424     u16         stickDirs;
425 
426     axis.x = axis.y = axis.z = 0.0f;
427 
428     stickDirs = DEMOPadGetDirs(0);
429 
430     // Model rotation
431     stickDirs = DEMOPadGetDirs(0);
432     if ( stickDirs & DEMO_STICK_UP    )
433         axis.x -= 1.0f;
434     if ( stickDirs & DEMO_STICK_DOWN  )
435         axis.x += 1.0f;
436     if ( stickDirs & DEMO_STICK_LEFT  )
437         axis.y -= 1.0f;
438     if ( stickDirs & DEMO_STICK_RIGHT )
439         axis.y += 1.0f;
440     if ( stickDirs & DEMO_SUBSTICK_LEFT  )
441         axis.z -= 1.0f;
442     if ( stickDirs & DEMO_SUBSTICK_RIGHT )
443         axis.z += 1.0f;
444 
445     // Camera zoom
446     c->position.y += (f32)DEMOPadGetSubStickY(0) / 30.0f * MOVE_SCALE;
447     Clamp(c->position.y, -600.0f, -200.0f);
448 
449     // Joint angle
450     if ( DEMOPadGetButton(0) & PAD_TRIGGER_L )
451         angle += MOVE_SCALE * 3.0f;
452     if ( DEMOPadGetButton(0) & PAD_TRIGGER_R )
453         angle -= MOVE_SCALE * 3.0f;
454     Clamp(angle, 0.0f, 150.0f);
455 
456 
457     //--------- Get View matrix
458     MTXLookAt( c->viewMtx, &c->position, &c->up, &c->target );
459 
460     //--------- Make local matrix
461     MTXInverse( c->viewMtx, tmpMtx );
462     MTXMultVecSR( tmpMtx, &axis, &axis );
463     if ( axis.x != 0.0f || axis.y != 0.0f || axis.z != 0.0f )
464     {
465         MTXRotAxisDeg( tmpMtx, &axis, MOVE_SCALE );
466         MTXConcat( tmpMtx, pipeLocalMtx, pipeLocalMtx );
467     }
468 
469     //--------- Set pipe bend parameter
470     for ( i = 1; i < NUMRINGS-2; i ++ )
471     {
472         pipe[i].rot = angle / ((NUMRINGS-3) * 2);
473     }
474 
475     //--------- Make ModelView matrix
476     MTXConcat( c->viewMtx, pipeLocalMtx, pipeMtx[0] );
477     for ( i = 0; i < NUMRINGS-1; i ++ )
478     {
479         MTXTrans( localMtx, 0, 0, pipe[i].length );
480         MTXRotDeg( tmpMtx, 'Y', pipe[i].rot );
481         MTXConcat( tmpMtx,   localMtx, localMtx );
482         MTXConcat( localMtx, tmpMtx,   localMtx );
483         MTXConcat( pipeMtx[i], localMtx, pipeMtx[i+1] );
484     }
485     DCFlushRange( pipeMtx, sizeof(pipeMtx) );
486 }
487 
488 //---------------------------------------------------------------------------
489 //  Create a model as display list
490 //---------------------------------------------------------------------------
myCreateModel(void)491 void  myCreateModel( void )
492 {
493     s32     i, j, k;
494     u8      m0 = 0; // GX_PNMTX0;
495     u8      m1;
496 
497     //--------- allocate buffer for the display list
498     if ( myDisplayList == NULL )
499     {
500         myDisplayList = MEMAllocFromAllocator(&DemoAllocator1, MYDLBUFSIZE);
501         DCInvalidateRange( myDisplayList, MYDLBUFSIZE);
502     }
503 
504     //-------- Vertex attribute settings
505     GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_POS,  GX_POS_XY,   GX_S8, 0 );
506     GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_NRM,  GX_NRM_XYZ,  GX_S8, 6 );
507     GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );
508 
509     //-------- Vertex descriptor settings
510     GXClearVtxDesc( );
511     GXSetVtxDesc( GX_VA_PNMTXIDX, GX_DIRECT );
512     GXSetVtxDesc( GX_VA_POS, GX_INDEX8 );
513     GXSetVtxDesc( GX_VA_NRM, GX_INDEX8 );
514     GXSetVtxDesc( GX_VA_CLR0, GX_INDEX8 );
515 
516     GXGetVtxDescv(myDLVcd); // save vertex descriptor state
517 
518     //-------- start generating display list
519     GXBeginDisplayList( myDisplayList, MYDLBUFSIZE );
520 
521 
522     //-------- Pipe lid 0  (Triangle fan)
523     GXBegin( GX_TRIANGLEFAN, GX_VTXFMT0, VTXINRING );
524     for ( i = 0; i < VTXINRING; i ++ )
525     {
526         GXMatrixIndex1x8( m0 );
527         GXPosition1x8   ( (u8)i );
528         GXNormal1x8     ( (u8)PIPELID0_NRM );
529         GXColor1x8      ( (u8)PIPELID0_CLR );
530     }
531     GXEnd( );
532 
533 
534     //-------- Pipe body (Triangle strip)
535     for ( j = 0; j < NUMRINGS-1; j ++ )
536     {
537         m0 = (u8)(j * 3);   // GX_PNMTX0(=0), GX_PNMTX1(=3), ...
538         m1 = (u8)((j+1)*3); // GX_PNMTX1(=3), GX_PNMTX2(=6), ...
539 
540         GXBegin( GX_TRIANGLESTRIP, GX_VTXFMT0, (VTXINRING+1)*2 );
541         k = VTXINRING-1;
542         for ( i = -1; i < VTXINRING; i ++, k = i )
543         {
544             GXMatrixIndex1x8( m0 );
545             GXPosition1x8   ( (u8)k );
546             GXNormal1x8     ( (u8)k );
547             GXColor1x8      ( (u8)j );
548             GXMatrixIndex1x8( m1 );
549             GXPosition1x8   ( (u8)k );
550             GXNormal1x8     ( (u8)k );
551             GXColor1x8      ( (u8)j );
552         }
553         GXEnd( );
554 
555     }
556 
557     //-------- Pipe lid 1  (Triangle fan)
558     GXBegin( GX_TRIANGLEFAN, GX_VTXFMT0, VTXINRING );
559     for ( i = 0; i < VTXINRING; i ++ )
560     {
561         GXMatrixIndex1x8( m1 );
562         GXPosition1x8   ( (u8)(VTXINRING-1-i) );
563         GXNormal1x8     ( (u8)PIPELID1_NRM );
564         GXColor1x8      ( (u8)PIPELID1_CLR );
565     }
566     GXEnd( );
567 
568     //-------- end of the display list
569     myDLSize = GXEndDisplayList();
570 
571 }
572 
573 //---------------------------------------------------------------------------
574 //  Draw model
575 //---------------------------------------------------------------------------
myDrawModel(void)576 void  myDrawModel( void )
577 {
578     s32         i;
579     u32         m0;
580     GXColor     matColor = { 0, 0, 0, 0 };
581     GXLightObj  light;
582     GXColor     color0 = { 160, 160, 160, 0 };
583     GXColor     color1 = { 96, 96, 96, 0 };
584 
585     //--------- Set rendering parameters
586     GXSetChanCtrl( GX_COLOR0,   GX_ENABLE,
587                    GX_SRC_REG,  GX_SRC_VTX, GX_LIGHT0,
588                    GX_DF_CLAMP, GX_AF_NONE  );
589 
590     GXSetChanCtrl( GX_ALPHA0,   GX_DISABLE,
591                    GX_SRC_REG,  GX_SRC_VTX, GX_LIGHT_NULL,
592                    GX_DF_CLAMP, GX_AF_NONE  );
593 
594     GXSetChanAmbColor( GX_COLOR0A0, color0 );
595 
596     GXInitLightPos(&light, 1000.0f, 0.0f, 0.0f);
597     GXInitLightColor(&light, color1 );
598     GXLoadLightObjImm(&light, GX_LIGHT0);
599 
600     GXSetNumTexGens  ( 0 );             // # of Texgen proc
601     GXSetNumChans    ( 1 );             // # of Color Channel
602     GXSetNumTevStages( 1 );             // # of Tev Stage
603 
604     GXSetTevOrder( GX_TEVSTAGE0,
605                    GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0 );
606     GXSetTevOp( GX_TEVSTAGE0, GX_PASSCLR );
607 
608     GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0);
609 
610     //-------- Array base & stride setting
611     GXSetArray( GX_VA_POS,        &ringVtx[0].x,  sizeof( ringVtx[0] ) );
612     GXSetArray( GX_VA_NRM,        &ringVtx[0].nx, sizeof( ringVtx[0] ) );
613     GXSetArray( GX_VA_CLR0,       &pipeClr[0],    sizeof( pipeClr[0] ) );
614     GXSetArray( GX_POS_MTX_ARRAY, &pipeMtx[0],    sizeof( pipeMtx[0] ) );
615 
616     //-------- Vertex attribute settings
617     GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_POS, GX_POS_XY,  GX_S8, 0 );
618     GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_S8, 6 );
619     GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );
620 
621     //-------- Vertex descriptor settings
622     GXSetVtxDescv(myDLVcd);
623 
624     //-------- Set transform matrices
625     for ( i = 0 ; i < NUMRINGS ; ++i )
626     {
627         m0 = (u32)(i * 3); // GX_PNMTX0(=0), GX_PNMTX1(=3), ...
628         GXLoadPosMtxIndx( (u16)i, m0 );
629         GXLoadNrmMtxImm( pipeMtx[i], m0 );
630     }
631 
632     //-------- Draw the model
633     GXCallDisplayList( myDisplayList, myDLSize );
634 
635     return;
636 }
637 
638 //---------------------------------------------------------------------------
639 //    Prints the directions on how to use this demo
640 //---------------------------------------------------------------------------
PrintIntro(void)641 void PrintIntro( void )
642 {
643     OSReport("\n\n");
644     OSReport("**********************************************\n");
645     OSReport("tev-outline: cartoon-outline demo\n");
646     OSReport("**********************************************\n");
647     OSReport("to quit hit the start button\n");
648     OSReport("\n");
649     OSReport("Main stick   : Rotate the model\n");
650     OSReport("Sub  stick   : Control zoom\n");
651     OSReport("L/R triggers : Bend/Stretch the model\n");
652     OSReport("**********************************************\n");
653     OSReport("\n\n");
654 }
655 
656 /*======== End of tev-outline.c ========*/
657