1 /*---------------------------------------------------------------------------*
2 Project: Dolphin/Revolution gx demo
3 File: lit-spot.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-spot
15 Spot light angle attenuation 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 #define NUM_LIGHTS 4
30 #define NUM_PANELTYPE 6
31 #define PANEL_ARRAY_SIZE ( 16 * 16 * 3 )
32
33 #define Clamp(val,min,max) \
34 ((val) = (((val)<(min)) ? (min) : ((val)>(max)) ? (max) : (val)))
35
36 /*---------------------------------------------------------------------------*
37 Structure definitions
38 *---------------------------------------------------------------------------*/
39 // for camera
40 typedef struct
41 {
42 Vec location;
43 Vec up;
44 Vec target;
45 f32 left;
46 f32 top;
47 f32 znear;
48 f32 zfar;
49 } CameraConfig;
50
51 typedef struct
52 {
53 CameraConfig cfg;
54 Mtx view;
55 Mtx44 proj;
56 } MyCameraObj;
57
58 // for lighting
59 typedef struct
60 {
61 f32 a0;
62 f32 a1;
63 f32 a2;
64 } AngleAttn;
65
66 typedef struct
67 {
68 GXLightObj lobj;
69 Vec pos;
70 s32 theta;
71 s32 phi;
72 u32 colorIdx;
73 u32 attnType;
74 u32 enable;
75 } MyLightObj;
76
77 typedef struct
78 {
79 MyLightObj light[NUM_LIGHTS];
80 GXAttnFn attnFunc;
81 } MyLightEnvObj;
82
83 // for model object
84 typedef struct
85 {
86 u32 type;
87 f32* posArray;
88 f32* normArray;
89 } MyTessPanelObj;
90
91 // for entire scene control
92 typedef struct
93 {
94 MyCameraObj cam;
95 MyLightEnvObj lightEnv;
96 MyTessPanelObj panel;
97 u32 cur;
98 u32 mode;
99 u32 mark;
100 } MySceneCtrlObj;
101
102 /*---------------------------------------------------------------------------*
103 Forward references
104 *---------------------------------------------------------------------------*/
105 void main ( void );
106 static void DrawInit ( MySceneCtrlObj* sc );
107 static void DrawTick ( MySceneCtrlObj* sc );
108 static void AnimTick ( MySceneCtrlObj* sc );
109 static void CreateTessPanel ( MyTessPanelObj* pnl );
110 static void DrawTessPanel ( MyTessPanelObj* pnl );
111 static void DrawLightMark ( MyLightObj* light );
112 static void SetCamera ( MyCameraObj* cam );
113 static void SetLight ( MyLightEnvObj* le, Mtx view );
114 static void DisableLight ( void );
115 static void PrintIntro ( void );
116 static void StatusMessage ( MyLightObj* light );
117
118 /*---------------------------------------------------------------------------*
119 Lighting and model parameters
120 *---------------------------------------------------------------------------*/
121 #define BLACK MyColors[4]
122 #define REG_MATERIAL MyColors[5]
123 #define REG_AMBIENT MyColors[6]
124
125 static GXColor MyColors[] ATTRIBUTE_ALIGN(32) =
126 {
127 {0xff, 0xff, 0xff, 0xff}, // white
128 {0xff, 0x00, 0x00, 0xff}, // red
129 {0x00, 0xff, 0x00, 0xff}, // green
130 {0x00, 0x00, 0xff, 0xff}, // blue
131
132 {0x00, 0x00, 0x00, 0x00}, // black
133 {0xc0, 0xc0, 0xc0, 0xff}, // material
134 {0x10, 0x10, 0x10, 0xff} // ambient
135 };
136
137 static Vec DefaultLightPos[4] =
138 {
139 { 200, 200, 450 },
140 { 200, -200, 450 },
141 { -200, -200, 450 },
142 { -200, 200, 450 }
143 };
144
145 #define NUM_OF_ATTNS 20
146 static AngleAttn LightAttnSamples[NUM_OF_ATTNS] =
147 {
148 { -9.0F, 10.0F, 0.0F },
149 { -24.0F, 25.0F, 0.0F },
150 { -49.0F, 50.0F, 0.0F },
151 { -4.0F, 5.0F, 0.0F },
152 { -18.5F, 20.0F, 0.0F },
153 { -47.0F, 50.0F, 0.0F },
154 {-299.0F, 200.0F, 100.0F },
155 { -74.0F, 50.0F, 25.0F },
156 { -26.0F, 18.0F, 9.0F },
157 { -2.0F, 2.0F, 1.0F },
158 {-297.0F, 200.0F, 100.0F },
159 { -72.5F, 50.0F, 25.0F },
160 { 0.5F, 0.5F, 0.25F },
161 { -0.5F, 2.0F, 1.0F },
162 { 1.0F, -2.0F, 1.0F },
163 { 38.5F, -40.0F, 0.0F },
164 { -17.0F, 48.0F, -32.0F },
165 { -3.0F, 8.0F, -4.0F },
166 { 0.0F, 1.0F, 0.0F },
167 { 0.5F, 0.0F, 0.0F }
168 };
169
170 /*---------------------------------------------------------------------------*
171 Camera configuration
172 *---------------------------------------------------------------------------*/
173 static CameraConfig DefaultCamera =
174 {
175 { 0.0F, 0.0F, 1200.0F }, // location
176 { 0.0F, 1.0F, 0.0F }, // up
177 { 0.0F, 0.0F, 0.0F }, // target
178 -320.0F, // left
179 240.0F, // top
180 500.0F, // near
181 2000.0F // far
182 };
183
184 /*---------------------------------------------------------------------------*
185 Strings for messages
186 *---------------------------------------------------------------------------*/
187 static char* CtrlMsg[] =
188 {
189 "White Light",
190 "Red Light",
191 "Green Light",
192 "Blue Light"
193 };
194
195 static char* ModeMsg[] =
196 {
197 "Direction & attenuation control",
198 "Position control",
199 "Camera control"
200 };
201
202 /*---------------------------------------------------------------------------*
203 Global variables
204 *---------------------------------------------------------------------------*/
205 static MySceneCtrlObj SceneCtrl;
206
207 /*---------------------------------------------------------------------------*
208 Application main loop
209 *---------------------------------------------------------------------------*/
main(void)210 void main ( void )
211 {
212 DEMOInit(NULL);
213
214 DrawInit(&SceneCtrl); // Initialize vertex formats, array
215 // and default scene settings
216
217 PrintIntro(); // Print demo directions
218
219 while(!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
220 {
221 DEMOBeforeRender();
222 DrawTick(&SceneCtrl); // Draw the model.
223 DEMODoneRender();
224 DEMOPadRead(); // Update pad status.
225 AnimTick(&SceneCtrl); // Update animation.
226 }
227
228 OSHalt("End of demo");
229 }
230
231 /*---------------------------------------------------------------------------*
232 Functions
233 *---------------------------------------------------------------------------*/
234 /*---------------------------------------------------------------------------*
235 Name: DrawInit
236
237 Description: Initializes the vertex attribute format and allocates
238 the array memory for the indexed data.
239 This function also initializes scene control parameters.
240
241 Arguments: sc : pointer to the structure of scene control parameters
242
243 Returns: none
244 *---------------------------------------------------------------------------*/
DrawInit(MySceneCtrlObj * sc)245 static void DrawInit( MySceneCtrlObj* sc )
246 {
247 u32 i;
248
249 // vertex attribute
250 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
251 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
252 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
253
254
255 // Default scene control parameter settings
256
257 // camera
258 sc->cam.cfg = DefaultCamera;
259
260 // light parameters
261 for ( i = 0 ; i < 4 ; ++i )
262 {
263 sc->lightEnv.light[i].pos = DefaultLightPos[i];
264 sc->lightEnv.light[i].theta = 0;
265 sc->lightEnv.light[i].phi = 0;
266 sc->lightEnv.light[i].attnType = 0;
267 sc->lightEnv.light[i].enable = TRUE;
268 sc->lightEnv.light[i].colorIdx = i;
269 }
270 sc->lightEnv.attnFunc = GX_AF_SPOT;
271
272 // allocate arrays
273 sc->panel.posArray = MEMAllocFromAllocator(&DemoAllocator1, PANEL_ARRAY_SIZE * sizeof(f32));
274 ASSERT( sc->panel.posArray != 0 );
275 sc->panel.normArray = MEMAllocFromAllocator(&DemoAllocator1, PANEL_ARRAY_SIZE * sizeof(f32));
276 ASSERT( sc->panel.normArray != 0 );
277 sc->panel.type = 0;
278
279 // create default panel
280 CreateTessPanel(&sc->panel);
281
282 // current control object and control mode
283 sc->cur = 0;
284 sc->mode = 0;
285 sc->mark = 1;
286 }
287
288 /*---------------------------------------------------------------------------*
289 Name: DrawTick
290
291 Description: Draw models specified by given scene control parameters.
292
293 Arguments: sc : pointer to the structure of scene control parameters
294
295 Returns: none
296 *---------------------------------------------------------------------------*/
DrawTick(MySceneCtrlObj * sc)297 static void DrawTick( MySceneCtrlObj* sc )
298 {
299 Mtx ms; // Scale matrix.
300 Mtx mt; // Translation matrix
301 Mtx mv; // Modelview matrix.
302 Mtx mvi; // Modelview matrix.
303 s32 ix, iy;
304
305 // render mode = one color / no texture
306 GXSetNumTexGens(0);
307 GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
308 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
309
310 // set camera
311 SetCamera(&sc->cam);
312
313 // set lighting
314 SetLight(&sc->lightEnv, sc->cam.view);
315
316 // draw 2x2=4 panels as a wall
317 MTXScale(ms, 400.0F, 400.0F, 120.0F);
318 for ( iy = 0 ; iy < 2 ; ++iy )
319 {
320 for ( ix = 0 ; ix < 2 ; ++ix )
321 {
322 MTXTrans(mt, ix * 400.0F - 400.0F, iy * 400.0F - 400.0F, 0.0F);
323
324 MTXConcat(sc->cam.view, mt, mv);
325 MTXConcat(mv, ms, mv);
326
327 GXLoadPosMtxImm(mv, GX_PNMTX0);
328 MTXInverse(mv, mvi);
329 MTXTranspose(mvi, mv);
330 GXLoadNrmMtxImm(mv, GX_PNMTX0);
331
332 DrawTessPanel(&sc->panel);
333 }
334 }
335
336 // turn off lighting
337 DisableLight();
338
339 // draw a light mark
340 MTXCopy(sc->cam.view, mv);
341 GXLoadPosMtxImm(mv, GX_PNMTX0);
342 MTXInverse(mv, mvi);
343 MTXTranspose(mvi, mv);
344 GXLoadNrmMtxImm(mv, GX_PNMTX0);
345
346 if ( sc->mark == 1 && sc->cur < NUM_LIGHTS )
347 {
348 DrawLightMark(&sc->lightEnv.light[sc->cur]);
349 }
350
351 }
352
353 /*---------------------------------------------------------------------------*
354 Name: AnimTick
355
356 Description: Changes scene control parameters by using pad input.
357
358 Arguments: sc : pointer to the structure of scene control parameters.
359
360 Returns: none
361 *---------------------------------------------------------------------------*/
AnimTick(MySceneCtrlObj * sc)362 static void AnimTick( MySceneCtrlObj* sc )
363 {
364 static u16 counter = 0;
365 u32 i;
366 MyLightObj* lo = sc->lightEnv.light;
367
368
369 // Frame counter
370 ++counter;
371
372 // Light Blinking Control
373 for ( i = 0 ; i < NUM_LIGHTS ; ++i )
374 {
375 lo[i].enable = TRUE;
376 }
377
378 if ( ( counter % 32 ) > 28 )
379 {
380 lo[sc->cur].enable = FALSE;
381 }
382
383 // Each light control mode
384 if ( sc->cur < NUM_LIGHTS )
385 {
386 // Direction
387 lo[sc->cur].theta += ( DEMOPadGetStickX(0) / 32 );
388 Clamp(lo[sc->cur].theta, -60, 60);
389 lo[sc->cur].phi += ( DEMOPadGetStickY(0) / 32 );
390 Clamp(lo[sc->cur].phi, -60, 60);
391
392 // Position X/Y
393 lo[sc->cur].pos.x += ( DEMOPadGetSubStickX(0) / 16 );
394 Clamp(lo[sc->cur].pos.x, -320, 320);
395 lo[sc->cur].pos.y += ( DEMOPadGetSubStickY(0) / 16 );
396 Clamp(lo[sc->cur].pos.y, -240, 240);
397
398 // Position Z
399 lo[sc->cur].pos.z += ( DEMOPadGetTriggerR(0) / 16 )
400 - ( DEMOPadGetTriggerL(0) / 16 );
401 Clamp(lo[sc->cur].pos.z, 50, 600);
402
403 // Attenuation parameter change
404 if ( DEMOPadGetButtonDown(0) & PAD_BUTTON_X )
405 {
406 lo[sc->cur].attnType =
407 ( lo[sc->cur].attnType + 1 ) % NUM_OF_ATTNS;
408 StatusMessage(&lo[sc->cur]);
409 }
410 if ( DEMOPadGetButtonDown(0) & PAD_BUTTON_Y )
411 {
412 lo[sc->cur].attnType =
413 ( lo[sc->cur].attnType + NUM_OF_ATTNS - 1 ) % NUM_OF_ATTNS;
414 StatusMessage(&lo[sc->cur]);
415 }
416 }
417 // General / camera control mode
418 else
419 {
420 // Camera calculation
421 Vec* cloc = &sc->cam.cfg.location;
422
423 cloc->x += ( DEMOPadGetStickX(0) / 16 ) * 2;
424 Clamp(cloc->x, -480, 480);
425
426 cloc->y += ( DEMOPadGetStickY(0) / 16 ) * 2;
427 Clamp(cloc->y, -320, 320);
428
429 cloc->z =
430 sqrtf( 1200 * 1200 - cloc->y * cloc->y - cloc->x * cloc->x );
431
432
433 // Spotlight attenuation ON/OFF
434 if ( DEMOPadGetButtonDown(0) & PAD_BUTTON_X )
435 {
436 sc->lightEnv.attnFunc = GX_AF_NONE;
437 OSReport("GX_AF_NONE\n");
438 }
439 if ( DEMOPadGetButtonDown(0) & PAD_BUTTON_Y )
440 {
441 sc->lightEnv.attnFunc = GX_AF_SPOT;
442 OSReport("GX_AF_SPOT\n");
443 }
444
445 // Tesselated wall type Select
446 if ( DEMOPadGetButtonDown(0) & PAD_TRIGGER_R )
447 {
448 sc->panel.type += 1;
449 sc->panel.type %= NUM_PANELTYPE;
450 CreateTessPanel(&sc->panel);
451 }
452 if ( DEMOPadGetButtonDown(0) & PAD_TRIGGER_L )
453 {
454 sc->panel.type += NUM_PANELTYPE - 1;
455 sc->panel.type %= NUM_PANELTYPE;
456 CreateTessPanel(&sc->panel);
457 }
458 }
459
460
461 // Hide light mark
462 sc->mark = (u32)(( DEMOPadGetButton(0) & PAD_BUTTON_A ) ? 0 : 1);
463
464 // Select light / camera mode
465 if ( DEMOPadGetButtonDown(0) & PAD_BUTTON_B )
466 {
467 sc->cur = ( sc->cur + 1 ) % ( NUM_LIGHTS + 1 );
468
469 if ( sc->cur < NUM_LIGHTS )
470 {
471 StatusMessage(&sc->lightEnv.light[sc->cur]);
472 }
473 else
474 {
475 OSReport("Camera mode\n");
476 }
477 }
478 }
479
480 /*---------------------------------------------------------------------------*
481 Name: CreateTessPanel
482
483 Description: Creates tesselated vertex data
484
485 Arguments: pnl : pointer to a MyTessPanelObj structure
486
487 Returns: none
488 *---------------------------------------------------------------------------*/
CreateTessPanel(MyTessPanelObj * pnl)489 static void CreateTessPanel( MyTessPanelObj* pnl )
490 {
491 u8 ix, iy;
492 u32 in;
493 f32 px, py, pz, nx, ny, nz;
494 f32 theta, phi, s;
495
496 in = 0;
497
498 for ( iy = 0 ; iy <= 15 ; ++iy )
499 {
500 py = (f32)iy / 15.0F;
501
502 for ( ix = 0 ; ix <= 15 ; ++ix )
503 {
504 px = (f32)ix / 15.0F;
505
506 switch(pnl->type)
507 {
508 case 0 : // Z = 0
509 {
510 pz = 0.0F;
511 nx = 0.0F;
512 ny = 0.0F;
513 nz = 1.0F;
514 } break;
515 case 1 : // Z = sinX
516 {
517 theta = (f32)ix * 2.0F * PI / 15.0F;
518 s = sqrtf( 1.0F + cosf(theta) * cosf(theta) );
519 pz = sinf(theta);
520 nx = - cosf(theta) / s;
521 ny = 0.0F;
522 nz = 1.0F / s;
523 } break;
524 case 2 : // Z = sin2X
525 {
526 theta = (f32)ix * 4.0F * PI / 15.0F;
527 s = sqrtf( 1.0F + cosf(theta) * cosf(theta) );
528 pz = sinf(theta);
529 nx = - cosf(theta) / s;
530 ny = 0.0F;
531 nz = 1.0F / s;
532 } break;
533 case 3 : // Z = cos2X * sinY
534 {
535 theta = (f32)ix * 4.0F * PI / 15.0F;
536 phi = (f32)iy * 2.0F * PI / 15.0F;
537 s = sqrtf( 1.0F + cosf(theta) * cosf(theta) * sinf(phi) * sinf(phi) )
538 * sqrtf( 1.0F + sinf(theta) * sinf(theta) * cosf(phi) * cosf(phi) );
539 pz = cosf(theta) * cosf(phi);
540 nx = sinf(theta) * cosf(phi) / s;
541 ny = cosf(theta) * sinf(phi) / s;
542 nz = 1.0F / s;
543 } break;
544 case 4 : // Z = (X - 0.5)^2
545 {
546 theta = (f32)ix / 15.0F - 0.5F;
547 pz = 4.0F * theta * theta;
548 s = sqrtf( 1.0F + 64.0F * theta * theta );
549 nx = - (f32)theta * 8.0F / s;
550 ny = 0.0F;
551 nz = 1.0F / s;
552 } break;
553 case 5 : // Z = - (Y - 0.5)^2
554 {
555 theta = (f32)iy / 15.0F - 0.5F;
556 pz = 0.25F - 4.0F * theta * theta;
557 s = sqrtf( 1.0F + 64.0F * theta * theta );
558 nx = 0.0F;
559 ny = (f32)theta * 8.0F / s;
560 nz = 1.0F / s;
561 } break;
562 }
563
564 pnl->posArray[in] = px;
565 pnl->posArray[in+1] = py;
566 pnl->posArray[in+2] = pz;
567 pnl->normArray[in] = nx;
568 pnl->normArray[in+1] = ny;
569 pnl->normArray[in+2] = nz;
570
571 in += 3;
572 }
573 }
574
575 // flushes all data into main memory from D-cache
576 DCFlushRange(pnl->posArray, PANEL_ARRAY_SIZE * sizeof(f32));
577 DCFlushRange(pnl->normArray, PANEL_ARRAY_SIZE * sizeof(f32));
578 // invalidates previous data existing in vertex cache
579 GXInvalidateVtxCache();
580
581 }
582
583 /*---------------------------------------------------------------------------*
584 Name: DrawTessPanel
585
586 Description: Draws panel by using tesselated vertices
587
588 Arguments: pnl : pointer to a MyTessPanelObj structure
589
590 Returns: none
591 *---------------------------------------------------------------------------*/
DrawTessPanel(MyTessPanelObj * pnl)592 static void DrawTessPanel( MyTessPanelObj* pnl )
593 {
594 u32 i, x, y;
595
596 // set up vertex descriptors
597 // since GX_INDEX8 can handle up to 255 (not 256) vertices,
598 // GX_INDEX16 is used here.
599 GXClearVtxDesc();
600 GXSetVtxDesc(GX_VA_POS, GX_INDEX16);
601 GXSetVtxDesc(GX_VA_NRM, GX_INDEX16);
602
603 // set up array pointers and strides
604 GXSetArray(GX_VA_POS, pnl->posArray, 3 * sizeof(f32));
605 GXSetArray(GX_VA_NRM, pnl->normArray, 3 * sizeof(f32));
606
607 for ( y = 0 ; y < 15 ; ++y )
608 {
609 i = y * 16;
610
611 GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT0, 32);
612 for ( x = 0 ; x < 16 ; ++x )
613 {
614 GXPosition1x16((u16)i);
615 GXNormal1x16((u16)i);
616 GXPosition1x16((u16)(i+16));
617 GXNormal1x16((u16)(i+16));
618 ++i;
619 }
620 GXEnd();
621 }
622 }
623
624 /*---------------------------------------------------------------------------*
625 Name: DrawLightMark
626
627 Description: Draws a mark which shows light position and direction.
628
629 Arguments: light: pointer to a MyLightObj structure
630
631 Returns: none
632 *---------------------------------------------------------------------------*/
DrawLightMark(MyLightObj * light)633 static void DrawLightMark( MyLightObj* light )
634 {
635 f32 theta, phi, len;
636 Vec ldir;
637
638 theta = (f32)light->theta * PI / 180.0F;
639 phi = (f32)light->phi * PI / 180.0F;
640 ldir.x = sinf(theta);
641 ldir.y = sinf(phi) * cosf(theta);
642 ldir.z = cosf(phi) * cosf(theta);
643
644 len = fabsf(light->pos.z / ldir.z);
645 ldir.x = light->pos.x + ldir.x * len;
646 ldir.y = light->pos.y + ldir.y * len;
647 ldir.z = 0;
648
649 // set up vertex descriptors
650 GXClearVtxDesc();
651 GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
652 GXSetVtxDesc(GX_VA_CLR0, GX_INDEX8);
653
654 // set up array pointers and strides
655 GXSetArray(GX_VA_CLR0, MyColors, 4 * sizeof(u8));
656
657 GXBegin(GX_LINES, GX_VTXFMT0, 8);
658 GXPosition3f32(light->pos.x, light->pos.y, 700.0F);
659 GXColor1x8((u8)light->colorIdx);
660 GXPosition3f32(light->pos.x, light->pos.y, 0.0F);
661 GXColor1x8((u8)light->colorIdx);
662
663 GXPosition3f32(light->pos.x, -480.0F, light->pos.z);
664 GXColor1x8((u8)light->colorIdx);
665 GXPosition3f32(light->pos.x, 480.0F, light->pos.z);
666 GXColor1x8((u8)light->colorIdx);
667
668 GXPosition3f32(-640.0F, light->pos.y, light->pos.z);
669 GXColor1x8((u8)light->colorIdx);
670 GXPosition3f32( 640.0F, light->pos.y, light->pos.z);
671 GXColor1x8((u8)light->colorIdx);
672
673 GXPosition3f32(light->pos.x, light->pos.y, light->pos.z);
674 GXColor1x8((u8)light->colorIdx);
675 GXPosition3f32(ldir.x, ldir.y, ldir.z);
676 GXColor1x8((u8)light->colorIdx);
677 GXEnd();
678 }
679
680 /*---------------------------------------------------------------------------*
681 Name: SetCamera
682
683 Description: set view matrix and load projection matrix into hardware
684
685 Arguments: cam : pointer to the MyCameraObj structure
686
687 Returns: none
688 *---------------------------------------------------------------------------*/
SetCamera(MyCameraObj * cam)689 static void SetCamera( MyCameraObj* cam )
690 {
691 MTXLookAt(
692 cam->view,
693 &cam->cfg.location,
694 &cam->cfg.up,
695 &cam->cfg.target );
696
697 MTXFrustum(
698 cam->proj,
699 cam->cfg.top,
700 - (cam->cfg.top),
701 cam->cfg.left,
702 - (cam->cfg.left),
703 cam->cfg.znear,
704 cam->cfg.zfar );
705 GXSetProjection(cam->proj, GX_PERSPECTIVE);
706 }
707
708 /*---------------------------------------------------------------------------*
709 Name: SetLight
710
711 Description: Sets light objects and color channels
712
713 Arguments: le : pointer to a MyLightEnvObj structure
714 view : view matrix.
715
716 Returns: none
717 *---------------------------------------------------------------------------*/
SetLight(MyLightEnvObj * le,Mtx view)718 static void SetLight( MyLightEnvObj* le, Mtx view )
719 {
720 f32 theta, phi;
721 Vec ldir, lpos;
722 AngleAttn attn;
723 u32 i;
724 u32 lmask = 0;
725
726 for ( i = 0 ; i < NUM_LIGHTS ; ++i )
727 {
728 // direction
729 theta = (f32)le->light[i].theta * PI / 180.0F;
730 phi = (f32)le->light[i].phi * PI / 180.0F;
731 ldir.x = sinf(theta);
732 ldir.y = sinf(phi) * cosf(theta);
733 ldir.z = - cosf(phi) * cosf(theta);
734
735 // convert direction into view space
736 MTXMultVecSR(view, &ldir, &ldir);
737
738 // convert position into view space
739 lpos = le->light[i].pos;
740 MTXMultVec(view, &lpos, &lpos);
741
742 // angular attenuation parameters
743 attn = LightAttnSamples[le->light[i].attnType];
744
745 // set parameters for one light
746 GXInitLightDirv(&le->light[i].lobj, &ldir);
747 GXInitLightPosv(&le->light[i].lobj, &lpos);
748 GXInitLightColor(&le->light[i].lobj, MyColors[le->light[i].colorIdx]);
749 GXInitLightAttn(
750 &le->light[i].lobj,
751 attn.a0,
752 attn.a1,
753 attn.a2,
754 1.0F,
755 0.0F,
756 0.0F );
757 }
758
759 // loads each light object
760 GXLoadLightObjImm(&le->light[0].lobj, GX_LIGHT0);
761 GXLoadLightObjImm(&le->light[1].lobj, GX_LIGHT1);
762 GXLoadLightObjImm(&le->light[2].lobj, GX_LIGHT2);
763 GXLoadLightObjImm(&le->light[3].lobj, GX_LIGHT3);
764
765 // light mask control
766 lmask = le->light[0].enable ? ( lmask | GX_LIGHT0 ) : lmask;
767 lmask = le->light[1].enable ? ( lmask | GX_LIGHT1 ) : lmask;
768 lmask = le->light[2].enable ? ( lmask | GX_LIGHT2 ) : lmask;
769 lmask = le->light[3].enable ? ( lmask | GX_LIGHT3 ) : lmask;
770
771 // channel setting
772 GXSetNumChans(1); // number of active color channels
773 GXSetChanCtrl(
774 GX_COLOR0,
775 GX_ENABLE, // enable channel
776 GX_SRC_REG, // amb source
777 GX_SRC_REG, // mat source
778 lmask, // light mask
779 GX_DF_CLAMP, // diffuse function
780 le->attnFunc); // attenuation function
781 GXSetChanCtrl(
782 GX_ALPHA0,
783 GX_DISABLE, // disable channel
784 GX_SRC_REG, // amb source
785 GX_SRC_REG, // mat source
786 0, // light mask
787 GX_DF_NONE, // diffuse function
788 GX_AF_NONE); // attenuation function
789 // set up ambient color
790 GXSetChanAmbColor(GX_COLOR0A0, REG_AMBIENT);
791 // set up material color
792 GXSetChanMatColor(GX_COLOR0A0, REG_MATERIAL);
793 }
794
795 /*---------------------------------------------------------------------------*
796 Name: DisableLight
797
798 Description: Disables lighting
799
800 Arguments: none
801
802 Returns: none
803 *---------------------------------------------------------------------------*/
DisableLight(void)804 static void DisableLight( void )
805 {
806 GXSetNumChans(1);
807 GXSetChanCtrl(
808 GX_COLOR0A0,
809 GX_DISABLE, // disable channel
810 GX_SRC_VTX, // amb source
811 GX_SRC_VTX, // mat source
812 0, // light mask
813 GX_DF_NONE, // diffuse function
814 GX_AF_NONE);
815 }
816
817 /*---------------------------------------------------------------------------*
818 Name: PrintIntro
819
820 Description: Prints the directions on how to use this demo.
821
822 Arguments: none
823
824 Returns: none
825 *---------------------------------------------------------------------------*/
PrintIntro(void)826 static void PrintIntro( void )
827 {
828 OSReport("\n\n");
829 OSReport("******************************************************\n");
830 OSReport("lit-spot: spot light angle attenuation test\n");
831 OSReport("******************************************************\n");
832 OSReport("to quit hit the start button\n");
833 OSReport("\n");
834 OSReport("B Button : Select a light or camera\n");
835 OSReport(" [each light control mode]\n");
836 OSReport("Main Stick : Change direction of selected light\n");
837 OSReport("Sub Stick : Change XY-position of selected light\n");
838 OSReport("L/R Triggers : Change Z-position of selected light\n");
839 OSReport("X/Y Buttons : Change the spotlight shape\n");
840 OSReport(" [camera control mode]\n");
841 OSReport("Main Stick : Move the camera location\n");
842 OSReport("X/Y Buttons : Enable/Disable spot function\n");
843 OSReport("L/R Triggers : Change the wall shape\n");
844 OSReport("******************************************************\n");
845 OSReport("\n");
846 }
847
848 /*---------------------------------------------------------------------------*
849 Name: StatusMessage
850
851 Description: Prints current status.
852 *---------------------------------------------------------------------------*/
StatusMessage(MyLightObj * light)853 static void StatusMessage(MyLightObj* light)
854 {
855 u32 i;
856 OSReport("%s ", CtrlMsg[light->colorIdx]);
857
858 i = light->attnType;
859 OSReport(" a0 = %f ", LightAttnSamples[i].a0);
860 OSReport(" a1 = %f ", LightAttnSamples[i].a1);
861 OSReport(" a2 = %f ", LightAttnSamples[i].a2);
862
863 OSReport("\n");
864 }
865
866 /*============================================================================*/
867