1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin/Revolution gx demo
3   File:     lit-texture.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-texture
15      Texture with lighting test
16  *---------------------------------------------------------------------------*/
17 
18 /*---------------------------------------------------------------------------*
19    Header files
20  *---------------------------------------------------------------------------*/
21 #include <demo.h>
22 #include <math.h>
23 
24 /*---------------------------------------------------------------------------*
25    Macro definitions
26  *---------------------------------------------------------------------------*/
27 #define  PI    3.14159265358979323846F
28 
29 #define  NUM_TEVMODES    5
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         colorCtrl[3][3];
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     GXTexObj       texture;
73     u32            tevMode;
74 } MySceneCtrlObj;
75 
76 /*---------------------------------------------------------------------------*
77    Forward references
78  *---------------------------------------------------------------------------*/
79 void        main            ( void );
80 static void DrawInit        ( MySceneCtrlObj* sc );
81 static void DrawTick        ( MySceneCtrlObj* sc );
82 static void AnimTick        ( MySceneCtrlObj* sc );
83 static void DrawModel       ( u32 model );
84 static void DrawLightMark   ( void );
85 static void SetCamera       ( MyCameraObj* cam );
86 static void SetLight        ( MyLightEnvObj * le, Mtx view );
87 static void DisableLight    ( void );
88 static void PrintIntro      ( void );
89 static void PrintParam      ( u32 cur, f32 param );
90 
91 /*---------------------------------------------------------------------------*
92    Model data and strings for message
93  *---------------------------------------------------------------------------*/
94 #define SPHERE      0
95 #define CYLINDER    1
96 #define TORUS       2
97 #define ICOSA       3
98 #define DODECA      4
99 #define OCTA        5
100 #define CUBE        6
101 
102 #define MODELS      7
103 
104 static GXTevMode TevModeTable[] =
105 {
106     GX_MODULATE,
107     GX_DECAL,
108     GX_PASSCLR,
109     GX_REPLACE,
110     GX_BLEND     // not supported on the MAC emulator
111 };
112 
113 static char* TevModeStr[] =
114 {
115     "GX_MODULATE",
116     "GX_DECAL",
117     "GX_PASSCLR",
118     "GX_REPLACE",
119     "GX_BLEND"
120 };
121 
122 static char* ParamTitle[] =
123 {
124     "Ambient",
125     "Material",
126     "Light"
127 };
128 
129 /*---------------------------------------------------------------------------*
130    Test texture data
131  *---------------------------------------------------------------------------*/
132 #define TEST_TEXTURE_WIDTH   8
133 #define TEST_TEXTURE_HEIGHT  8
134 #define TEST_TEXTURE_FORMAT  GX_TF_RGB5A3
135 
136 static u16 TestTextureData[] ATTRIBUTE_ALIGN(32) =
137 {
138     // RGB5A3 format 8x8
139     0x7FFF, 0x7F00, 0x7F88, 0x70FF,
140     0x78FF, 0x700F, 0x78F8, 0x7888,
141     0x7CCC, 0x7FF8, 0x7F8F, 0x7FF0,
142     0x7F0F, 0x788F, 0x70F0, 0x7000,
143 
144     0x1FFF, 0x1F00, 0x1F88, 0x10FF,
145     0x18FF, 0x100F, 0x18F8, 0x1888,
146     0x1CCC, 0x1FF8, 0x1F8F, 0x1FF0,
147     0x1F0F, 0x188F, 0x10F0, 0x1000,
148 
149     0x0FFF, 0x0F00, 0x0F88, 0x00FF,
150     0x08FF, 0x000F, 0x08F8, 0x0888,
151     0x0CCC, 0x0FF8, 0x0F8F, 0x0FF0,
152     0x0F0F, 0x088F, 0x00F0, 0x0000,
153 
154     0x6FFF, 0x6F00, 0x6F88, 0x60FF,
155     0x68FF, 0x600F, 0x68F8, 0x6888,
156     0x6CCC, 0x6FF8, 0x6F8F, 0x6FF0,
157     0x6F0F, 0x688F, 0x60F0, 0x6000,
158 };
159 
160 /*---------------------------------------------------------------------------*
161    Camera configuration
162  *---------------------------------------------------------------------------*/
163 static CameraConfig DefaultCamera =
164 {
165     { 0.0F, 0.0F, 900.0F }, // location
166     { 0.0F, 1.0F,   0.0F }, // up
167     { 0.0F, 0.0F,   0.0F }, // target
168     -320.0F, // left
169     240.0F,  // top
170     400.0F,  // near
171     2000.0F  // far
172 };
173 
174 /*---------------------------------------------------------------------------*
175    Global variables
176  *---------------------------------------------------------------------------*/
177 static MySceneCtrlObj  SceneCtrl;    // scene control parameters
178 
179 /*---------------------------------------------------------------------------*
180    Application main loop
181  *---------------------------------------------------------------------------*/
main(void)182 void main ( void )
183 {
184     DEMOInit(NULL);      // Init the OS, game pad, graphics and video.
185 
186     DrawInit(&SceneCtrl);       // Initialize vertex formats and scene parameters.
187 
188     PrintIntro();    // Print demo directions
189 
190     while(!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
191     {
192         DEMOBeforeRender();
193         DrawTick(&SceneCtrl);    // Draw the model.
194         DEMODoneRender();
195         DEMOPadRead();           // Update pad status.
196         AnimTick(&SceneCtrl);    // Update animation.
197     }
198 
199     OSHalt("End of demo");
200 }
201 
202 /*---------------------------------------------------------------------------*
203    Functions
204  *---------------------------------------------------------------------------*/
205 /*---------------------------------------------------------------------------*
206     Name:           DrawInit
207 
208     Description:    Initializes the vertex attribute format, texture and
209                     default scene parameters.
210 
211     Arguments:      sc : pointer to the structure of scene control parameters
212 
213     Returns:        none
214  *---------------------------------------------------------------------------*/
DrawInit(MySceneCtrlObj * sc)215 static void DrawInit( MySceneCtrlObj* sc )
216 {
217     u32 i;
218     Mtx mv,mr;
219 
220     // set up a vertex attribute
221     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
222     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
223     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
224 
225     // set up texture coord generation matrix
226     // because GXDraw Objects have no texture coords.
227     GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX3x4, GX_TG_POS, GX_TEXMTX0);
228     MTXLightFrustum(mv, -1.0F, 1.0F, -1.0F, 1.0F, 8.0F, 1.0F, 1.0F, 0.5F, 0.5F);
229     MTXTrans(mr, 0.0F, 0.0F, -5.0F);
230     MTXConcat(mv, mr, mv);
231     GXLoadTexMtxImm(mv, GX_TEXMTX0, GX_MTX3x4);
232 
233     GXInvalidateTexAll();
234 
235 
236     // Default scene parameter settings
237 
238     // camera
239     sc->cam.cfg = DefaultCamera;
240     SetCamera(&sc->cam);   // never changes in this test
241 
242     // texture
243     GXInitTexObj(
244         &sc->texture,
245         TestTextureData,
246         TEST_TEXTURE_WIDTH,
247         TEST_TEXTURE_HEIGHT,
248         TEST_TEXTURE_FORMAT,
249         GX_REPEAT, // s
250         GX_REPEAT, // t
251         GX_FALSE );
252     GXInitTexObjLOD(
253         &sc->texture,
254         GX_NEAR,
255         GX_NEAR,
256         0,
257         0,
258         0,
259         GX_FALSE,
260         GX_FALSE,
261         GX_ANISO_1 );
262 
263     // light parameters
264     sc->lightEnv.theta  = 0;
265     sc->lightEnv.phi    = 0;
266 
267     // color of Ambient/Material/Light
268     for ( i = 0 ; i < 3 ; ++i )
269     {
270         sc->lightEnv.colorCtrl[0][i] = 0.1F;
271         sc->lightEnv.colorCtrl[1][i] = 1.0F;
272         sc->lightEnv.colorCtrl[2][i] = 0.9F;
273     }
274 
275     // initialize model control matrix
276     MTXScale(sc->modelCtrl, 250.0F, 250.0F, 250.0F);
277     sc->modelType = 0;
278 
279     // tev mode
280     sc->tevMode = 0;
281 }
282 
283 /*---------------------------------------------------------------------------*
284     Name:           DrawTick
285 
286     Description:    Draws the model by using given scene parameters
287 
288     Arguments:      sc : pointer to the structure of scene control parameters
289 
290     Returns:        none
291  *---------------------------------------------------------------------------*/
DrawTick(MySceneCtrlObj * sc)292 static void DrawTick( MySceneCtrlObj* sc )
293 {
294     Mtx  mv;  // Modelview matrix.
295     Mtx  mr;  // Rotate matrix
296     Mtx  mvi; // Modelview matrix.
297 
298     // Tev mode = one color / one texture
299     GXSetNumTexGens(1); // use one texture coord
300     GXSetTevOp(GX_TEVSTAGE0, TevModeTable[sc->tevMode]);
301     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
302 
303     // texture and lights
304     GXLoadTexObj(&sc->texture, GX_TEXMAP0);
305     SetLight(&sc->lightEnv, sc->cam.view);
306 
307     // Draw a model
308     MTXConcat(sc->cam.view, sc->modelCtrl, mv);
309     GXLoadPosMtxImm(mv, GX_PNMTX0);
310     MTXInverse(mv, mvi);
311     MTXTranspose(mvi, mv);
312     GXLoadNrmMtxImm(mv, GX_PNMTX0);
313     DrawModel(sc->modelType);
314 
315 
316     // Tev mode = one color / no texture
317     GXSetNumTexGens(0);
318     GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
319     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
320     // disable lighting
321     DisableLight();
322 
323     // draw a light mark
324     MTXRotDeg(mr, 'y', sc->lightEnv.theta);
325     MTXConcat(sc->cam.view, mr, mv);
326     MTXRotDeg(mr, 'x', - sc->lightEnv.phi);
327     MTXConcat(mv, mr, mv);
328     GXLoadPosMtxImm(mv, GX_PNMTX0);
329     DrawLightMark();
330 }
331 
332 /*---------------------------------------------------------------------------*
333     Name:           AnimTick
334 
335     Description:    Changes scene parameters according to the pad status.
336 
337     Arguments:      sc : pointer to the structure of scene control parameters
338 
339     Returns:        none
340  *---------------------------------------------------------------------------*/
AnimTick(MySceneCtrlObj * sc)341 static void AnimTick( MySceneCtrlObj* sc )
342 {
343     static u32  cursor = 0;
344     u16  down;
345     Mtx  mrx, mry;
346 
347     // PAD
348     down = DEMOPadGetButtonDown(0);
349 
350     // Light Position Calculation
351     sc->lightEnv.theta += (DEMOPadGetStickX(0) / 24);
352     sc->lightEnv.theta %= 360;
353     sc->lightEnv.phi += (DEMOPadGetStickY(0) / 24);
354     Clamp(sc->lightEnv.phi, -90, 90);
355 
356 
357     // Model Rotation Calculation
358     MTXRotDeg(mry, 'x', -(DEMOPadGetSubStickY(0) / 24));
359     MTXRotDeg(mrx, 'y', (DEMOPadGetSubStickX(0) / 24));
360     MTXConcat(mry, sc->modelCtrl, sc->modelCtrl);
361     MTXConcat(mrx, sc->modelCtrl, sc->modelCtrl);
362 
363 
364     // Select Ambient/Material/Light (also R/G/B)
365     if ( down & PAD_BUTTON_Y )
366     {
367         cursor = ( cursor + 1 ) % 9;
368         PrintParam(cursor, sc->lightEnv.colorCtrl[cursor/3][cursor%3]);
369     }
370     if ( down & PAD_BUTTON_X )
371     {
372         cursor = ( cursor + 8 ) % 9;
373         PrintParam(cursor, sc->lightEnv.colorCtrl[cursor/3][cursor%3]);
374     }
375     // Color Parameter Tuning
376     if ( down & PAD_TRIGGER_L )
377     {
378         sc->lightEnv.colorCtrl[cursor/3][cursor%3] -= 0.05F;
379         if ( sc->lightEnv.colorCtrl[cursor/3][cursor%3] < 0.0F )
380         {
381             sc->lightEnv.colorCtrl[cursor/3][cursor%3] = 0.0F;
382         }
383         PrintParam(cursor, sc->lightEnv.colorCtrl[cursor/3][cursor%3]);
384     }
385     if ( down & PAD_TRIGGER_R )
386     {
387         sc->lightEnv.colorCtrl[cursor/3][cursor%3] += 0.05F;
388         if ( sc->lightEnv.colorCtrl[cursor/3][cursor%3] > 1.0F )
389         {
390             sc->lightEnv.colorCtrl[cursor/3][cursor%3] = 1.0F;
391         }
392         PrintParam(cursor, sc->lightEnv.colorCtrl[cursor/3][cursor%3]);
393     }
394 
395     // Change tev mode
396     if ( down & PAD_BUTTON_B )
397     {
398         sc->tevMode = ( sc->tevMode + 1 ) % NUM_TEVMODES;
399         OSReport("TevMode : %s\n", TevModeStr[sc->tevMode]);
400     }
401 
402     // Model Select
403     if ( down & PAD_BUTTON_A )
404     {
405         sc->modelType = ( sc->modelType + 1 ) % MODELS;
406     }
407 }
408 
409 /*---------------------------------------------------------------------------*
410     Name:           DrawModel
411 
412     Description:    Draws specified model
413 
414     Arguments:      model : specifies which model is to be displayed
415 
416     Returns:        none
417  *---------------------------------------------------------------------------*/
DrawModel(u32 model)418 static void DrawModel(u32 model)
419 {
420     // sets up vertex descriptors
421     GXClearVtxDesc();
422     GXSetVtxDesc(GX_VA_POS,  GX_DIRECT);
423     GXSetVtxDesc(GX_VA_NRM,  GX_DIRECT);
424 
425     // draws a GXDraw model
426     switch(model)
427     {
428         case CYLINDER :
429             GXDrawCylinder(32);
430             break;
431         case TORUS :
432             GXDrawTorus(0.25F, 12, 16);
433             break;
434         case SPHERE :
435             GXDrawSphere(12, 24);
436             break;
437         case CUBE :
438             GXDrawCube();
439             break;
440         case OCTA :
441             GXDrawOctahedron();
442             break;
443         case ICOSA :
444             GXDrawIcosahedron();
445             break;
446         case DODECA :
447             GXDrawDodeca();
448             break;
449     }
450 }
451 
452 /*---------------------------------------------------------------------------*
453     Name:           DrawLightMark
454 
455     Description:    Draws a mark which shows position of the light.
456 
457     Arguments:      none
458 
459     Returns:        none
460  *---------------------------------------------------------------------------*/
DrawLightMark(void)461 static void DrawLightMark( void )
462 {
463     // sets up vertex descriptors
464     GXClearVtxDesc();
465     GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
466     GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
467 
468     GXBegin(GX_LINES, GX_VTXFMT0, 8);
469         GXPosition3f32(500.0F, 500.0F, -500.0F);
470         GXColor4u8(0, 255, 255, 255);
471         GXPosition3f32(0.0F, 0.0F, 500.0F);
472         GXColor4u8(0, 255, 255, 255);
473 
474         GXPosition3f32(500.0F, -500.0F, -500.0F);
475         GXColor4u8(0, 255, 255, 255);
476         GXPosition3f32(0.0F, 0.0F, 500.0F);
477         GXColor4u8(0, 255, 255, 255);
478 
479         GXPosition3f32(-500.0F, 500.0F, -500.0F);
480         GXColor4u8(0, 255, 255, 255);
481         GXPosition3f32(0.0F, 0.0F, 500.0F);
482         GXColor4u8(0, 255, 255, 255);
483 
484         GXPosition3f32(-500.0F, -500.0F, -500.0F);
485         GXColor4u8(0, 255, 255, 255);
486         GXPosition3f32(0.0F, 0.0F, 500.0F);
487         GXColor4u8(0, 255, 255, 255);
488     GXEnd();
489 }
490 
491 /*---------------------------------------------------------------------------*
492     Name:           SetCamera
493 
494     Description:    Sets view matrix and loads projection matrix into hardware
495 
496     Arguments:      cam : pointer to the MyCameraObj structure
497 
498     Returns:        none
499  *---------------------------------------------------------------------------*/
SetCamera(MyCameraObj * cam)500 static void SetCamera( MyCameraObj* cam )
501 {
502     MTXLookAt(
503         cam->view,
504         &cam->cfg.location,
505         &cam->cfg.up,
506         &cam->cfg.target );
507 
508     MTXFrustum(
509         cam->proj,
510         cam->cfg.top,
511         - (cam->cfg.top),
512         cam->cfg.left,
513         - (cam->cfg.left),
514         cam->cfg.znear,
515         cam->cfg.zfar );
516     GXSetProjection(cam->proj, GX_PERSPECTIVE);
517 }
518 
519 /*---------------------------------------------------------------------------*
520     Name:           SetLight
521 
522     Description:    Sets up lights and lighting channel parameters
523 
524     Arguments:      le   : pointer to a MyLightEnvObj structure
525                     view : view matrix
526 
527     Returns:        none
528  *---------------------------------------------------------------------------*/
SetLight(MyLightEnvObj * le,Mtx view)529 static void SetLight( MyLightEnvObj* le, Mtx view )
530 {
531     GXColor colorBuf[3];
532     Vec lpos;
533     f32 theta, phi;
534     u32 i;
535 
536     // Light Position
537     theta = (f32)le->theta * PI / 180.0F;
538     phi   = (f32)le->phi   * PI / 180.0F;
539     lpos.x = 500.0F * cosf(phi) * sinf(theta);
540     lpos.y = 500.0F * sinf(phi);
541     lpos.z = 500.0F * cosf(phi) * cosf(theta);
542 
543     // Convert light position into view space
544     MTXMultVec(view, &lpos, &lpos);
545 
546     // Light/Material Color
547     for ( i = 0 ; i < 3 ; ++i )
548     {
549         colorBuf[i].r = (u8)(le->colorCtrl[i][0] * 255.0F);
550         colorBuf[i].g = (u8)(le->colorCtrl[i][1] * 255.0F);
551         colorBuf[i].b = (u8)(le->colorCtrl[i][2] * 255.0F);
552         colorBuf[i].a = 255;
553     }
554 
555     GXInitLightPos(&le->lobj, lpos.x, lpos.y, lpos.z);
556     GXInitLightColor(&le->lobj, colorBuf[2]);
557     GXLoadLightObjImm(&le->lobj, GX_LIGHT0);
558 
559     // Lighting channel
560     GXSetNumChans(1); // number of active color channels
561     GXSetChanCtrl(
562         GX_COLOR0A0,
563         GX_ENABLE,   // enable channel
564         GX_SRC_REG,  // amb source
565         GX_SRC_REG,  // mat source
566         GX_LIGHT0,   // light mask
567         GX_DF_CLAMP, // diffuse function
568         GX_AF_NONE);
569     // set up ambient color
570     GXSetChanAmbColor(GX_COLOR0A0, colorBuf[0]);
571     // set up material color
572     GXSetChanMatColor(GX_COLOR0A0, colorBuf[1]);
573 
574 }
575 
576 /*---------------------------------------------------------------------------*
577     Name:           DisableLight
578 
579     Description:    Disables lighting
580 
581     Arguments:      none
582 
583     Returns:        none
584  *---------------------------------------------------------------------------*/
DisableLight(void)585 static void DisableLight( void )
586 {
587     GXSetNumChans(1);
588     GXSetChanCtrl(
589         GX_COLOR0A0,
590         GX_DISABLE,  // disable channel
591         GX_SRC_VTX,  // amb source
592         GX_SRC_VTX,  // mat source
593         GX_LIGHT0,   // light mask
594         GX_DF_NONE,  // diffuse function
595         GX_AF_NONE);
596 }
597 
598 /*---------------------------------------------------------------------------*
599     Name:           PrintIntro
600 
601     Description:    Prints the directions on how to use this demo.
602 
603     Arguments:      none
604 
605     Returns:        none
606  *---------------------------------------------------------------------------*/
PrintIntro(void)607 static void PrintIntro( void )
608 {
609     OSReport("\n\n");
610     OSReport("************************************************\n");
611     OSReport("lit-texture: texture with lighting test\n");
612     OSReport("************************************************\n");
613     OSReport("to quit hit the start button\n");
614     OSReport("\n");
615     OSReport("Main Stick   : Move Light Position\n");
616     OSReport("Sub  Stick   : Rotate the Moddel\n");
617     OSReport("X/Y Buttons  : Select control parameter\n");
618     OSReport("L/R Triggers : Change parameter value\n");
619     OSReport("A Button     : Change Model\n");
620     OSReport("B Button     : Change tev mode\n");
621     OSReport("************************************************\n\n");
622 }
623 
624 /*---------------------------------------------------------------------------*
625     Name:           PrintParam
626 
627     Description:    Prints specified parameter.
628  *---------------------------------------------------------------------------*/
PrintParam(u32 cur,f32 param)629 static void PrintParam( u32 cur, f32 param )
630 {
631     char rgb_chars[] = {'R','G','B'};
632 
633     OSReport("%s", ParamTitle[cur/3]);
634     OSReport("[%c]", rgb_chars[cur%3]);
635     OSReport(" = %f\n", param);
636 }
637 
638 /*============================================================================*/
639