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