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