1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin/Revolution gx demo
3   File:     cul-viewport.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_WD       1       // Dummy - actual value filled at runtime
18 #define SCREEN_HT       1       // Dummy - actual value filled at runtime
19 #define SCREEN_DEPTH    128.0f
20 #define SCREEN_ZNEAR    0.0f    // near plane Z in screen coordinates
21 #define SCREEN_ZFAR 1.0f    // far  plane Z in screen coordinates
22 #define ZBUFFER_MAX 0x00ffffff
23 
24 #define M_NUMBEROF(x)       (sizeof(x)/sizeof(*(x)))
25 
26 #define Clamp(val,min,max) \
27     ((val) = (((val) < (min)) ? (min) : ((val) > (max)) ? (max) : (val)))
28 
29 /*---------------------------------------------------------------------------*
30    Typedefs
31  *---------------------------------------------------------------------------*/
32 typedef struct
33 {
34     s32     xorg;
35     s32     yorg;
36     s32     width;
37     s32     height;
38 }   ScissorBox;
39 
40 typedef struct
41 {
42     Camera* camera;
43     ViewPort*   viewport;
44     ScissorBox* scissor;
45     GXColor*    bgcolor;
46     s32         cursor;
47     u32         screen_wd;
48     u32         screen_ht;
49 }   Scene;
50 
51 /*---------------------------------------------------------------------------*
52    Forward references
53  *---------------------------------------------------------------------------*/
54 static void    SceneDraw      ( Scene* );
55 static void    SceneDrawInfo  ( Scene* );
56 static void    ControlInit    ( Scene* );
57 static void    SceneControl   ( Scene* );
58 static void    myInitModel    ( void );
59 static void    myDrawModel    ( Camera* );
60 static void    myDrawRectangle( f32, f32, f32, f32, GXColor );
61 static void    PrintIntro     ( void );
62 
63 /*---------------------------------------------------------------------------*
64    Rendering parameters
65  *---------------------------------------------------------------------------*/
66 static Camera   myCamera =
67 {
68     { 0.0f,   0.0f, 0.0f }, // position
69     { 0.0f,1000.0f, 0.0f }, // target
70     { 0.0f,   0.0f, 1.0f }, // upVec
71        33.3f,           // fovy
72        16.0f,           // near plane Z in camera coordinates
73      1024.0f,           // far  plane Z in camera coordinates
74 };
75 
76 static ViewPort    myViewPort = { 0, 0, SCREEN_WD, SCREEN_HT };
77 static ScissorBox  myScissor  = { 0, 0, SCREEN_WD, SCREEN_HT };
78 static GXColor     myBgColor  = {  32,  32, 255, 255};
79 static Scene       myScene    =
80    { &myCamera, &myViewPort, &myScissor, &myBgColor, 0, SCREEN_WD, SCREEN_HT };
81 
82 /*---------------------------------------------------------------------------*
83    Application main loop
84  *---------------------------------------------------------------------------*/
main(void)85 void    main ( void )
86 {
87     GXRenderModeObj *rmp;
88 
89     // initialize render settings and set clear color for first frame
90     DEMOInit(NULL);
91     GXInvalidateTexAll( );
92 
93     PrintIntro();
94 
95     // Perform dummy copy to clear EFB by specified color
96     GXSetCopyClear( *(myScene.bgcolor), GX_MAX_Z24 );
97     GXCopyDisp( DEMOGetCurrentBuffer(), GX_TRUE );
98 
99     myInitModel( );
100 
101     rmp = DEMOGetRenderModeObj();
102 
103     myScene.screen_wd = rmp->fbWidth;
104     myScene.screen_ht = rmp->efbHeight;
105     myViewPort.width  = (s16) myScene.screen_wd;
106     myViewPort.height = (s16) myScene.screen_ht;
107     myScissor.width   = (u16) myScene.screen_wd;
108     myScissor.height  = (u16) myScene.screen_ht;
109     ControlInit( &myScene );
110 
111     while ( ! ( DEMOPadGetButton(0) & PAD_BUTTON_MENU ) )
112     {
113         // get pad status
114         DEMOPadRead( );
115 
116         // General control & model animation
117         SceneControl( &myScene );
118         // No animation for this model.
119 
120         // Draw scene
121         DEMOBeforeRender( );
122         SceneDraw( &myScene );
123         DEMODoneRender( );
124     }
125 
126     OSHalt("End of demo");
127 }
128 
129 /*---------------------------------------------------------------------------*
130    Functions
131  *---------------------------------------------------------------------------*/
132 
133 //============================================================================
134 //  Scene
135 //============================================================================
136 
137 /*---------------------------------------------------------------------------*
138     Name:           SceneDraw
139     Description:    Draw model
140     Arguments:      Scene* s
141     Returns:        none
142  *---------------------------------------------------------------------------*/
143 static
SceneDraw(Scene * s)144 void    SceneDraw( Scene* s )
145 {
146     Camera* c  = s->camera;
147     ViewPort*   v  = s->viewport;
148     ScissorBox* si = s->scissor;
149     float       aspect = (float) (4.0 / 3.0);
150 	GXColor color1 = {255,32,32,255};
151 	GXColor color2 = {32,255,32,255};
152 
153     // Pixel processing mode
154     GXSetBlendMode( GX_BM_BLEND, GX_BL_ONE, GX_BL_ZERO, GX_LO_CLEAR );
155     GXSetZMode( GX_TRUE, GX_ALWAYS, GX_TRUE );
156 
157     // Culling mode
158     GXSetCullMode( GX_CULL_BACK );
159 
160     // Set coordinates for rectangle drawing
161     DEMOSetupScrnSpc( (s32) s->screen_wd, (s32) s->screen_ht, 100.0f );
162 
163     // Draw scissoring and viewport box
164     myDrawRectangle( (f32) si->xorg, (f32) si->yorg,
165                  (f32)(si->xorg + si->width  - 1),
166                  (f32)(si->yorg + si->height - 1),
167                  color1 );
168     myDrawRectangle( (f32) v->xorg, (f32) v->yorg,
169                  (f32)(v->xorg + v->width  - 1),
170                  (f32)(v->yorg + v->height - 1),
171                  color2 );
172 
173     // Set projection matrix
174     MTXPerspective( c->projMtx, c->fovy, aspect, c->znear, c->zfar );
175     GXSetProjection( c->projMtx, GX_PERSPECTIVE );
176 
177     // Set CameraView matrix
178     MTXLookAt( c->viewMtx, &c->position, &c->up, &c->target );
179 
180     // Set Viewport
181     GXSetViewport( v->xorg, v->yorg, v->width, v->height,
182                SCREEN_ZNEAR, SCREEN_ZFAR );
183     GXSetScissor( (u32)si->xorg, (u32)si->yorg, (u32)si->width, (u32)si->height );
184 
185     // Draw objects
186     myDrawModel( c );
187 
188     // draw information
189     SceneDrawInfo( s );
190     return;
191 }
192 
193 /*---------------------------------------------------------------------------*
194     Name:           SceneDrawInfo
195     Description:    Draw scene information
196     Arguments:
197     Returns:        none
198  *---------------------------------------------------------------------------*/
199 static
SceneDrawInfo(Scene * s)200 void    SceneDrawInfo( Scene* s )
201 {
202     ViewPort*   v  = s->viewport;
203     ScissorBox* si = s->scissor;
204     s32     x, y;
205 
206     GXSetViewport( 0, 0, (f32) s->screen_wd, (f32) s->screen_ht,
207                    SCREEN_ZNEAR, SCREEN_ZFAR );
208     GXSetScissor ( 0, 0, (u32) s->screen_wd, (u32) s->screen_ht );
209 
210     // Draw parameters to the window
211     DEMOInitCaption( DM_FT_XLU, (s32) s->screen_wd, (s32) s->screen_ht );
212     DEMOPrintf( 15, 15, 0, "Scissor(Red)    (%5d,%5d)-(%5d,%5d)",
213             si->xorg, si->yorg,
214             (u16)(si->xorg + si->width), (u16)(si->yorg + si->height) );
215     DEMOPrintf( 15, 25, 0, "ViewPort(Green) (%5d,%5d)-(%5d,%5d)",
216             v->xorg,            v->yorg,
217             v->xorg + v->width, v->yorg + v->height );
218 
219     // Draw cursor
220     switch ( s->cursor )
221     {
222       case 0:  x = si->xorg;             y = si->yorg;               break;
223       case 1:  x = si->xorg+si->width-1; y = si->yorg+si->height-1;  break;
224       case 2:  x =  v->xorg;             y =  v->yorg;               break;
225       case 3:  x =  v->xorg+v->width-1;  y =  v->yorg+v->height-1;   break;
226     }
227     DEMOPuts( (s16)(x-4), (s16)(y-5), 0, "o" );
228 
229     return;
230 }
231 
232 /*---------------------------------------------------------------------------*
233  *---------------------------------------------------------------------------*/
234 static
235 ViewPort   myView[] =
236 { { 0,           0,           SCREEN_WD*8, SCREEN_HT*8 },
237   { SCREEN_WD*1, SCREEN_HT*1, SCREEN_WD*4, SCREEN_HT*4 } };
238 
239 static
240 ScissorBox myScis[] =
241 { { 0,           0,           SCREEN_WD*8, SCREEN_HT*8   },
242   { SCREEN_WD*3, SCREEN_HT*3, SCREEN_WD*4, SCREEN_HT*4 } };
243 
244 static
245 struct {
246     ViewPort*   view;
247     ScissorBox* scis;
248 } myWinPos[] =
249   { { &myView[0], &myScis[0] },
250     { &myView[0], &myScis[1] },
251     { &myView[1], &myScis[1] },
252     { &myView[1], &myScis[0] } };
253 
254 /*---------------------------------------------------------------------------*
255     Name:           ControlInit
256     Description:    init parameter control
257     Arguments:
258     Returns:        none
259  *---------------------------------------------------------------------------*/
260 static
ControlInit(Scene * s)261 void    ControlInit( Scene* s )
262 {
263     int i;
264 
265     for(i=0; i<2; i++)
266     {
267         myView[i].xorg   *= (s16) (s->screen_wd / 8);
268         myView[i].yorg   *= (s16) (s->screen_ht / 8);
269         myView[i].width  *= (s16) (s->screen_wd / 8);
270         myView[i].height *= (s16) (s->screen_ht / 8);
271 
272         myScis[i].xorg   *= (u16) (s->screen_wd / 8);
273         myScis[i].yorg   *= (u16) (s->screen_ht / 8);
274         myScis[i].width  *= (u16) (s->screen_wd / 8);
275         myScis[i].height *= (u16) (s->screen_ht / 8);
276     }
277 }
278 
279 /*---------------------------------------------------------------------------*
280     Name:           SceneControl
281     Description:    user interface for parameter control
282     Arguments:
283     Returns:        none
284  *---------------------------------------------------------------------------*/
285 static
SceneControl(Scene * s)286 void    SceneControl( Scene* s )
287 {
288     static u32  predef = 0;
289     ViewPort*   v  = s->viewport;
290     ScissorBox* si = s->scissor;
291     s32     step, dx, dy;
292 
293     // Modify box by Button A
294     if ( DEMOPadGetButtonDown(0) & PAD_BUTTON_A )
295     {
296         predef = ( predef + 1 ) % M_NUMBEROF(myWinPos);
297 
298         *v  = *(myWinPos[predef].view);
299         *si = *(myWinPos[predef].scis);
300     }
301 
302     // Change cursor by Button B
303     if ( DEMOPadGetButtonDown(0) & PAD_BUTTON_B )
304     {
305         s->cursor = ( s->cursor + 1 ) % 4;
306     }
307 
308     // Move edge
309     step = ( DEMOPadGetButton(0) & PAD_BUTTON_X ) ? 6 : 1;
310     dy = - ( DEMOPadGetStickY(0) / 24 ) * step;
311     dx =   ( DEMOPadGetStickX(0) / 24 ) * step;
312 
313     // Get pointer for values specified by cursor
314     switch ( s->cursor )
315     {
316       case 0:   si->xorg  += dx; si->yorg   += dy;
317             si->width -= dx; si->height -= dy;  break;
318       case 1:   si->width += dx; si->height += dy;  break;
319       case 2:    v->xorg  += dx;  v->yorg   += dy;
320              v->width -= dx;  v->height -= dy;  break;
321       case 3:    v->width += dx;  v->height += dy;  break;
322     }
323 
324     Clamp(si->xorg, 0, (s32)s->screen_wd);
325     Clamp(si->yorg, 0, (s32)s->screen_ht);
326     Clamp(si->width,  0, (s32)(s->screen_wd - si->xorg));
327     Clamp(si->height, 0, (s32)(s->screen_ht - si->yorg));
328 
329     return;
330 }
331 
332 //============================================================================
333 //  Model
334 //  Rectangles
335 //============================================================================
336 typedef struct
337 {
338     f32     x, y, z;
339     f32     radius;
340     GXColor color;
341 }   MySphere;
342 
343 #define GRIDX   5
344 #define GRIDY   4
345 
346 static MySphere    mySphere[GRIDX*GRIDY];
347 static GXLightObj  myLight;
348 static Point3d     myLightPos = { 1000.0f, -1000.0f, 1000.0f }; // in world space
349 /*---------------------------------------------------------------------------*
350     Name:           myDrawModel
351     Description:    draw model
352     Arguments:      Camera *c
353     Returns:        none
354  *---------------------------------------------------------------------------*/
355 static
myInitModel(void)356 void    myInitModel( void )
357 {
358     s32     i;
359 	GXColor white = {255,255,255,255};
360 
361     GXInitLightColor( &myLight, white );
362     GXInitLightSpot( &myLight, 0.0f, GX_SP_OFF );
363     GXInitLightDistAttn( &myLight, 0.0f, 0.0f, GX_DA_OFF );
364 
365     for ( i = 0; i < M_NUMBEROF(mySphere); i ++ )
366     {
367         mySphere[i].x = (float)(((i % GRIDX) * 2 - GRIDX + 1) * 10);
368         mySphere[i].y = 90.0f;
369         mySphere[i].z = (float)(((i / GRIDX) * 2 - GRIDY + 1) * 10);
370         mySphere[i].radius = 10.0f;
371         mySphere[i].color.r = (u8)((i & 1) ? 255 : 64);
372         mySphere[i].color.g = (u8)((i & 2) ? 255 : 64);
373         mySphere[i].color.b = (u8)((i & 4) ? 255 : 64);
374         mySphere[i].color.a = 255;
375     }
376 }
377 
378 /*---------------------------------------------------------------------------*
379     Name:           myDrawModel
380     Description:    draw model
381     Arguments:      Camera *c
382     Returns:        none
383  *---------------------------------------------------------------------------*/
384 static
myDrawModel(Camera * c)385 void    myDrawModel( Camera *c )
386 {
387     Point3d lpos;
388     Mtx     mvmtx, mmtx;
389     s32     i;
390 	GXColor black = { 0, 0, 0, 0 };
391 
392     // use constant material color
393     GXSetNumChans( 1 );         // # of color channels
394     GXSetChanCtrl( GX_COLOR0,
395                GX_ENABLE,       // enable Channel
396                GX_SRC_REG,      // amb source
397                GX_SRC_REG,      // mat source
398                GX_LIGHT0,       // light mask
399                GX_DF_CLAMP,     // diffuse function
400                GX_AF_NONE );    // atten   function
401     GXSetChanCtrl( GX_ALPHA0,
402                GX_DISABLE,      // enable Channel
403                GX_SRC_REG,      // amb source
404                GX_SRC_REG,      // mat source
405                GX_LIGHT0,       // light mask
406                GX_DF_NONE,      // diffuse function
407                GX_AF_NONE );    // atten   function
408     GXSetChanAmbColor( GX_COLOR0, black );
409 
410     // Set material color to go through PE stage.
411     GXSetNumTexGens( 0 );       // # of Tex gens
412     GXSetNumTevStages( 1 );     // # of Tev Stage
413     GXSetTevOrder( GX_TEVSTAGE0,
414                    GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0 );
415     GXSetTevOp( GX_TEVSTAGE0, GX_PASSCLR );
416 
417     // set modelview matrix
418     GXSetCurrentMtx( GX_PNMTX0 );
419 
420     // set a light object
421     MTXMultVec( c->viewMtx, &myLightPos, &lpos );
422     GXInitLightPos( &myLight, lpos.x, lpos.y, lpos.z ); // in view space
423     GXLoadLightObjImm( &myLight, GX_LIGHT0 );
424 
425     // Set vtx desc and Draw primitives
426     GXClearVtxDesc( );
427     GXSetVtxDesc( GX_VA_POS, GX_DIRECT );
428     GXSetVtxDesc( GX_VA_NRM, GX_DIRECT );
429     GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );
430     GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0 );
431 
432     mmtx[0][1] = mmtx[0][2] = mmtx[1][2] = 0.0f;
433     mmtx[1][0] = mmtx[2][0] = mmtx[2][1] = 0.0f;
434     for ( i = 0; i < M_NUMBEROF(mySphere); i ++ )
435     {
436         GXSetChanMatColor( GX_COLOR0, mySphere[i].color );
437         mmtx[0][0] = mmtx[1][1] = mmtx[2][2] = mySphere[i].radius;
438         mmtx[0][3] = mySphere[i].x;
439         mmtx[1][3] = mySphere[i].y;
440         mmtx[2][3] = mySphere[i].z;
441         MTXConcat( c->viewMtx, mmtx, mvmtx );
442 
443         // Load ModelView matrix for position transformation into view space
444         GXLoadPosMtxImm( mvmtx, GX_PNMTX0 );
445 
446         // Load ModelView matrix for normal transformation into view space
447         // Note: mvmtx is uniform transform here, so that (mvmtx)^(-T) = mvmtx
448         GXLoadNrmMtxImm( mvmtx, GX_PNMTX0 );
449 
450         GXDrawSphere1(1);
451     }
452     return;
453 }
454 
455 /*---------------------------------------------------------------------------*
456     Name:           myFillRectangle
457     Description:    fill rectangle
458     Arguments:
459     Returns:        none
460  *---------------------------------------------------------------------------*/
461 static
myDrawRectangle(f32 x0,f32 y0,f32 x1,f32 y1,GXColor color)462 void    myDrawRectangle( f32 x0, f32 y0, f32 x1, f32 y1, GXColor color )
463 {
464     // Draw rectangle
465     x0 += 0.5f;     // center of pixel
466     y0 += 0.5f;
467     x1 += 0.5f;
468     y1 += 0.5f;
469 
470     // Set rendering mode
471     GXSetNumChans( 1 );         // # of color channels
472     GXSetChanCtrl( GX_COLOR0,
473                GX_FALSE,        // enable Channel
474                GX_SRC_REG,      // amb source
475                GX_SRC_REG,      // mat source
476                GX_LIGHT0,       // light mask
477                GX_DF_NONE,      // diffuse function
478                GX_AF_NONE );    // atten   function
479     GXSetChanMatColor( GX_COLOR0, color );
480 
481     GXSetNumTexGens( 0 );       // # of Tex gens
482     GXSetNumTevStages( 1 );     // # of Tev Stage
483     GXSetTevOrder( GX_TEVSTAGE0,
484                    GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0 );
485     GXSetTevOp( GX_TEVSTAGE0, GX_PASSCLR );
486 
487     // Draw rectangle
488     GXClearVtxDesc( );
489     GXSetVtxDesc( GX_VA_POS, GX_DIRECT );
490     GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );
491     GXBegin( GX_LINESTRIP, GX_VTXFMT0, 5 );
492         GXPosition3f32( x0, y0, 0.0f );
493         GXPosition3f32( x1, y0, 0.0f );
494         GXPosition3f32( x1, y1, 0.0f );
495         GXPosition3f32( x0, y1, 0.0f );
496         GXPosition3f32( x0, y0, 0.0f );
497     GXEnd( );
498     return;
499 }
500 
501 /*---------------------------------------------------------------------------*
502     Name:           PrintIntro
503 
504     Description:    Prints the directions on how to use this demo.
505 
506     Arguments:      none
507 
508     Returns:        none
509  *---------------------------------------------------------------------------*/
PrintIntro(void)510 static void PrintIntro( void )
511 {
512     OSReport("\n\n");
513     OSReport("*******************************************************\n");
514     OSReport("cul-viewport: demonstrate viewport/scissor controls\n");
515     OSReport("*******************************************************\n");
516     OSReport("to quit hit the start button\n");
517     OSReport("\n");
518     OSReport("  Stick X/Y    : drag corner of viewport/scissor window\n");
519     OSReport("  X button     : hold down to increase stick speed\n");
520     OSReport("  A button     : step through different cases\n");
521     OSReport("  B button     : move cursor\n");
522     OSReport("*******************************************************\n\n");
523 }
524 
525 /*======== End of cul-viewport.c ========*/
526