1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin/Revolution gx demo
3   File:     tg-emboss.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_DEPTH    128.0f
18 #define SCREEN_ZNEAR    0.0f    // near plane Z in screen coordinates
19 #define SCREEN_ZFAR     1.0f    // far  plane Z in screen coordinates
20 #define ZBUFFER_MAX     0x00ffffff
21 
22 /*---------------------------------------------------------------------------*
23    Typedefs
24  *---------------------------------------------------------------------------*/
25 typedef struct
26 {
27     Camera*     camera;
28     ViewPort*   viewport;
29     GXColor*    bgcolor;
30 }   Scene;
31 
32 /*---------------------------------------------------------------------------*
33    Forward references
34  *---------------------------------------------------------------------------*/
35 void    SceneDraw      ( Scene* );
36 void    SceneControl   ( Scene*, DEMOPadStatus* );
37 void    myInitModel    ( void );
38 void    myAnimeModel   ( Scene*, DEMOPadStatus* );
39 void    myDrawModel    ( Scene* );
40 void    myInfoModel    ( Scene* );
41 static void PrintIntro( void );
42 
43 /*---------------------------------------------------------------------------*
44    Rendering parameters
45  *---------------------------------------------------------------------------*/
46 Camera   myCamera =
47 {
48     { 0.0f,-300.0f, 0.0f },     // position
49     { 0.0f,   0.0f, 0.0f },     // target
50     { 0.0f,   0.0f, 1.0f },     // upVec
51        33.3f,                   // fovy
52        16.0f,                   // near plane Z in camera coordinates
53      1024.0f,                   // far  plane Z in camera coordinates
54 };
55 
56 ViewPort        myViewPort = { 0, 0, 0, 0 };
57 GXColor         myBgColor  = {  32,  32, 255, 255};
58 Scene           myScene    = { &myCamera, &myViewPort, &myBgColor };
59 
60 /*---------------------------------------------------------------------------*
61    Application main loop
62  *---------------------------------------------------------------------------*/
main(void)63 void    main ( void )
64 {
65     GXRenderModeObj *rmp;
66 
67     // initialize render settings and set clear color for first frame
68     DEMOInit(NULL);
69     GXInvalidateTexAll( );
70     GXSetCopyClear( *(myScene.bgcolor), GX_MAX_Z24 );
71 
72     // Dummy copy operation to clear the eFB by specified color
73     GXCopyDisp( DEMOGetCurrentBuffer(), GX_TRUE );
74 
75     rmp = DEMOGetRenderModeObj();
76     myViewPort.width  = (s16) rmp->fbWidth;
77     myViewPort.height = (s16) rmp->efbHeight;
78 
79     myInitModel( );
80 
81     while ( ! ( DEMOPadGetButton(0) & PAD_BUTTON_MENU ) )
82     {
83         // get pad status
84         DEMOPadRead( );
85 
86         // General control & model animation
87         SceneControl( &myScene, &DemoPad[0] );
88         myAnimeModel( &myScene, &DemoPad[0] );
89 
90         // Draw scene
91         DEMOBeforeRender( );
92         SceneDraw( &myScene );
93         DEMODoneRender( );
94     }
95 
96     OSHalt("End of demo");
97 }
98 
99 /*---------------------------------------------------------------------------*
100    Functions
101  *---------------------------------------------------------------------------*/
102 
103 //============================================================================
104 //  Scene
105 //============================================================================
106 
107 /*---------------------------------------------------------------------------*
108     Name:           SceneControl
109     Description:    user interface for parameter control
110     Arguments:
111     Returns:        none
112  *---------------------------------------------------------------------------*/
SceneControl(Scene * s,DEMOPadStatus * pad)113 void    SceneControl( Scene* s, DEMOPadStatus* pad )
114 {
115     #pragma  unused( s, pad )
116     return;
117 }
118 
119 /*---------------------------------------------------------------------------*
120     Name:           SceneDraw
121     Description:    Draw model
122     Arguments:      Scene* s
123     Returns:        none
124  *---------------------------------------------------------------------------*/
SceneDraw(Scene * s)125 void    SceneDraw( Scene* s )
126 {
127     Camera*     c  = s->camera;
128     ViewPort*   v  = s->viewport;
129     float       aspect = (float) (4.0 / 3.0);
130 
131     // Set projection matrix
132     MTXPerspective ( c->projMtx, c->fovy, aspect, c->znear, c->zfar );
133     GXSetProjection( c->projMtx, GX_PERSPECTIVE );
134 
135     // Set CameraView matrix
136     MTXLookAt( c->viewMtx, &c->position, &c->up, &c->target );
137 
138     // Set Viewport
139     GXSetViewport( v->xorg, v->yorg, v->width, v->height,
140                    SCREEN_ZNEAR, SCREEN_ZFAR );
141     GXSetScissor ( v->xorg, v->yorg, v->width, v->height );
142 
143     // Set rendering mode
144     GXSetCullMode ( GX_CULL_BACK );
145 
146     // Draw objects
147     myDrawModel( s );
148 
149     // draw information
150     myInfoModel( s );
151     return;
152 }
153 
154 //============================================================================
155 //  Model
156 //  Rectangles
157 //============================================================================
158 typedef struct
159 {
160     GXColor        color;
161     Point3d        pos;         // in world space
162     f32            dist;
163     GXLightObj     obj;
164 }   MyLight;
165 
166 typedef struct
167 {
168     Mtx            modelMtx;
169     u8             bumpScale;   // 0-128 on Emulator, 0-255 on HW
170     s32            invNrmScale;
171     s32            blendSteps;
172     u32            texNo;
173     GXTexObj       texObj;
174 }   MyModel;
175 
176 typedef struct
177 {
178     s32            cursor;
179     s32            animation;
180     GXTexCoordID   coord, coord1; // to show all tex coord pairs work
181 }   MyControl;
182 
183 MyLight         myLight;
184 MyModel         myModel;
185 MyControl       myControl;
186 TPLPalettePtr   texPalette = 0;
187 
188 #ifndef M_SQRT3
189 #define M_SQRT3     1.732050808f
190 #endif
191 
192 /*---------------------------------------------------------------------------*
193     Name:           myDrawModel
194     Description:    draw model
195     Arguments:      Camera *c
196     Returns:        none
197  *---------------------------------------------------------------------------*/
myInitModel(void)198 void    myInitModel( void )
199 {
200     Vec   axis = { 1.0f, 0.0f, 1.0f };
201 
202     //------------------------------------------------------------------------
203     //  MODEL
204     //------------------------------------------------------------------------
205 
206     //  Matrix
207     MTXRotAxisDeg( myModel.modelMtx, &axis, -150.0f );
208 
209     //  Texture
210     myModel.texNo = 1;
211     TPLGetPalette( &texPalette, "gxTests/tg-02.tpl" );
212     TPLGetGXTexObjFromPalette( texPalette, &myModel.texObj, myModel.texNo-1 );
213 
214     //  Bump Mapping
215     myModel.bumpScale   = 128;
216     myModel.blendSteps  = 3;
217     myModel.invNrmScale = 48;
218 
219     //------------------------------------------------------------------------
220     //  LIGHT
221     //------------------------------------------------------------------------
222 
223     //  Light color
224     myLight.color.r = 32;
225     myLight.color.g = 64;
226     myLight.color.b = 96;
227 
228     //  Light position in world space
229     myLight.dist  = 100.0f;
230     myLight.pos.x = - myLight.dist * 1.0f / M_SQRT3;
231     myLight.pos.y = - myLight.dist * 1.0f / M_SQRT3;
232     myLight.pos.z = + myLight.dist * 1.0f / M_SQRT3;
233 
234     //  Set white light with no attenuation
235     GXInitLightSpot    ( &myLight.obj, 0.0f, GX_SP_OFF );
236     GXInitLightDistAttn( &myLight.obj, 0.0f, 0.0f, GX_DA_OFF );
237 
238     //------------------------------------------------------------------------
239     //  CONTROL
240     //------------------------------------------------------------------------
241     myControl.cursor = 0;
242     myControl.animation = 1;
243     myControl.coord = GX_TEXCOORD0;
244     myControl.coord1 = GX_TEXCOORD1;
245 }
246 
247 /*---------------------------------------------------------------------------*
248     Name:           myAnimeModel
249     Description:    animate model
250     Arguments:      Scene* s
251     Returns:        none
252  *---------------------------------------------------------------------------*/
myAnimeModel(Scene * s,DEMOPadStatus * pad)253 void    myAnimeModel( Scene* s, DEMOPadStatus* pad )
254 {
255 #   pragma  unused(s)
256     f32  r2, y2, scale;
257     Mtx  tmp;
258     Vec  axis;
259 
260     //---------------------------------------------------------------------
261     //  Move cursor
262     //---------------------------------------------------------------------
263     if ( pad->buttonDown & PAD_BUTTON_X )
264     {
265         myControl.cursor ++;
266     }
267     if ( pad->buttonDown & PAD_BUTTON_B )
268     {
269         myControl.cursor += 4;
270     }
271     myControl.cursor %= 5;
272 
273     //---------------------------------------------------------------------
274     //  Cycle though all texture coordinates
275     //---------------------------------------------------------------------
276     if ( pad->buttonDown & PAD_BUTTON_Y )
277     {
278         myControl.coord++;
279         if (myControl.coord > GX_TEXCOORD6)
280             myControl.coord = GX_TEXCOORD0;
281         myControl.coord1 = (GXTexCoordID)(myControl.coord + 1);
282         OSReport("Using texture coord %d and %d\n",
283                 myControl.coord, myControl.coord1);
284     }
285     //---------------------------------------------------------------------
286     //  Change item
287     //---------------------------------------------------------------------
288     if ( pad->buttonDown & PAD_BUTTON_A )
289     {
290         switch ( myControl.cursor )
291         {
292         case  0:
293             //  Texture
294             myModel.texNo %= 3;
295             myModel.texNo ++;
296             TPLGetGXTexObjFromPalette( texPalette,
297                                   &myModel.texObj, myModel.texNo-1 );
298             break;
299 
300         case  1:
301             //  Animation
302             myControl.animation ^= 1;
303             break;
304 
305         case  2:
306             //  Bump scale
307             myModel.bumpScale = (u8)( ( myModel.bumpScale < 128 )
308                                       ? myModel.bumpScale + 32 : 0 );
309             break;
310 
311         case  3:
312             //  Normal scale    ( 8 - 96 )
313             myModel.invNrmScale %= 96;
314             myModel.invNrmScale += 8;
315             break;
316 
317         case  4:
318             //  Show step of blending
319             myModel.blendSteps %= 3;
320             myModel.blendSteps ++;
321             break;
322         }
323     }
324 
325     //---------------------------------------------------------------------
326     //  Animation
327     //---------------------------------------------------------------------
328     if ( myControl.animation )
329     {
330         axis.x = 1.0f;
331         axis.y = 2.0f;
332         axis.z = 0.5f;
333         MTXRotAxisDeg( tmp, &axis, 1.0f );
334         MTXConcat( myModel.modelMtx, tmp, myModel.modelMtx );
335     }
336 
337     //---------------------------------------------------------------------
338     //  Change light position
339     //---------------------------------------------------------------------
340     if ( pad->dirs & DEMO_STICK_LEFT  ) myLight.pos.x -= 2.0f;
341     if ( pad->dirs & DEMO_STICK_RIGHT ) myLight.pos.x += 2.0f;
342     if ( pad->dirs & DEMO_STICK_UP    ) myLight.pos.z += 2.0f;
343     if ( pad->dirs & DEMO_STICK_DOWN  ) myLight.pos.z -= 2.0f;
344 
345     r2 = myLight.pos.x * myLight.pos.x + myLight.pos.z * myLight.pos.z;
346     y2 = myLight.dist * myLight.dist - r2;
347 
348     if ( y2 < 0 )
349     {
350         scale = myLight.dist / sqrtf(r2);
351         myLight.pos.x *= scale;
352         myLight.pos.z *= scale;
353         myLight.pos.y  = 0.0f;
354     }
355     else
356     {
357         myLight.pos.y = - sqrtf(y2);
358     }
359 }
360 
361 /*---------------------------------------------------------------------------*
362     Name:           myDrawModel
363     Description:    draw model
364     Arguments:      Scene *c
365     Returns:        none
366  *---------------------------------------------------------------------------*/
367 
myDrawModel(Scene * s)368 void    myDrawModel( Scene* s )
369 {
370     Camera*     c = s->camera;
371     Mtx         mvmtx, posMtx, nrmMtx;
372     Point3d     lpos;
373     f32         nrmScale = 1.0f / (f32)myModel.invNrmScale;
374     GXColor color1 = {255,64,64,255};
375 
376     // set a light object
377     MTXMultVec( c->viewMtx, &myLight.pos, &lpos );
378     GXInitLightPos   ( &myLight.obj, lpos.x, lpos.y, lpos.z );
379     GXInitLightColor ( &myLight.obj, myLight.color );
380     GXLoadLightObjImm( &myLight.obj, GX_LIGHT0 );
381 
382     // set modelview matrix
383     GXSetCurrentMtx( GX_PNMTX0 );
384 
385     // Load ModelView matrix for pos/nrm into view space
386     // Note: mvmtx is uniform transformation here, then (mvmtx)^(-T) = mvmtx
387     //       With bump mapping, normal must be scaled to match texel size in
388     //       texture space.
389     MTXConcat      ( c->viewMtx, myModel.modelMtx, mvmtx );
390     MTXScale       ( posMtx, 75.0f, 75.0f, 75.0f );
391     MTXConcat      ( mvmtx,  posMtx, posMtx );
392     GXLoadPosMtxImm( posMtx, GX_PNMTX0 );
393     MTXScale       ( nrmMtx, nrmScale, nrmScale, nrmScale );
394     MTXConcat      ( mvmtx,  nrmMtx, nrmMtx );
395     GXLoadNrmMtxImm( nrmMtx, GX_PNMTX0 );
396 
397     // Set texture
398     GXLoadTexObj( &myModel.texObj, GX_TEXMAP0 );
399 
400     // Render mode for Box
401     GXClearVtxDesc( );
402 
403     //  z update for 1st stage
404     GXSetZMode  ( GX_TRUE, GX_LESS, GX_TRUE );
405 
406     //------------------------------------------------------------------------
407     //   Actual code for bump mapping on dolphin HW.
408     //------------------------------------------------------------------------
409     {
410         GXColor bumpScale;
411         u32     i;
412         GXColor white = {255,255,255,255};
413         GXColor grey = {128,128,128,128};
414 
415         //  Vertex component
416         GXClearVtxDesc();
417         GXSetVtxDesc( GX_VA_POS,  GX_DIRECT );
418         GXSetVtxDesc( GX_VA_NBT,  GX_DIRECT );
419         GXSetVtxDesc( GX_VA_TEX0, GX_DIRECT );
420 
421         //  Light 0 for bump mapping
422         GXSetNumChans(1); // GX_COLOR0A0
423         GXSetChanCtrl( GX_COLOR0, GX_ENABLE,     GX_SRC_REG,  GX_SRC_REG,
424                                   GX_LIGHT0,     GX_DF_CLAMP, GX_AF_NONE );
425         GXSetChanCtrl( GX_ALPHA0, GX_DISABLE,    GX_SRC_REG,  GX_SRC_REG,
426                                   GX_LIGHT_NULL, GX_DF_CLAMP, GX_AF_NONE );
427         GXSetChanMatColor( GX_COLOR0A0, white );
428         GXSetChanAmbColor( GX_COLOR0A0, grey );
429 
430         // clear out unused tex gens
431         for (i = 0; i < myControl.coord; i++)
432             GXSetTexCoordGen( (GXTexCoordID)i, GX_TG_MTX2x4,
433                               GX_TG_POS, GX_IDENTITY );
434 
435         //  Tex Gen
436         //     GX_TEXCOORD0: Base texcoord of bump mapping
437         //     GX_TEXCOORD1: Tex gen by bump mapping
438         GXSetNumTexGens((u8)(myControl.coord1+1)); // coord1 is always the max coord
439         GXSetTexCoordGen( myControl.coord, GX_TG_MTX2x4,
440                           GX_TG_TEX0,      GX_IDENTITY );
441         GXSetTexCoordGen( myControl.coord1, GX_TG_BUMP0,
442                           (GXTexGenSrc)((u32)myControl.coord + GX_TG_TEXCOORD0),
443                           GX_IDENTITY );
444 
445         //  Tev Order
446         //     GX_TEVSTAGE0: send base    texture + diffuse color
447         //     GX_TEVSTAGE1: send shifted texture
448         GXSetTevOrder( GX_TEVSTAGE0,
449                        myControl.coord, GX_TEXMAP0, GX_COLOR0A0   );
450         GXSetTevOrder( GX_TEVSTAGE1,
451                        myControl.coord1, GX_TEXMAP0, GX_COLOR_NULL );
452 
453         //  Tev Register
454         //     GX_TEVREG0: ( X, X, X, bumpScale )
455         bumpScale.a = myModel.bumpScale;
456         GXSetTevColor( GX_TEVREG0, bumpScale );
457 
458         //
459         //  In many case, bump mapping needs 3 tev stage, but here,
460         //  use only 2 tev stages, since no material texture map
461         //
462         GXSetNumTevStages( 2 );
463 
464         //
465         //  Tev stage0
466         //     Color:   BumpTexture * bumpScale + DiffuseColor => R
467         //     Alpha:   Not used
468         //
469         GXSetTevColorIn( GX_TEVSTAGE0, GX_CC_ZERO,
470                                        GX_CC_TEXC,  /* Bump Texture   */
471                                        GX_CC_A0,    /* BumpScale      */
472                                        GX_CC_RASC   /* Diffuse color  */ );
473         GXSetTevColorOp( GX_TEVSTAGE0, GX_TEV_ADD,
474                                        GX_TB_ZERO,
475                                        GX_CS_SCALE_1,
476                                        GX_DISABLE,
477                                        GX_TEVPREV   /* To next stage  */ );
478 
479         GXSetTevAlphaIn( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO,
480                                        GX_CA_ZERO, GX_CA_ZERO );
481         GXSetTevAlphaOp( GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO,
482                                        GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV );
483 
484         //
485         //  Tev stage1
486         //     Color:   ShiftTexture * bumpScale * (-1) + R  =>  R
487         //     Alpha:   Not used
488         //
489         GXSetTevColorIn( GX_TEVSTAGE1, GX_CC_ZERO,
490                                        GX_CC_TEXC,  /* Shift Texture  */
491                                        GX_CC_A0,    /* BumpScale      */
492                                        GX_CC_CPREV  /* Last stage out */ );
493         GXSetTevColorOp( GX_TEVSTAGE1, GX_TEV_SUB,  /* mult (-1)      */
494                                        GX_TB_ZERO,
495                                        GX_CS_SCALE_1,
496                                        GX_ENABLE,
497                                        GX_TEVPREV                        );
498 
499         GXSetTevAlphaIn( GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_ZERO,
500                                        GX_CA_ZERO, GX_CA_ZERO );
501         GXSetTevAlphaOp( GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO,
502                                        GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV );
503 
504         //-------------------------------------------------
505         //  Draw objects
506         //-------------------------------------------------
507         GXDrawCube( );
508     }
509 
510     //-------------------------------------------------
511     //  Draw light direction
512     //-------------------------------------------------
513 
514     // Shade mode
515     GXSetChanCtrl    ( GX_COLOR0, GX_DISABLE,    GX_SRC_REG,  GX_SRC_REG,
516                                   GX_LIGHT_NULL, GX_DF_CLAMP, GX_AF_NONE );
517     GXSetChanMatColor( GX_COLOR0, color1 );
518 
519     GXSetNumTexGens  ( 0 );
520 
521     // Tev mode
522     GXSetNumTevStages( 1 );
523     GXSetTevOrder    ( GX_TEVSTAGE0,
524                        GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0 );
525     GXSetTevOp       ( GX_TEVSTAGE0, GX_PASSCLR );
526 
527     // Render mode
528     GXSetBlendMode   ( GX_BM_BLEND, GX_BL_ONE, GX_BL_ZERO, GX_LO_CLEAR );
529     GXSetZMode       ( GX_TRUE, GX_LESS, GX_TRUE );
530 
531     // Draw lines
532     GXClearVtxDesc   ( );
533     GXSetVtxDesc     ( GX_VA_POS, GX_DIRECT );
534     GXSetVtxAttrFmt  ( GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );
535     GXLoadPosMtxImm  ( c->viewMtx, GX_PNMTX0 );
536     GXBegin( GX_LINES, GX_VTXFMT1, 2 );
537        GXPosition3f32( 0.0f, 0.0f, 0.0f );
538        GXPosition3f32( myLight.pos.x, myLight.pos.y, myLight.pos.z );
539     GXEnd( );
540     GXBegin( GX_LINESTRIP, GX_VTXFMT1, 5 );
541        GXPosition3f32( myLight.pos.x+2.0f, myLight.pos.y, myLight.pos.z+2.0f );
542        GXPosition3f32( myLight.pos.x+2.0f, myLight.pos.y, myLight.pos.z-2.0f );
543        GXPosition3f32( myLight.pos.x-2.0f, myLight.pos.y, myLight.pos.z-2.0f );
544        GXPosition3f32( myLight.pos.x-2.0f, myLight.pos.y, myLight.pos.z+2.0f );
545        GXPosition3f32( myLight.pos.x+2.0f, myLight.pos.y, myLight.pos.z+2.0f );
546     GXEnd( );
547 
548     return;
549 }
550 
551 /*---------------------------------------------------------------------------*
552     Name:           ModelDrawInfo
553     Description:    Draw scene information
554     Arguments:
555     Returns:        none
556  *---------------------------------------------------------------------------*/
myInfoModel(Scene * s)557 void    myInfoModel( Scene* s )
558 {
559     ViewPort*   v = s->viewport;
560 
561     // Z mode for drawing captions
562     GXSetZMode( GX_TRUE, GX_ALWAYS, GX_TRUE );
563 
564     // Draw parameters to the window
565     DEMOInitCaption( DM_FT_XLU, v->width, v->height );
566     DEMOPuts  ( 10, (s16)(myControl.cursor*8+10), 0, "\x7f" );
567     DEMOPrintf( 18, 10, 0, "Texture      %d", myModel.texNo );
568     DEMOPrintf( 18, 18, 0,
569                 "Animation    %s", myControl.animation ? "ON" : "OFF" );
570     DEMOPrintf( 18, 26, 0, "Bump   scale %d", myModel.bumpScale );
571     DEMOPrintf( 18, 34, 0, "Normal scale 1/%d", myModel.invNrmScale );
572     DEMOPrintf( 18, 42, 0, "Blend  steps %d", myModel.blendSteps );
573 
574     return;
575 }
576 
577 /*---------------------------------------------------------------------------*
578     Name:           PrintIntro
579 
580     Description:    Prints the directions on how to use this demo.
581 
582     Arguments:      none
583 
584     Returns:        none
585  *---------------------------------------------------------------------------*/
PrintIntro(void)586 static void PrintIntro( void )
587 {
588     OSReport("\n\n");
589     OSReport("**********************************************\n");
590     OSReport("tg-emboss: demonstrate bump mapping using the \n");
591     OSReport("           embossing technique.               \n");
592     OSReport("**********************************************\n");
593     OSReport("to quit hit the start button\n");
594     OSReport("\n");
595     OSReport("Main Stick   : Move Light Position\n");
596     OSReport("Sub  Stick   : Rotate the Model\n");
597     OSReport("X/B Buttons  : Select parameter\n");
598     OSReport("A Button     : Change selected parameter\n");
599     OSReport("Y Button     : Change texture coordinate\n");
600     OSReport("**********************************************\n");
601 }
602 
603 
604 
605 /*======== End of tg-emboss.c ========*/
606