1 /*---------------------------------------------------------------------------*
2 Project: Dolphin/Revolution gx demo
3 File: lit-prelit.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-prelit
15 Vertex lighting with a prelit color
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
30 #define NUM_FAKELIGHTS 8
31 #define WALL_SIZE 64
32 #define WALL_ARRAY_SIZE ( WALL_SIZE * WALL_SIZE * 3 )
33
34 #define ALL_LIGHTS \
35 ( GX_LIGHT0 | GX_LIGHT1 | GX_LIGHT2 | GX_LIGHT3 )
36
37 /*---------------------------------------------------------------------------*
38 Structure definitions
39 *---------------------------------------------------------------------------*/
40 // for camera
41 typedef struct
42 {
43 Vec location;
44 Vec up;
45 Vec target;
46 f32 left;
47 f32 top;
48 f32 znear;
49 f32 zfar;
50 } CameraConfig;
51
52 typedef struct
53 {
54 CameraConfig cfg;
55 Mtx view;
56 Mtx44 proj;
57 } MyCameraObj;
58
59 // for lighting
60 typedef struct
61 {
62 GXLightObj lobj;
63 s32 theta;
64 s32 velocity;
65 u32 color;
66 } MyLightObj;
67
68 // for pre-lighting
69 typedef struct
70 {
71 f32 xpos;
72 f32 ypos;
73 f32 zpos;
74 f32 vx;
75 f32 vy;
76 u32 color;
77 } MyFakeLightObj;
78
79 // for entire scene control
80 typedef struct
81 {
82 MyCameraObj cam;
83 MyFakeLightObj fakeLight[NUM_FAKELIGHTS];
84 u8* preLitColor;
85 MyLightObj lightCtrl[4];
86 GXColorSrc ambSrc;
87 GXColorSrc matSrc;
88 } MySceneCtrlObj;
89
90 /*---------------------------------------------------------------------------*
91 Forward references
92 *---------------------------------------------------------------------------*/
93 void main ( void );
94 static void DrawInit ( MySceneCtrlObj* sc );
95 static void DrawTick ( MySceneCtrlObj* sc );
96 static void AnimTick ( MySceneCtrlObj* sc );
97 static void DrawWall ( void );
98 static void SetCamera ( MyCameraObj* cam );
99 static void SetLight ( MySceneCtrlObj* sc );
100 static void PreLighting ( MySceneCtrlObj* sc );
101 static void PrintIntro ( void );
102 static void StatusMessage ( MySceneCtrlObj* sc );
103
104 /*---------------------------------------------------------------------------*
105 Model and Lighting data
106 *---------------------------------------------------------------------------*/
107 #define REG_MATERIAL MyColors[12]
108 #define REG_AMBIENT MyColors[13]
109
110 static GXColor MyColors[] ATTRIBUTE_ALIGN(32) =
111 {
112 {0xc0, 0xc0, 0xc0, 0xff}, // white
113 {0xc0, 0xc0, 0x00, 0xff}, // yellow
114 {0x00, 0xc0, 0xc0, 0xff}, // cyan
115 {0xc0, 0x00, 0xc0, 0xff}, // magenta
116
117 {0xc0, 0x00, 0x00, 0xff}, // red
118 {0x00, 0xc0, 0x00, 0xff}, // green
119 {0x00, 0x00, 0xc0, 0xff}, // blue
120 {0xc0, 0x60, 0x00, 0xff}, // orange
121 {0xc0, 0x60, 0x90, 0xff}, // pink
122 {0x70, 0xc0, 0x40, 0xff}, // olive green
123 {0xc0, 0xa0, 0x70, 0xff}, // beige
124 {0x40, 0x00, 0xc0, 0xff}, // indigo
125
126 {0xe0, 0xe0, 0xe0, 0xff}, // material reg.
127 {0x40, 0x40, 0x40, 0xff}, // ambient reg.
128 };
129
130 static f32 FixedNormal[] ATTRIBUTE_ALIGN(32) =
131 { 0.0F, 0.0F, 1.0F };
132
133 static s16 LightPos[4][3] =
134 {
135 { 400, 400, 400 },
136 { 400, -400, 400 },
137 { -400, -400, 400 },
138 { -400, 400, 400 }
139 };
140
141 static Vec LightRotAxis[4] =
142 {
143 { -1.0F, 1.0F, 0.0F },
144 { 1.0F, 1.0F, 0.0F },
145 { 1.0F, -1.0F, 0.0F },
146 { -1.0F, -1.0F, 0.0F }
147 };
148
149 static MyFakeLightObj DefaultFakeLightStatus[NUM_FAKELIGHTS] =
150 {
151 // xpos ypos zpos vx vy color
152 { 24.0F, 24.0F, 4.0F, 0.4F, 0.8F, 4 },
153 { 24.0F, 40.0F, 4.5F, -0.6F, 0.2F, 5 },
154 { 40.0F, 24.0F, 5.0F, -0.5F, 0.4F, 6 },
155 { 40.0F, 40.0F, 5.5F, -0.2F, -0.7F, 7 },
156 { 32.0F, 8.0F, 6.0F, 0.3F, 0.5F, 8 },
157 { 8.0F, 32.0F, 6.5F, -0.8F, -0.2F, 9 },
158 { 56.0F, 32.0F, 7.0F, 0.4F, 0.4F, 10 },
159 { 32.0F, 56.0F, 7.5F, -0.5F, 0.0F, 11 }
160 };
161
162 #define ANGLE_ATN0 -99.0F
163 #define ANGLE_ATN1 100.0F
164 #define ANGLE_ATN2 0.0F
165
166 /*---------------------------------------------------------------------------*
167 Camera configuration
168 *---------------------------------------------------------------------------*/
169 static CameraConfig DefaultCamera =
170 {
171 { 0.0F, 0.0F, 1200.0F }, // location
172 { 0.0F, 1.0F, 0.0F }, // up
173 { 0.0F, 0.0F, 0.0F }, // target
174 -320.0F, // left
175 240.0F, // top
176 500.0F, // near
177 2000.0F // far
178 };
179
180 /*---------------------------------------------------------------------------*
181 Global variables
182 *---------------------------------------------------------------------------*/
183 static MySceneCtrlObj SceneCtrl; // scene control parameters
184
185 /*---------------------------------------------------------------------------*
186 Application main loop
187 *---------------------------------------------------------------------------*/
main(void)188 void main ( void )
189 {
190 DEMOInit(NULL); // Initialize the OS, game pad, graphics and video.
191
192 DrawInit(&SceneCtrl); // Initialize vertex formats, arrays, lights, etc.
193
194 PrintIntro(); // Print demo directions
195
196 StatusMessage(&SceneCtrl); // Print current status
197 while(!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
198 {
199 DEMOBeforeRender();
200 DrawTick(&SceneCtrl); // Draw the model.
201 DEMODoneRender();
202 DEMOPadRead(); // Update pad status.
203 AnimTick(&SceneCtrl); // Update animation.
204 }
205
206 OSHalt("End of demo");
207 }
208
209
210 /*---------------------------------------------------------------------------*
211 Functions
212 *---------------------------------------------------------------------------*/
213 /*---------------------------------------------------------------------------*
214 Name: DrawInit
215
216 Description: Initializes the vertex attribute, the array pointers
217 and strides for the indexed data and lighting parameters.
218 This function also set up modelview matrix.
219
220 Arguments: sc : pointer to the structure of scene control parameters
221
222 Returns: none
223 *---------------------------------------------------------------------------*/
DrawInit(MySceneCtrlObj * sc)224 static void DrawInit( MySceneCtrlObj* sc )
225 {
226 Mtx ms, mt, mv, mvi;
227 f32 scaling;
228 u32 i;
229
230 // sets vertex attributes
231 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_U8, 0);
232 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
233 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGB, GX_RGB8, 0);
234
235 // sets array pointers
236 sc->preLitColor = MEMAllocFromAllocator(&DemoAllocator1, WALL_ARRAY_SIZE );
237 ASSERTMSG(sc->preLitColor != 0, "Memory allocation failed.");
238
239 GXSetArray(GX_VA_CLR0, sc->preLitColor, 3*sizeof(u8));
240 GXSetArray(GX_VA_NRM, FixedNormal, 3*sizeof(f32));
241
242
243 // initialize scene control parameters
244
245 // camera
246 sc->cam.cfg = DefaultCamera;
247 SetCamera(&sc->cam); // never changes in this test
248
249 // set hardware light parameters
250 for ( i = 0 ; i < 4 ; ++i )
251 {
252 sc->lightCtrl[i].theta = 70;
253 sc->lightCtrl[i].velocity = 2;
254 sc->lightCtrl[i].color = i;
255 }
256
257 // copy default fake light parameters
258 for ( i = 0 ; i < NUM_FAKELIGHTS ; ++i )
259 {
260 sc->fakeLight[i] = DefaultFakeLightStatus[i];
261 }
262
263 // channel color source control
264 sc->ambSrc = GX_SRC_VTX;
265 sc->matSrc = GX_SRC_REG;
266
267
268 // modelview matrix is never changed in this test.
269 scaling = 800.0F / WALL_SIZE;
270 MTXScale(ms, scaling, scaling, 1.0F); // scale
271 MTXTrans(mt, -400.0F, -400.0F, 0.0F); // translation
272 MTXConcat(sc->cam.view, mt, mv);
273 MTXConcat(mv, ms, mv);
274 GXLoadPosMtxImm(mv, GX_PNMTX0);
275 MTXInverse(mv, mvi);
276 MTXTranspose(mvi, mv);
277 GXLoadNrmMtxImm(mv, GX_PNMTX0);
278 }
279
280 /*---------------------------------------------------------------------------*
281 Name: DrawTick
282
283 Description: Draw the model once.
284 GXInit makes GX_PNMTX0 the default matrix.
285
286 Arguments: sc : pointer to the structure of scene control parameters
287
288 Returns: none
289 *---------------------------------------------------------------------------*/
DrawTick(MySceneCtrlObj * sc)290 static void DrawTick( MySceneCtrlObj* sc )
291 {
292 // render mode = one color / no texture
293 GXSetNumTexGens(0);
294 GXSetNumChans(1);
295 GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
296 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
297
298 // pre-lighting
299 PreLighting(sc);
300
301 // hardware lights and channel control
302 SetLight(sc);
303
304 // sets preloaded modelview matrix and draws wall
305 GXSetCurrentMtx(GX_PNMTX0);
306 DrawWall();
307 }
308
309 /*---------------------------------------------------------------------------*
310 Name: AnimTick
311
312 Description: Moves light objects and controls scene by using pad status.
313
314 Arguments: sc : pointer to the structure of scene control parameters
315
316 Returns: none
317 *---------------------------------------------------------------------------*/
AnimTick(MySceneCtrlObj * sc)318 static void AnimTick( MySceneCtrlObj* sc )
319 {
320 u16 down = DEMOPadGetButtonDown(0);
321 u32 i;
322
323 // changes channel source setting
324 if ( down & PAD_BUTTON_A )
325 {
326 sc->ambSrc = ( sc->ambSrc == GX_SRC_REG ) ? GX_SRC_VTX : GX_SRC_REG;
327
328 if ( sc->ambSrc == GX_SRC_REG )
329 {
330 sc->matSrc = ( sc->matSrc == GX_SRC_REG ) ? GX_SRC_VTX : GX_SRC_REG;
331 }
332
333 StatusMessage(sc);
334 }
335
336 // moves fake lights
337 for ( i = 0 ; i < NUM_FAKELIGHTS ; ++i )
338 {
339 sc->fakeLight[i].xpos += sc->fakeLight[i].vx;
340 sc->fakeLight[i].ypos += sc->fakeLight[i].vy;
341
342 if ( sc->fakeLight[i].xpos < 0.0F || sc->fakeLight[i].xpos > WALL_SIZE )
343 {
344 sc->fakeLight[i].vx = - sc->fakeLight[i].vx;
345 }
346 if ( sc->fakeLight[i].ypos < 0.0F || sc->fakeLight[i].ypos > WALL_SIZE )
347 {
348 sc->fakeLight[i].vy = - sc->fakeLight[i].vy;
349 }
350 }
351
352 // moves hardware lights
353 for ( i = 0 ; i < 4 ; ++i )
354 {
355 sc->lightCtrl[i].theta += sc->lightCtrl[i].velocity;
356 if ( sc->lightCtrl[i].theta < 0 || sc->lightCtrl[i].theta > 90 )
357 {
358 sc->lightCtrl[i].velocity = - sc->lightCtrl[i].velocity;
359 }
360 }
361
362 }
363
364 /*---------------------------------------------------------------------------*
365 Name: DrawWall
366
367 Description: Draws a tessellated wall
368
369 Arguments: none
370
371 Returns: none
372 *---------------------------------------------------------------------------*/
DrawWall(void)373 static void DrawWall( void )
374 {
375 u32 x, y, i;
376
377 // sets up vertex descriptors
378 GXClearVtxDesc();
379 GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
380 GXSetVtxDesc(GX_VA_NRM, GX_INDEX8);
381 GXSetVtxDesc(GX_VA_CLR0, GX_INDEX16);
382
383 for ( y = 0 ; y < WALL_SIZE - 1 ; ++y )
384 {
385 i = y * WALL_SIZE;
386 GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT0, WALL_SIZE * 2);
387 for ( x = 0 ; x < WALL_SIZE ; ++x )
388 {
389 GXPosition3u8((u8)x, (u8)y, 0);
390 GXNormal1x8(0);
391 GXColor1x16((u16)(i+x));
392 GXPosition3u8((u8)x, (u8)(y+1), 0);
393 GXNormal1x8(0);
394 GXColor1x16((u16)(i+x+WALL_SIZE));
395 }
396 GXEnd();
397 }
398 }
399
400 /*---------------------------------------------------------------------------*
401 Name: SetCamera
402
403 Description: Sets view matrix and loads projection matrix into hardware
404
405 Arguments: cam : pointer to the MyCameraObj structure
406
407 Returns: none
408 *---------------------------------------------------------------------------*/
SetCamera(MyCameraObj * cam)409 static void SetCamera( MyCameraObj* cam )
410 {
411 MTXLookAt(
412 cam->view,
413 &cam->cfg.location,
414 &cam->cfg.up,
415 &cam->cfg.target );
416
417 MTXFrustum(
418 cam->proj,
419 cam->cfg.top,
420 - (cam->cfg.top),
421 cam->cfg.left,
422 - (cam->cfg.left),
423 cam->cfg.znear,
424 cam->cfg.zfar );
425 GXSetProjection(cam->proj, GX_PERSPECTIVE);
426 }
427
428 /*---------------------------------------------------------------------------*
429 Name: SetLight
430
431 Description: Sets hardware light objects and color channels
432
433 Arguments: sc : pointer to the structure of scene control parameters
434
435 Returns: none
436 *---------------------------------------------------------------------------*/
SetLight(MySceneCtrlObj * sc)437 void SetLight( MySceneCtrlObj* sc )
438 {
439 Mtx mr;
440 u32 i;
441
442 for ( i = 0 ; i < 4 ; ++i )
443 {
444 Vec ldir = { 0.0F, 0.0F, -1.0F };
445 Vec lpos, laxis;
446
447 // Light direction
448 laxis = LightRotAxis[i];
449 MTXRotAxisDeg(mr, &laxis, (f32)sc->lightCtrl[i].theta);
450 MTXMultVec(mr, &ldir, &ldir);
451 // convert direction into view space
452 MTXMultVecSR(sc->cam.view, &ldir, &ldir);
453
454 // Light position
455 lpos.x = (f32)LightPos[i][0];
456 lpos.y = (f32)LightPos[i][1];
457 lpos.z = (f32)LightPos[i][2];
458 // convert position into view space
459 MTXMultVec(sc->cam.view, &lpos, &lpos);
460
461 GXInitLightDirv(&sc->lightCtrl[i].lobj, &ldir);
462 GXInitLightPosv(&sc->lightCtrl[i].lobj, &lpos);
463 GXInitLightAttn(
464 &sc->lightCtrl[i].lobj,
465 ANGLE_ATN0,
466 ANGLE_ATN1,
467 ANGLE_ATN2,
468 1.0F,
469 0.0F,
470 0.0F );
471 GXInitLightColor(
472 &sc->lightCtrl[i].lobj,
473 MyColors[sc->lightCtrl[i].color] );
474 }
475
476 // loads each light object
477 GXLoadLightObjImm(&sc->lightCtrl[0].lobj, GX_LIGHT0);
478 GXLoadLightObjImm(&sc->lightCtrl[1].lobj, GX_LIGHT1);
479 GXLoadLightObjImm(&sc->lightCtrl[2].lobj, GX_LIGHT2);
480 GXLoadLightObjImm(&sc->lightCtrl[3].lobj, GX_LIGHT3);
481
482 // color channel setting
483 GXSetNumChans(1); // number of color channels
484 GXSetChanCtrl(
485 GX_COLOR0,
486 GX_ENABLE, // enable channel
487 sc->ambSrc, // amb source
488 sc->matSrc, // mat source
489 ALL_LIGHTS, // light mask
490 GX_DF_CLAMP, // diffuse function
491 GX_AF_SPOT);
492 GXSetChanCtrl(
493 GX_ALPHA0,
494 GX_DISABLE, // disable channel
495 GX_SRC_REG, // amb source
496 GX_SRC_REG, // mat source
497 0, // light mask
498 GX_DF_NONE, // diffuse function
499 GX_AF_NONE);
500 // set up material and ambient register
501 GXSetChanMatColor(GX_COLOR0A0, REG_MATERIAL);
502 GXSetChanAmbColor(GX_COLOR0A0, REG_AMBIENT);
503
504 }
505
506 /*---------------------------------------------------------------------------*
507 Name: PreLighting
508
509 Description: Creates an array of pre-lighted vertex color by
510 using fake lights.
511
512 Arguments: sc : pointer to the structure of scene control parameters
513
514 Returns: none
515 *---------------------------------------------------------------------------*/
PreLighting(MySceneCtrlObj * sc)516 static void PreLighting( MySceneCtrlObj* sc )
517 {
518 f32 x, y, z, r, g, b, dx, dy, bri;
519 u32 iv, il, col;
520
521 // calculates colors on each vertex
522 iv = 0;
523 for ( y = 0.0F ; y < (f32)WALL_SIZE ; y += 1.0F )
524 {
525 for ( x = 0.0F ; x < (f32)WALL_SIZE ; x += 1.0F )
526 {
527 r = g = b = 0.0F;
528
529 for ( il = 0 ; il < NUM_FAKELIGHTS ; ++il )
530 {
531 col = sc->fakeLight[il].color;
532 dx = sc->fakeLight[il].xpos - x;
533 dy = sc->fakeLight[il].ypos - y;
534 z = sc->fakeLight[il].zpos * sc->fakeLight[il].zpos;
535
536 bri = z / ( dx * dx + dy * dy + z );
537 r += bri * MyColors[col].r;
538 g += bri * MyColors[col].g;
539 b += bri * MyColors[col].b;
540 }
541
542 sc->preLitColor[iv] = (u8)(( r > 255.0F ) ? 255 : r);
543 sc->preLitColor[iv+1] = (u8)(( g > 255.0F ) ? 255 : g);
544 sc->preLitColor[iv+2] = (u8)(( b > 255.0F ) ? 255 : b);
545 iv += 3;
546 }
547 }
548
549 // flushes all data existing in D-cache into main memory
550 DCFlushRange(sc->preLitColor, WALL_ARRAY_SIZE);
551 // invalidates previous data existing in vertex cache
552 GXInvalidateVtxCache();
553 }
554
555 /*---------------------------------------------------------------------------*
556 Name: PrintIntro
557
558 Description: Prints the directions on how to use this demo.
559
560 Arguments: none
561
562 Returns: none
563 *---------------------------------------------------------------------------*/
PrintIntro(void)564 static void PrintIntro( void )
565 {
566 OSReport("\n\n");
567 OSReport("*****************************************\n");
568 OSReport("lit-prelit: prelit vertex lighting test\n");
569 OSReport("*****************************************\n");
570 OSReport("to quit hit the start button\n");
571 OSReport("\n");
572 OSReport("A Button : Change channel sources\n");
573 OSReport("*****************************************\n");
574 OSReport("\n");
575 }
576
577 /*---------------------------------------------------------------------------*
578 Name: StatusMessage
579
580 Description: Prints the current status of scene control.
581
582 Arguments: sc : pointer to the structure of scene control parameters
583
584 Returns: none
585 *---------------------------------------------------------------------------*/
StatusMessage(MySceneCtrlObj * sc)586 static void StatusMessage( MySceneCtrlObj* sc )
587 {
588 if ( sc->ambSrc == GX_SRC_VTX )
589 OSReport("Ambient:Vertex ");
590 else
591 OSReport("Ambient:Register");
592
593 if ( sc->matSrc == GX_SRC_VTX )
594 OSReport(" Material:Vertex ");
595 else
596 OSReport(" Material:Register");
597
598 OSReport("\n");
599 }
600
601 /*============================================================================*/
602