1 /*---------------------------------------------------------------------------*
2 Project: Dolphin/Revolution gx demo
3 File: tg-shadow.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 tg-shadow
15 Generating shadow by texture projection
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 MAX_Z 0x00ffffff // max value of Z buffer
30 #define NUM_GRIDS 7
31
32 // Since using box (mipmap) filter, actual texture size becomes
33 // quarter of source image size on framebuffer
34 #define SHADOW_TEX_SIZE 64
35 #define SHADOW_SRC_SIZE (SHADOW_TEX_SIZE * 2)
36
37 #define Clamp(val,min,max) \
38 ((val) = (((val) < (min)) ? (min) : ((val) > (max)) ? (max) : (val)))
39
40 /*---------------------------------------------------------------------------*
41 Structure definitions
42 *---------------------------------------------------------------------------*/
43 // for camera
44 typedef struct
45 {
46 Vec location;
47 Vec up;
48 Vec target;
49 f32 left;
50 f32 top;
51 f32 znear;
52 f32 zfar;
53 } CameraConfig;
54
55 typedef struct
56 {
57 CameraConfig cfg;
58 Mtx view;
59 Mtx44 proj;
60 s32 theta;
61 s32 phi;
62 f32 distance;
63 } MyCameraObj;
64
65 // for light
66 typedef struct
67 {
68 GXLightObj lobj;
69 MyCameraObj cam;
70 } MyLightObj;
71
72 // for entire scene control
73 typedef struct
74 {
75 MyCameraObj cam;
76 MyLightObj light;
77 GXTexObj shadowTex;
78 u8* shadowTexData;
79 s32 modelZ;
80 s32 modelRot;
81 u32 anim;
82 u16 screen_wd;
83 u16 screen_ht;
84 } MySceneCtrlObj;
85
86 /*---------------------------------------------------------------------------*
87 Forward references
88 *---------------------------------------------------------------------------*/
89 void main ( void );
90 static void DrawInit ( MySceneCtrlObj* sc );
91 static void DrawTick ( MySceneCtrlObj* sc );
92 static void AnimTick ( MySceneCtrlObj* sc );
93 static void DrawFloor ( void );
94 static void GetTexProjMtx ( MyCameraObj* cam, Mtx mp );
95 static void SetCamera ( MyCameraObj* cam );
96 static void SetLight ( MyLightObj* light, Mtx v );
97 static void DisableLight ( void );
98 static void PrintIntro ( void );
99
100 /*---------------------------------------------------------------------------*
101 Lighting parameters
102 *---------------------------------------------------------------------------*/
103 #define COL_WHITE MyColors[0]
104 #define COL_BG MyColors[1]
105 #define COL_AMBIENT MyColors[2]
106 #define COL_LIGHT MyColors[3]
107 #define COL_SHADOW MyColors[4]
108 #define COL_TORUS MyColors[5]
109 #define COL_FLOOR MyColors[6]
110
111 static GXColor MyColors[] ATTRIBUTE_ALIGN(32) =
112 {
113 {0xff, 0xff, 0xff, 0xff}, // white
114 {0x20, 0x20, 0x20, 0x00}, // background
115 {0x40, 0x40, 0x40, 0xff}, // ambient
116 {0xc0, 0xc0, 0xc0, 0xff}, // light color
117 {0x00, 0x00, 0x00, 0xc0}, // shadow color
118 {0x80, 0xc0, 0xff, 0xff}, // torus
119 {0xf0, 0xf0, 0xf0, 0xff} // floor
120 };
121
122 // fixed normal vector
123 static f32 FixedNormal[] ATTRIBUTE_ALIGN(32) =
124 {
125 1.0F, 0.0F, 0.0F, // X
126 0.0F, 1.0F, 0.0F, // Y
127 0.0F, 0.0F, 1.0F // Z
128 };
129
130 /*---------------------------------------------------------------------------*
131 Camera configuration
132 *---------------------------------------------------------------------------*/
133 static CameraConfig DefaultCamera =
134 {
135 { 1500.0F, 1500.0F, 400.0F }, // location
136 { 0.0F, 0.0F, 1.0F }, // up
137 { 0.0F, 0.0F, 0.0F }, // target
138 -160.0F, // left
139 120.0F, // top
140 300.0F, // near
141 5000.0F // far
142 };
143
144 static CameraConfig DefaultLightCamera =
145 {
146 { 1500.0F, 1500.0F, 2000.0F }, // location
147 { 0.0F, 0.0F, 1.0F }, // up
148 { 0.0F, 0.0F, 400.0F }, // target
149 -32.0F, // left
150 32.0F, // top
151 150.0F, // near
152 10000.0F // far
153 };
154
155 /*---------------------------------------------------------------------------*
156 Global Variables
157 *---------------------------------------------------------------------------*/
158 static MySceneCtrlObj SceneCtrl; // scene control parameters
159 static TPLPalettePtr MyTplObj = NULL;
160 static GXTexObj MyFloorTexObj;
161
162 /*---------------------------------------------------------------------------*
163 Application main loop
164 *---------------------------------------------------------------------------*/
main(void)165 void main ( void )
166 {
167 DEMOInit(NULL); // Init the OS, game pad, graphics and video.
168
169 DrawInit(&SceneCtrl); // Initialize vertex formats and scene parameters etc.
170
171 PrintIntro(); // Print demo directions
172
173 while(!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
174 {
175 DEMOBeforeRender();
176 DrawTick(&SceneCtrl); // Draw the model.
177 DEMODoneRender();
178 DEMOPadRead();
179 AnimTick(&SceneCtrl); // Update animation.
180 }
181
182 OSHalt("End of demo");
183 }
184
185 /*---------------------------------------------------------------------------*
186 Functions
187 *---------------------------------------------------------------------------*/
188 /*---------------------------------------------------------------------------*
189 Name: DrawInit
190
191 Description: Initializes the vertex attribute format, texture and
192 default scene parameters.
193
194 Arguments: sc : pointer to the structure of scene control parameters
195
196 Returns: none
197 *---------------------------------------------------------------------------*/
DrawInit(MySceneCtrlObj * sc)198 static void DrawInit( MySceneCtrlObj* sc )
199 {
200 GXRenderModeObj *rmp;
201 u32 size;
202
203 // get framebuffer size of current rendering mode
204 rmp = DEMOGetRenderModeObj();
205 sc->screen_wd = rmp->fbWidth;
206 sc->screen_ht = rmp->efbHeight;
207
208 // set up a vertex attribute
209 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S8, 0);
210 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
211 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S8, 4);
212
213 // Set pixel format with alpha
214 GXSetPixelFmt(GX_PF_RGBA6_Z24, GX_ZC_LINEAR);
215 GXSetAlphaUpdate(GX_ENABLE);
216
217 GXSetCopyClear(COL_BG, MAX_Z);
218 GXSetCullMode(GX_CULL_NONE);
219
220 // Need to clear background by specified color
221 // since pixelfmt is different than DEMOInit default.
222 // The clear operation can be done by dummy copy.
223 GXCopyDisp(DEMOGetCurrentBuffer(), GX_TRUE);
224
225 // Texture object for the floor
226 TPLGetPalette(&MyTplObj, "gxTextrs.tpl");
227 TPLGetGXTexObjFromPalette(MyTplObj, &MyFloorTexObj, 6);
228
229 // Default scene parameter settings
230
231 // camera
232 sc->cam.cfg = DefaultCamera;
233 sc->cam.theta = 45;
234 sc->cam.phi = 25;
235 sc->cam.distance = 2500.0F;
236
237 // light projection camera
238 sc->light.cam.cfg = DefaultLightCamera;
239 sc->light.cam.theta = 0;
240 sc->light.cam.phi = 60;
241 sc->light.cam.distance = 3000.0F;
242
243 // model control parameters
244 sc->modelZ = 0;
245 sc->modelRot = 0;
246 sc->anim = 1;
247
248 // Texture object for shadow
249 size = GXGetTexBufferSize(
250 SHADOW_TEX_SIZE,
251 SHADOW_TEX_SIZE,
252 GX_TF_IA4,
253 GX_FALSE,
254 0 );
255 sc->shadowTexData = MEMAllocFromAllocator(&DemoAllocator1, size);
256
257 GXInitTexObj(
258 &sc->shadowTex,
259 sc->shadowTexData,
260 SHADOW_TEX_SIZE,
261 SHADOW_TEX_SIZE,
262 GX_TF_IA4,
263 GX_CLAMP,
264 GX_CLAMP,
265 GX_FALSE );
266 GXInitTexObjLOD(
267 &sc->shadowTex,
268 GX_LINEAR,
269 GX_LINEAR,
270 0.0F,
271 0.0F,
272 0.0F,
273 GX_FALSE,
274 GX_FALSE,
275 GX_ANISO_1 );
276
277 }
278
279 /*---------------------------------------------------------------------------*
280 Name: DrawTick
281
282 Description: Draw the model by using given scene parameters
283
284 Arguments: sc : pointer to the structure of scene control parameters
285
286 Returns: none
287 *---------------------------------------------------------------------------*/
DrawTick(MySceneCtrlObj * sc)288 static void DrawTick( MySceneCtrlObj* sc )
289 {
290 static u16 count = 0;
291 Mtx ms, mt, mv, mvi, mtr;
292 f32 tr, zt;
293
294 GXInvalidateTexAll();
295
296 // Modelview matrix for torus object
297 zt = 100.0F * sinf(sc->modelZ * PI / 180.0F) + 500.0F;
298 MTXTrans(mt, 100.0F, 100.0F, zt);
299 MTXScale(ms, 300.0F, 300.0F, 300.0F);
300 MTXConcat(mt, ms, mtr);
301 MTXRotDeg(ms, 'z', sc->modelRot);
302 MTXConcat(mtr, ms, mtr);
303 MTXRotDeg(ms, 'x', 90);
304 MTXConcat(mtr, ms, mtr);
305
306 //-------------------------------------------
307 // Make Shadow Texture
308 //-------------------------------------------
309
310 // Set viewport/camera/light for making shadow texture
311 GXSetViewport(0, 0, SHADOW_SRC_SIZE, SHADOW_SRC_SIZE, 0.0F, 1.0F);
312 SetCamera(&sc->light.cam);
313 DisableLight();
314 // Set tev to use only one vertex color
315 GXSetNumChans(1);
316 GXSetNumTevStages(1);
317 GXSetNumTexGens(0);
318 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
319 GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
320
321 // Draw torus object for shadow texture
322 GXSetChanMatColor(GX_COLOR0A0, COL_SHADOW);
323
324 MTXConcat(sc->light.cam.view, mtr, mv);
325 GXLoadPosMtxImm(mv, GX_PNMTX0);
326 MTXInverse(mv, mvi);
327 MTXTranspose(mvi, mv);
328 GXLoadNrmMtxImm(mv, GX_PNMTX0);
329
330 GXDrawTorus(0.20F, 12, 16);
331
332 //-------------------------------------------
333 // Copy Shadow Image into Texture
334 //-------------------------------------------
335
336 // Don't need to flush pixel pipe here since PE does the copy
337 // and it can't start the copy until it's done rendering anyway
338
339 // Copy shadow image into texture
340 GXSetTexCopySrc(0, 0, SHADOW_SRC_SIZE, SHADOW_SRC_SIZE);
341 GXSetTexCopyDst(SHADOW_TEX_SIZE, SHADOW_TEX_SIZE, GX_TF_IA4, GX_TRUE);
342 GXCopyTex(sc->shadowTexData, GX_TRUE);
343
344 // Wait for finishing the copy task in the graphics pipeline
345 GXPixModeSync();
346
347 //-------------------------------------------
348 // Make Main Image
349 //-------------------------------------------
350
351 // Set viewport/camera/light for the main image
352 GXSetViewport(0, 0, sc->screen_wd, sc->screen_ht, 0.0F, 1.0F);
353 SetCamera(&sc->cam);
354 SetLight(&sc->light, sc->cam.view);
355
356 // for the torus object
357 GXSetChanMatColor(GX_COLOR0A0, COL_TORUS);
358
359 MTXConcat(sc->cam.view, mtr, mv);
360 GXLoadPosMtxImm(mv, GX_PNMTX0);
361 MTXInverse(mv, mvi);
362 MTXTranspose(mvi, mv);
363 GXLoadNrmMtxImm(mv, GX_PNMTX0);
364
365 // Draw a torus
366 GXDrawTorus(0.20F, 12, 16);
367
368 // Now get ready to draw floor
369 // Set tev to display multi texture
370 GXSetNumTevStages(2);
371 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
372 GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1, GX_TEXMAP1, GX_COLOR0A0);
373 GXSetTevOp(GX_TEVSTAGE0, GX_MODULATE);
374 GXSetTevOp(GX_TEVSTAGE1, GX_DECAL);
375
376 // Set texgen (TEXCOORD0 is default setting)
377 GXSetNumTexGens(2);
378 GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
379 GXSetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX3x4, GX_TG_POS, GX_TEXMTX1);
380
381 // Textures for floor panels
382 GXLoadTexObj(&MyFloorTexObj, GX_TEXMAP0);
383 GXLoadTexObj(&sc->shadowTex, GX_TEXMAP1);
384 GXSetChanMatColor(GX_COLOR0A0, COL_FLOOR);
385
386 // Modelview matrix for floor panels
387 tr = -(f32)NUM_GRIDS / 2.0F;
388 MTXScale(ms, 200.0F, 200.0F, 50.0F);
389 MTXTrans(mt, tr, tr, 0.0F);
390 MTXConcat(ms, mt, ms);
391 MTXConcat(sc->cam.view, ms, mv);
392 GXLoadPosMtxImm(mv, GX_PNMTX0);
393 MTXInverse(mv, mvi);
394 MTXTranspose(mvi, mv);
395 GXLoadNrmMtxImm(mv, GX_PNMTX0);
396
397 // Projection matrix for texture coordinate generation
398 GetTexProjMtx(&sc->light.cam, mv);
399 MTXConcat(mv, ms, mv);
400 GXLoadTexMtxImm(mv, GX_TEXMTX1, GX_MTX3x4);
401
402 // Draw floor panels
403 DrawFloor();
404 }
405
406 /*---------------------------------------------------------------------------*
407 Name: AnimTick
408
409 Description: Changes scene parameters according to the pad status.
410
411 Arguments: sc : pointer to the structure of scene control parameters
412
413 Returns: none
414 *---------------------------------------------------------------------------*/
AnimTick(MySceneCtrlObj * sc)415 static void AnimTick( MySceneCtrlObj* sc )
416 {
417 // Camera position
418 sc->cam.theta += ( DEMOPadGetStickX(0) / 24 );
419 Clamp(sc->cam.theta, 0, 90);
420 sc->cam.phi += ( DEMOPadGetStickY(0) / 24 );
421 Clamp(sc->cam.phi, 10, 60);
422
423 // Light position
424 sc->light.cam.theta += ( DEMOPadGetSubStickX(0) / 24 );
425 if ( sc->light.cam.theta > 360 )
426 {
427 sc->light.cam.theta -= 360;
428 }
429 if ( sc->light.cam.theta < 0 )
430 {
431 sc->light.cam.theta += 360;
432 }
433 sc->light.cam.phi += ( DEMOPadGetSubStickY(0) / 24 );
434 Clamp(sc->light.cam.phi, 15, 85);
435
436 // Moves the model automatically
437 if (sc->anim)
438 {
439 sc->modelZ += 5;
440 if ( sc->modelZ > 360 )
441 {
442 sc->modelZ -= 360;
443 }
444
445 sc->modelRot += 8;
446 if ( sc->modelRot > 360 )
447 {
448 sc->modelRot -= 360;
449 }
450 }
451
452 if ( DEMOPadGetButtonDown(0) & PAD_BUTTON_A )
453 {
454 sc->anim = 1 - sc->anim;
455 }
456 }
457
458 /*---------------------------------------------------------------------------*
459 Name: DrawFloor
460
461 Description: Draws the floor which contains some steps
462
463 Arguments: none
464
465 Returns: none
466 *---------------------------------------------------------------------------*/
DrawFloor(void)467 static void DrawFloor( void )
468 {
469 s8 x, y, z;
470
471 // set up vertex descriptors
472 GXClearVtxDesc();
473 GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
474 GXSetVtxDesc(GX_VA_NRM, GX_INDEX8);
475 GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
476
477 // normal array
478 GXSetArray(GX_VA_NRM, FixedNormal, 3 * sizeof(f32));
479
480 z = 0;
481 for ( y = 0 ; y < NUM_GRIDS ; ++y )
482 {
483 GXBegin(GX_QUADS, GX_VTXFMT0, NUM_GRIDS * 12);
484 for ( x = 0 ; x < NUM_GRIDS ; ++x )
485 {
486 z = (s8)(NUM_GRIDS - x - y);
487
488 // Z side
489 GXPosition3s8(x, y, z);
490 GXNormal1x8(2);
491 GXTexCoord2s8(0, 0);
492 GXPosition3s8((s8)(x+1), y, z);
493 GXNormal1x8(2);
494 GXTexCoord2s8(0x10, 0);
495 GXPosition3s8((s8)(x+1), (s8)(y+1), z);
496 GXNormal1x8(2);
497 GXTexCoord2s8(0x10, 0x10);
498 GXPosition3s8(x, (s8)(y+1), z);
499 GXNormal1x8(2);
500 GXTexCoord2s8(0, 0x10);
501
502 // X side
503 GXPosition3s8((s8)(x+1), y, z);
504 GXNormal1x8(0);
505 GXTexCoord2s8(0, 0);
506 GXPosition3s8((s8)(x+1), (s8)(y+1), z);
507 GXNormal1x8(0);
508 GXTexCoord2s8(0x10, 0);
509 GXPosition3s8((s8)(x+1), (s8)(y+1), (s8)(z-1));
510 GXNormal1x8(0);
511 GXTexCoord2s8(0x10, 0x8);
512 GXPosition3s8((s8)(x+1), y, (s8)(z-1));
513 GXNormal1x8(0);
514 GXTexCoord2s8(0, 0x8);
515
516 // Y side
517 GXPosition3s8((s8)(x+1), (s8)(y+1), z);
518 GXNormal1x8(1);
519 GXTexCoord2s8(0, 0);
520 GXPosition3s8(x, (s8)(y+1), z);
521 GXNormal1x8(1);
522 GXTexCoord2s8(0x10, 0);
523 GXPosition3s8(x, (s8)(y+1), (s8)(z-1));
524 GXNormal1x8(1);
525 GXTexCoord2s8(0x10, 0x8);
526 GXPosition3s8((s8)(x+1), (s8)(y+1), (s8)(z-1));
527 GXNormal1x8(1);
528 GXTexCoord2s8(0, 0x8);
529 }
530 GXEnd();
531 }
532 }
533
534 /*---------------------------------------------------------------------------*
535 Name: GetTexProjMtx
536
537 Description: sets texture coord generation matrix for shadow texture
538
539 Arguments: cam : pointer to the MyCameraObj structure
540 mp : a matrix the result should be set
541
542 Returns: none
543 *---------------------------------------------------------------------------*/
GetTexProjMtx(MyCameraObj * cam,Mtx mp)544 static void GetTexProjMtx( MyCameraObj* cam, Mtx mp )
545 {
546 Mtx proj;
547
548 MTXLightFrustum(
549 proj,
550 - (cam->cfg.top), // t = -y in projected texture
551 cam->cfg.top,
552 cam->cfg.left,
553 - (cam->cfg.left),
554 cam->cfg.znear,
555 0.5F,
556 0.5F,
557 0.5F,
558 0.5F );
559 MTXConcat(proj, cam->view, mp);
560 }
561
562 /*---------------------------------------------------------------------------*
563 Name: SetCamera
564
565 Description: set view matrix and load projection matrix into hardware
566
567 Arguments: cam : pointer to the MyCameraObj structure
568
569 Returns: none
570 *---------------------------------------------------------------------------*/
SetCamera(MyCameraObj * cam)571 static void SetCamera( MyCameraObj* cam )
572 {
573 f32 r_theta, r_phi;
574
575 r_theta = (f32)cam->theta * PI / 180.0F;
576 r_phi = (f32)cam->phi * PI / 180.0F;
577
578 cam->cfg.location.x =
579 cam->distance * cosf(r_theta) * cosf(r_phi);
580 cam->cfg.location.y =
581 cam->distance * sinf(r_theta) * cosf(r_phi);
582 cam->cfg.location.z =
583 cam->distance * sinf(r_phi);
584
585 MTXLookAt(
586 cam->view,
587 &cam->cfg.location,
588 &cam->cfg.up,
589 &cam->cfg.target );
590
591 MTXFrustum(
592 cam->proj,
593 cam->cfg.top,
594 - (cam->cfg.top),
595 cam->cfg.left,
596 - (cam->cfg.left),
597 cam->cfg.znear,
598 cam->cfg.zfar );
599 GXSetProjection(cam->proj, GX_PERSPECTIVE);
600 }
601
602 /*---------------------------------------------------------------------------*
603 Name: SetLight
604
605 Description: Set up lights and lighting channel parameters
606
607 Arguments: light : pointer to a MyLightObj structure
608 v : view matrix
609
610 Returns: none
611 *---------------------------------------------------------------------------*/
SetLight(MyLightObj * light,Mtx v)612 void SetLight( MyLightObj* light, Mtx v )
613 {
614 Vec lpos = light->cam.cfg.location;
615
616 // Multiplied by view matrix
617 MTXMultVec(v, &lpos, &lpos);
618
619 GXInitLightPos(&light->lobj, lpos.x, lpos.y, lpos.z);
620 GXInitLightColor(&light->lobj, COL_LIGHT);
621 GXLoadLightObjImm(&light->lobj, GX_LIGHT0);
622
623 GXSetChanCtrl(
624 GX_COLOR0A0,
625 GX_ENABLE, // enable channel
626 GX_SRC_REG, // amb source
627 GX_SRC_REG, // mat source
628 GX_LIGHT0, // light mask
629 GX_DF_CLAMP, // diffuse function
630 GX_AF_NONE );
631 // set up material color
632 GXSetChanAmbColor(GX_COLOR0A0, COL_AMBIENT);
633 }
634
635 /*---------------------------------------------------------------------------*
636 Name: DisableLight
637
638 Description: Disables lighting
639
640 Arguments: none
641
642 Returns: none
643 *---------------------------------------------------------------------------*/
DisableLight(void)644 void DisableLight( void )
645 {
646 GXSetChanCtrl(
647 GX_COLOR0A0,
648 GX_DISABLE, // disable channel
649 GX_SRC_REG, // amb source
650 GX_SRC_REG, // mat source
651 GX_LIGHT0, // light mask
652 GX_DF_NONE, // diffuse function
653 GX_AF_NONE);
654 }
655
656 /*---------------------------------------------------------------------------*
657 Name: PrintIntro
658
659 Description: Prints the directions on how to use this demo.
660
661 Arguments: none
662
663 Returns: none
664 *---------------------------------------------------------------------------*/
PrintIntro(void)665 static void PrintIntro( void )
666 {
667 OSReport("\n\n");
668 OSReport("******************************************************\n");
669 OSReport("tg-shadow: generating shadow by texture projection\n");
670 OSReport("******************************************************\n");
671 OSReport("to quit hit the start button\n");
672 OSReport("\n");
673 OSReport("Main stick : Move the camera\n");
674 OSReport("Sub stick : Move the light\n");
675 OSReport("A Button : Stop/Start animation\n");
676 OSReport("******************************************************\n");
677 OSReport("\n\n");
678 }
679
680 /*============================================================================*/
681