1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin/Revolution gx demo
3   File:     lit-cartoon.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    lit-cartoon
15      Unclamped diffuse function with texture coord generation
16      (Cartoon rendering)
17  *---------------------------------------------------------------------------*/
18 
19 
20 /*---------------------------------------------------------------------------*
21    Header files
22  *---------------------------------------------------------------------------*/
23 #include <demo.h>
24 #include <math.h>
25 
26 /*---------------------------------------------------------------------------*
27    Macro definitions
28  *---------------------------------------------------------------------------*/
29 #define PI    3.14159265358979323846F
30 
31 #define Clamp(val,min,max) \
32     ((val) = (((val) < (min)) ? (min) : ((val) > (max)) ? (max) : (val)))
33 
34 /*---------------------------------------------------------------------------*
35    Structure definitions
36  *---------------------------------------------------------------------------*/
37 // for camera
38 typedef struct
39 {
40     Vec    location;
41     Vec    up;
42     Vec    target;
43     f32    left;
44     f32    top;
45     f32    znear;
46     f32    zfar;
47 } CameraConfig;
48 
49 typedef struct
50 {
51     CameraConfig  cfg;
52     Mtx           view;
53     Mtx44         proj;
54 } MyCameraObj;
55 
56 // for lighting
57 typedef struct
58 {
59     GXLightObj  lobj;
60     s32         theta;
61     s32         phi;
62     f32         brightCtrl[3];
63     u32         cartoonType;
64 } MyLightEnvObj;
65 
66 // for entire scene control
67 typedef struct
68 {
69     MyCameraObj    cam;
70     MyLightEnvObj  lightEnv;
71     Mtx            modelCtrl;
72     u32            modelType;
73     GXTexObj       texture;
74     GXTevMode      tevMode;
75 } MySceneCtrlObj;
76 
77 /*---------------------------------------------------------------------------*
78    Forward references
79  *---------------------------------------------------------------------------*/
80 void        main            ( void );
81 static void DrawInit        ( MySceneCtrlObj* sc );
82 static void DrawTick        ( MySceneCtrlObj* sc );
83 static void AnimTick        ( MySceneCtrlObj* sc );
84 static void DrawModel       ( u32 model );
85 static void DrawLightMark   ( void );
86 static void SetCamera       ( MyCameraObj* cam );
87 static void SetLight        ( MyLightEnvObj* le, Mtx view );
88 static void DisableLight    ( void );
89 static void PrintIntro      ( void );
90 
91 /*---------------------------------------------------------------------------*
92    Model data and strings for message
93  *---------------------------------------------------------------------------*/
94 #define TORUS       0
95 #define SPHERE      1
96 #define CUBE        2
97 #define ICOSA       3
98 
99 #define MODELS      4
100 
101 static char* ParamTitle[] =
102 {
103     "Ambient",
104     "Material",
105     "Light"
106 };
107 
108 /*---------------------------------------------------------------------------*
109    Camera configuration
110  *---------------------------------------------------------------------------*/
111 static CameraConfig DefaultCamera =
112 {
113     { 0.0F, 0.0F, 900.0F }, // location
114     { 0.0F, 1.0F,   0.0F }, // up
115     { 0.0F, 0.0F,   0.0F }, // target
116     -320.0F, // left
117     240.0F,  // top
118     400.0F,  // near
119     2000.0F  // far
120 };
121 
122 /*---------------------------------------------------------------------------*
123    Global variables
124  *---------------------------------------------------------------------------*/
125 static MySceneCtrlObj  SceneCtrl;       // scene control parameters
126 static TPLPalettePtr   MyTplObj = 0;    // texture palette file
127 static GXTexCoordID    CoordCtrl = GX_TEXCOORD0; // select one of 7 tex coords
128 
129 /*---------------------------------------------------------------------------*
130    Application main loop
131  *---------------------------------------------------------------------------*/
main(void)132 void main ( void )
133 {
134     DEMOInit(NULL);    // Init the OS, game pad, graphics and video.
135 
136     DrawInit(&SceneCtrl);       // Initialize vertex formats and scene parameters.
137 
138     PrintIntro();  // Print demo directions
139 
140     while(!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
141     {
142         DEMOBeforeRender();
143         DrawTick(&SceneCtrl);    // Draw the model.
144         DEMODoneRender();
145         DEMOPadRead();           // Update pad status.
146         AnimTick(&SceneCtrl);    // Update animation.
147     }
148 
149     OSHalt("End of demo");
150 }
151 
152 /*---------------------------------------------------------------------------*
153    Functions
154  *---------------------------------------------------------------------------*/
155 /*---------------------------------------------------------------------------*
156     Name:           DrawInit
157 
158     Description:    Initializes the vertex attribute format, texture and
159                     default scene parameters.
160 
161     Arguments:      sc : pointer to the structure of scene control parameters
162 
163     Returns:        none
164  *---------------------------------------------------------------------------*/
DrawInit(MySceneCtrlObj * sc)165 static void DrawInit( MySceneCtrlObj* sc )
166 {
167     TPLDescriptorPtr tdp;
168 
169     // set up a vertex attribute
170     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
171     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
172     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
173 
174     // texture from Tpl file
175     TPLGetPalette(&MyTplObj, "gxTests/lit-06.tpl");
176     tdp = TPLGet(MyTplObj, 0);
177     GXInitTexObj(
178         &sc->texture,
179         tdp->textureHeader->data,
180         tdp->textureHeader->width,
181         tdp->textureHeader->height,
182         (GXTexFmt)tdp->textureHeader->format,
183         GX_CLAMP,   // s
184         GX_CLAMP,   // t
185         GX_FALSE ); // Mipmap
186     GXInitTexObjLOD(
187         &sc->texture,
188         tdp->textureHeader->minFilter,
189         tdp->textureHeader->magFilter,
190         tdp->textureHeader->minLOD,
191         tdp->textureHeader->maxLOD,
192         tdp->textureHeader->LODBias,
193         GX_FALSE,
194         tdp->textureHeader->edgeLODEnable,
195         GX_ANISO_1);
196     GXInvalidateTexAll();
197 
198 
199     // Default scene parameter settings
200 
201     // camera
202     sc->cam.cfg = DefaultCamera;
203     SetCamera(&sc->cam);   // never changes in this test
204 
205     // light parameters
206     sc->lightEnv.theta  = 0;
207     sc->lightEnv.phi    = 0;
208 
209     // brightness of Ambient/Material/Light
210     sc->lightEnv.brightCtrl[0] = 0.5F;
211     sc->lightEnv.brightCtrl[1] = 1.0F;
212     sc->lightEnv.brightCtrl[2] = 0.5F;
213 
214     // type of cartoon lighting (1D texture lookup index)
215     sc->lightEnv.cartoonType = 0;
216 
217     // model control matrix
218     MTXScale(sc->modelCtrl, 250.0F, 250.0F, 250.0F);
219     sc->modelType = 0;
220 
221     // tev mode
222     sc->tevMode = GX_REPLACE;
223 }
224 
225 /*---------------------------------------------------------------------------*
226     Name:           DrawTick
227 
228     Description:    Draws the model by using given scene parameters
229 
230     Arguments:      sc : pointer to the structure of scene control parameters
231 
232     Returns:        none
233  *---------------------------------------------------------------------------*/
DrawTick(MySceneCtrlObj * sc)234 static void DrawTick( MySceneCtrlObj* sc )
235 {
236     Mtx  mv;  // Modelview matrix.
237     Mtx  mr;  // Rotate matrix.
238     Mtx  mvi; // Modelview matrix.
239     u32  i;
240 
241     // enable lighting
242     SetLight(&sc->lightEnv, sc->cam.view);
243 
244     // set texture
245     GXLoadTexObj(&sc->texture, GX_TEXMAP0);
246 
247     // texture coord generation mode for cartoon lighting
248     for (i = 0; i < CoordCtrl; i++)
249         GXSetTexCoordGen((GXTexCoordID)i, GX_TG_MTX2x4, GX_TG_POS, GX_IDENTITY);
250 
251     GXSetTexCoordGen(CoordCtrl, GX_TG_SRTG, GX_TG_COLOR0, GX_IDENTITY);
252 
253     // set Tev mode = one color / one texture
254     GXSetTevOp(GX_TEVSTAGE0, sc->tevMode);
255     GXSetTevOrder(GX_TEVSTAGE0, CoordCtrl, GX_TEXMAP0, GX_COLOR0A0);
256     GXSetNumTexGens((u8)(CoordCtrl+1));
257 
258     // draw a model
259     MTXConcat(sc->cam.view, sc->modelCtrl, mv);
260     GXLoadPosMtxImm(mv, GX_PNMTX0);
261     MTXInverse(mv, mvi);
262     MTXTranspose(mvi, mv);
263     GXLoadNrmMtxImm(mv, GX_PNMTX0);
264     DrawModel(sc->modelType);
265 
266 
267     // disable lights
268     DisableLight();
269 
270     // set Tev mode = one color / no texture
271     GXSetNumTexGens(0);
272     GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
273     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
274 
275     // draw a light mark
276     MTXRotDeg(mr, 'y', sc->lightEnv.theta);
277     MTXConcat(sc->cam.view, mr, mv);
278     MTXRotDeg(mr, 'x', - sc->lightEnv.phi);
279     MTXConcat(mv, mr, mv);
280     GXLoadPosMtxImm(mv, GX_PNMTX0);
281     DrawLightMark();
282 }
283 
284 /*---------------------------------------------------------------------------*
285     Name:           AnimTick
286 
287     Description:    Changes scene parameters according to the pad status.
288 
289     Arguments:      sc : pointer to the structure of scene control parameters
290 
291     Returns:        none
292  *---------------------------------------------------------------------------*/
AnimTick(MySceneCtrlObj * sc)293 static void AnimTick( MySceneCtrlObj* sc )
294 {
295     static u32  cursor = 0;
296     u16  down;
297     Mtx  mrx, mry;
298     u32  pr = 0;
299 
300     // PAD
301     down = DEMOPadGetButtonDown(0);
302 
303     // Light Position Calculation
304     sc->lightEnv.theta += (DEMOPadGetStickX(0) / 32);
305     sc->lightEnv.theta %= 360;
306     sc->lightEnv.phi += (DEMOPadGetStickY(0) / 32);
307     Clamp(sc->lightEnv.phi, -90, 90);
308 
309 
310     // Model Rotation Calculation
311     MTXRotDeg(mry, 'x', -(DEMOPadGetSubStickY(0) / 32));
312     MTXRotDeg(mrx, 'y', (DEMOPadGetSubStickX(0) / 32));
313     MTXConcat(mry, sc->modelCtrl, sc->modelCtrl);
314     MTXConcat(mrx, sc->modelCtrl, sc->modelCtrl);
315 
316 
317     // Select Ambient/Material/Light
318     if ( down & PAD_BUTTON_Y )
319     {
320         cursor = ( cursor + 1 ) % 3;
321         pr = 1;
322     }
323     if ( down & PAD_BUTTON_X )
324     {
325         CoordCtrl = (GXTexCoordID) (CoordCtrl + 1);
326         if (CoordCtrl == GX_MAX_TEXCOORD)
327             CoordCtrl = GX_TEXCOORD0;
328         OSReport("Tex Coord %d being tested\n", CoordCtrl);
329     }
330     // Ambient/Material/Light brightness tuning
331     if ( down & PAD_TRIGGER_L )
332     {
333         sc->lightEnv.brightCtrl[cursor] -= 0.05F;
334         if ( sc->lightEnv.brightCtrl[cursor] < 0.0F )
335         {
336             sc->lightEnv.brightCtrl[cursor] = 0.0F;
337         }
338         pr = 1;
339     }
340     if ( down & PAD_TRIGGER_R )
341     {
342         sc->lightEnv.brightCtrl[cursor] += 0.05F;
343         if ( sc->lightEnv.brightCtrl[cursor] > 1.0F )
344         {
345             sc->lightEnv.brightCtrl[cursor] = 1.0F;
346         }
347         pr = 1;
348     }
349 
350     // print selected/changed parameter
351     if ( pr )
352     {
353         OSReport(
354             "%s = %f\n",
355             ParamTitle[cursor],
356             sc->lightEnv.brightCtrl[cursor] );
357     }
358 
359     // change cartoon texture type
360     if ( down & PAD_BUTTON_B )
361     {
362         sc->lightEnv.cartoonType = ( sc->lightEnv.cartoonType + 1 ) % 8;
363     }
364 
365     // model select
366     if ( down & PAD_BUTTON_A )
367     {
368         sc->modelType = ( sc->modelType + 1 ) % MODELS;
369     }
370 
371 }
372 
373 /*---------------------------------------------------------------------------*
374     Name:           DrawModel
375 
376     Description:    Draws specified model
377 
378     Arguments:      model : specifies which model is to be displayed
379 
380     Returns:        none
381  *---------------------------------------------------------------------------*/
DrawModel(u32 model)382 static void DrawModel( u32 model )
383 {
384     // sets up vertex descriptors
385     GXClearVtxDesc();
386     GXSetVtxDesc(GX_VA_POS,  GX_DIRECT);
387     GXSetVtxDesc(GX_VA_NRM,  GX_DIRECT);
388 
389     // draws a GXDraw model
390     switch(model)
391     {
392         case TORUS :
393             GXDrawTorus(0.25F, 16, 24);
394             break;
395         case SPHERE :
396             GXDrawSphere(16, 24);
397             break;
398         case CUBE :
399             GXDrawCube();
400             break;
401         case ICOSA :
402             GXDrawIcosahedron();
403             break;
404     }
405 }
406 
407 /*---------------------------------------------------------------------------*
408     Name:           DrawLightMark
409 
410     Description:    Draws a mark which shows position of the light.
411 
412     Arguments:      none
413 
414     Returns:        none
415  *---------------------------------------------------------------------------*/
DrawLightMark(void)416 static void DrawLightMark( void )
417 {
418     // sets up vertex descriptors
419     GXClearVtxDesc();
420     GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
421     GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
422 
423     GXBegin(GX_LINES, GX_VTXFMT0, 8);
424         GXPosition3f32(500.0F, 500.0F, -500.0F);
425         GXColor4u8(0, 255, 255, 255);
426         GXPosition3f32(0.0F, 0.0F, 500.0F);
427         GXColor4u8(0, 255, 255, 255);
428 
429         GXPosition3f32(500.0F, -500.0F, -500.0F);
430         GXColor4u8(0, 255, 255, 255);
431         GXPosition3f32(0.0F, 0.0F, 500.0F);
432         GXColor4u8(0, 255, 255, 255);
433 
434         GXPosition3f32(-500.0F, 500.0F, -500.0F);
435         GXColor4u8(0, 255, 255, 255);
436         GXPosition3f32(0.0F, 0.0F, 500.0F);
437         GXColor4u8(0, 255, 255, 255);
438 
439         GXPosition3f32(-500.0F, -500.0F, -500.0F);
440         GXColor4u8(0, 255, 255, 255);
441         GXPosition3f32(0.0F, 0.0F, 500.0F);
442         GXColor4u8(0, 255, 255, 255);
443     GXEnd();
444 }
445 
446 /*---------------------------------------------------------------------------*
447     Name:           SetCamera
448 
449     Description:    Sets view matrix and loads projection matrix into hardware
450 
451     Arguments:      cam : pointer to the MyCameraObj structure
452 
453     Returns:        none
454  *---------------------------------------------------------------------------*/
SetCamera(MyCameraObj * cam)455 static void SetCamera( MyCameraObj* cam )
456 {
457     MTXLookAt(
458         cam->view,
459         &cam->cfg.location,
460         &cam->cfg.up,
461         &cam->cfg.target );
462 
463     MTXFrustum(
464         cam->proj,
465         cam->cfg.top,
466         - (cam->cfg.top),
467         cam->cfg.left,
468         - (cam->cfg.left),
469         cam->cfg.znear,
470         cam->cfg.zfar );
471     GXSetProjection(cam->proj, GX_PERSPECTIVE);
472 }
473 
474 /*---------------------------------------------------------------------------*
475     Name:           SetLight
476 
477     Description:    Sets up lights and lighting channel parameters
478 
479     Arguments:      le   : pointer to a MyLightEnvObj structure
480                     view : view matrix
481 
482     Returns:        none
483  *---------------------------------------------------------------------------*/
SetLight(MyLightEnvObj * le,Mtx view)484 static void SetLight( MyLightEnvObj* le, Mtx view )
485 {
486     GXColor colorBuf[3];
487     Vec lpos;
488     f32 theta, phi;
489     u32 i;
490 
491     // Light Position
492     theta = (f32)le->theta * PI / 180.0F;
493     phi   = (f32)le->phi   * PI / 180.0F;
494     lpos.x = 500.0F * cosf(phi) * sinf(theta);
495     lpos.y = 500.0F * sinf(phi);
496     lpos.z = 500.0F * cosf(phi) * cosf(theta);
497 
498     // Convert light position into view space
499     MTXMultVec(view, &lpos, &lpos);
500 
501     // Ambient/Material/Light color (red value only)
502     for ( i = 0 ; i < 3 ; ++i )
503     {
504         colorBuf[i].r = (u8)(le->brightCtrl[i] * 255.0F);
505         colorBuf[i].b = 0;
506         colorBuf[i].g = 0;
507         colorBuf[i].a = 255;
508     }
509     // The green component of ambient color is used to lookup
510     // 1D cartoon texture from 2D texture map.
511     colorBuf[0].g = (u8)(le->cartoonType * 0x20 + 0x10);
512     colorBuf[1].g = 255;
513 
514     GXInitLightPos(&le->lobj, lpos.x, lpos.y, lpos.z);
515     GXInitLightColor(&le->lobj, colorBuf[2]);
516     GXLoadLightObjImm(&le->lobj, GX_LIGHT0);
517 
518     // Lighting channel
519     GXSetNumChans(1); // number of active color channels
520     GXSetChanCtrl(
521         GX_COLOR0A0,
522         GX_ENABLE,   // enable channel
523         GX_SRC_REG,  // amb source
524         GX_SRC_REG,  // mat source
525         GX_LIGHT0,   // light mask
526         GX_DF_SIGN,  // diffuse function
527         GX_AF_NONE);
528     // set up ambient color
529     GXSetChanAmbColor(GX_COLOR0A0, colorBuf[0]);
530     // set up material color
531     GXSetChanMatColor(GX_COLOR0A0, colorBuf[1]);
532 
533 }
534 
535 /*---------------------------------------------------------------------------*
536     Name:           DisableLight
537 
538     Description:    Disables lighting
539 
540     Arguments:      none
541 
542     Returns:        none
543  *---------------------------------------------------------------------------*/
DisableLight(void)544 static void DisableLight( void )
545 {
546     GXSetNumChans(1);
547     GXSetChanCtrl(
548         GX_COLOR0A0,
549         GX_DISABLE,  // disable channel
550         GX_SRC_VTX,  // amb source
551         GX_SRC_VTX,  // mat source
552         GX_LIGHT0,   // light mask
553         GX_DF_NONE,  // diffuse function
554         GX_AF_NONE);
555 }
556 
557 /*---------------------------------------------------------------------------*
558     Name:           PrintIntro
559 
560     Description:    Prints the directions on how to use this demo.
561 
562     Arguments:      none
563 
564     Returns:        none
565  *---------------------------------------------------------------------------*/
PrintIntro(void)566 static void PrintIntro( void )
567 {
568     OSReport("\n\n");
569     OSReport("**********************************************\n");
570     OSReport("lit-cartoon: unclamped diffuse function with\n");
571     OSReport("            texture lookup (cartoon rendering)\n");
572     OSReport("**********************************************\n");
573     OSReport("to quit hit the start button\n");
574     OSReport("\n");
575     OSReport("Main Stick   : Move Light Position\n");
576     OSReport("Sub  Stick   : Rotate the Model\n");
577     OSReport("Y Button     : Select control parameter\n");
578     OSReport("X Buttons    : Select texture coordinate\n");
579     OSReport("L/R Triggers : Change parameter value\n");
580     OSReport("A Button     : Change Model\n");
581     OSReport("B Button     : Change 1D texture\n");
582     OSReport("**********************************************\n");
583 }
584 
585 /*============================================================================*/
586