1 /*---------------------------------------------------------------------------*
2 Project: Dolphin/Revolution gx demo
3 File: tg-project.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 #include <demo.h>
15 #include <math.h>
16
17 /*---------------------------------------------------------------------------*
18 Forward references
19 *---------------------------------------------------------------------------*/
20
21 void main ( void );
22
23 static void CameraInit ( Mtx v );
24 static void ViewInit ( Mtx v );
25 static void DrawInit ( void );
26 static void DrawTick ( void );
27 static void VertexLightInit ( void );
28
29 static void MakeModelMtx ( Vec xAxis, Vec yAxis, Vec zAxis, Mtx m );
30 static void AnimTick ( Mtx v );
31
32 static void DrawFrust ( void );
33
34 static void TextureLightInit( Mtx rot );
35
36 /*---------------------------------------------------------------------------*
37 Global variables
38 *---------------------------------------------------------------------------*/
39 // Vectors to keep track of the camera's coordinate system orientation
40 Vec CamX = {1.0F, 0.0F, 0.0F};
41 Vec CamY = {0.0F, 1.0F, 0.0F};
42 Vec CamZ = {0.0F, 0.0F, 1.0F};
43
44 Vec LightY = {0.0F, 1.0F, 0.0F};
45 Vec LightX = {1.0F, 0.0F, 0.0F};
46 Vec LightZ = {0.0F, 0.0F, 1.0F};
47
48 Mtx v, m;
49
50 // Scale for the camera's distance from the object
51 float CameraLocScale = 10;
52
53 Mtx lv;
54
55 float xmin = -.5F, xmax = .5F;
56 float ymin = -.5F, ymax = .5F;
57 float nnear = 5.0F;
58 float ffar = 100.0F;
59 float distance = -45.0F;
60
61 u8 CurrentControl = 0;
62 u8 CurrentModel = 0;
63 u8 CurrentTexture = 0;
64 GXTevMode CurrentTevMode = GX_DECAL;
65
66 TPLPalettePtr tpl = 0;
67
68 /*---------------------------------------------------------------------------*
69 Application main loop
70 *---------------------------------------------------------------------------*/
main(void)71 void main ( void )
72 {
73 DEMOInit(NULL);
74
75 OSReport("\n\n");
76 OSReport("**********************************************\n");
77 OSReport("tg-project: Texture Projection demo\n");
78 OSReport("**********************************************\n");
79 OSReport("To quit hit the start button.\n");
80 OSReport("\n");
81 OSReport("X button toggles the control mode.\n");
82 OSReport("Camera Control: Main stick moves camera.\n");
83 OSReport(" A/Y buttons zoom camera.\n");
84 OSReport("Light Position: Main stick moves light.\n");
85 OSReport(" A/Y buttons zoom light.\n");
86 OSReport("Light Parameter: Main stick controls light FOV.\n");
87 OSReport("Model Select: B button changes model.\n");
88 OSReport("Texture Select: B button changes the texture.\n");
89 OSReport("**********************************************\n");
90 OSReport("\n\n");
91
92 DrawInit(); // Define my vertex formats and set array pointers.
93
94 VertexLightInit();
95
96 DEMOPadRead(); // Read the joystick for this frame
97
98 // While the quit button is not pressed
99 while(!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
100 {
101 DEMOPadRead(); // Read the joystick for this frame
102
103 // Do animation based on input
104 AnimTick(v);
105 DEMOBeforeRender();
106
107 DrawTick(); // Draw the model.
108
109 DEMODoneRender();
110 }
111
112 OSHalt("End of demo");
113 }
114
115 /*---------------------------------------------------------------------------*
116 Functions
117 *---------------------------------------------------------------------------*/
118
119
120 /*---------------------------------------------------------------------------*
121 Name: CameraInit
122
123 Description: Initialize the projection matrix and load into hardware.
124
125 Arguments: v view matrix to be passed to ViewInit
126 cameraLocScale scale for the camera's distance from the
127 object - to be passed to ViewInit
128
129 Returns: none
130 *---------------------------------------------------------------------------*/
CameraInit(Mtx v)131 static void CameraInit ( Mtx v )
132 {
133 Mtx44 p;
134
135 MTXFrustum(p, .24F * CameraLocScale,-.24F * CameraLocScale,
136 -.32F * CameraLocScale, .32F * CameraLocScale,
137 .5F * CameraLocScale, 20.0F * CameraLocScale);
138
139 GXSetProjection(p, GX_PERSPECTIVE);
140
141 ViewInit(v);
142 }
143
144 /*---------------------------------------------------------------------------*
145 Name: ViewInit
146
147 Description: Initialize the view matrix.
148
149 Arguments: v view matrix
150 cameraLocScale value used to determine camera's distance
151 from the object
152
153 Returns: none
154 *---------------------------------------------------------------------------*/
ViewInit(Mtx v)155 static void ViewInit ( Mtx v )
156 {
157 Vec camPt = {0.0F, 0.0F, 8.0F};
158 Vec up = {0.0F, 1.0F, 0.0F};
159 Vec origin = {0.0F, 0.0F, 0.0F};
160
161 camPt.x *= CameraLocScale; // Scale camPt by cameraLocScale
162 camPt.y *= CameraLocScale;
163 camPt.z *= CameraLocScale;
164
165 MTXLookAt(v, &camPt, &up, &origin);
166 }
167
168
169 /*---------------------------------------------------------------------------*
170 Name: DrawInit
171
172 Description: Calls the correct initialization function for the current
173 model.
174
175 Arguments: none
176
177 Returns: none
178 *---------------------------------------------------------------------------*/
DrawInit(void)179 static void DrawInit( void )
180 {
181 GXTexObj to;
182 TPLDescriptorPtr tdp;
183
184 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
185 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
186
187 GXClearVtxDesc();
188 GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
189 GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
190
191 CameraInit(v); // Re-Initialize the camera.
192
193 GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX3x4, GX_TG_POS, GX_TEXMTX0);
194 GXSetNumChans(1);
195
196 TPLGetPalette(&tpl, "gxTests/tg-01.tpl");
197 tdp = TPLGet(tpl, 0);
198
199 GXInitTexObj(&to,
200 tdp->textureHeader->data,
201 tdp->textureHeader->width,
202 tdp->textureHeader->height,
203 (GXTexFmt)tdp->textureHeader->format,
204 GX_CLAMP,
205 GX_CLAMP,
206 GX_FALSE);
207
208 GXInitTexObjLOD(&to,
209 tdp->textureHeader->minFilter,
210 tdp->textureHeader->magFilter,
211 tdp->textureHeader->minLOD,
212 tdp->textureHeader->maxLOD,
213 tdp->textureHeader->LODBias,
214 GX_FALSE,
215 tdp->textureHeader->edgeLODEnable,
216 GX_ANISO_1);
217
218 GXLoadTexObj(&to, GX_TEXMAP0);
219
220 MTXScale(m, 20.0F, 20.0F, 20.0F);
221 }
222
223 /*---------------------------------------------------------------------------*
224 Name: DrawTick
225
226 Description: Draw the current model once.
227
228 Arguments: v view matrix
229 m model matrix
230
231 Returns: none
232 *---------------------------------------------------------------------------*/
DrawTick(void)233 static void DrawTick( void )
234 {
235 Mtx mv;
236
237 GXSetTevOp(GX_TEVSTAGE0, CurrentTevMode);
238 GXSetNumTexGens(1);
239 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
240
241 GXSetChanCtrl(
242 GX_COLOR0,
243 TRUE, // enable channel
244 GX_SRC_REG, // amb source
245 GX_SRC_REG, // mat source
246 GX_LIGHT0, // light mask
247 GX_DF_CLAMP, // diffuse function
248 GX_AF_NONE);
249
250 MTXConcat(v, m, mv);
251 GXLoadPosMtxImm(mv, GX_PNMTX0);
252 MTXInverse(mv, mv);
253 MTXTranspose(mv, mv);
254 GXLoadNrmMtxImm(mv, GX_PNMTX0);
255 switch(CurrentModel)
256 {
257 case 0:
258 GXDrawCube();
259 break;
260 case 1:
261 GXDrawDodeca();
262 break;
263 case 2:
264 GXDrawCylinder(20);
265 break;
266 case 3:
267 GXDrawSphere1(3);
268 break;
269 case 4:
270 GXDrawOctahedron();
271 break;
272 case 5:
273 GXDrawIcosahedron();
274 break;
275 case 6:
276 GXDrawTorus(.3F, 10, 50);
277 break;
278 }
279
280 GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
281 GXSetNumTexGens(0);
282 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
283 GXSetChanCtrl(
284 GX_COLOR0,
285 FALSE, // disable channel
286 GX_SRC_VTX, // amb source
287 GX_SRC_VTX, // mat source
288 GX_LIGHT0, // light mask
289 GX_DF_CLAMP, // diffuse function
290 GX_AF_NONE);
291 DrawFrust();
292 }
293
VertexLightInit(void)294 static void VertexLightInit ( void )
295 {
296 GXLightObj MyLight;
297 GXColor color = {255, 255, 255, 255};
298
299 GXInitLightPos(&MyLight, 0.0F, 0.0F, 0.0F);
300 GXInitLightColor(&MyLight, color);
301 GXLoadLightObjImm(&MyLight, GX_LIGHT0);
302
303 color.g = color.b = 0;
304 GXSetChanMatColor(GX_COLOR0, color);
305 }
306
307 /*---------------------------------------------------------------------------*
308 Name: MakeModelMtx
309
310 Description: computes a model matrix from 3 vectors representing an
311 object's coordinate system.
312
313 Arguments: xAxis vector for the object's X axis
314 yAxis vector for the object's Y axis
315 zAxis vector for the object's Z axis
316
317 Returns: none
318 *---------------------------------------------------------------------------*/
MakeModelMtx(Vec xAxis,Vec yAxis,Vec zAxis,Mtx m)319 static void MakeModelMtx ( Vec xAxis, Vec yAxis, Vec zAxis, Mtx m )
320 {
321 VECNormalize(&xAxis,&xAxis);
322 VECNormalize(&yAxis,&yAxis);
323 VECNormalize(&zAxis, &zAxis);
324
325 m[0][0] = xAxis.x;
326 m[1][0] = xAxis.y;
327 m[2][0] = xAxis.z;
328
329 m[0][1] = yAxis.x;
330 m[1][1] = yAxis.y;
331 m[2][1] = yAxis.z;
332
333 m[0][2] = zAxis.x;
334 m[1][2] = zAxis.y;
335 m[2][2] = zAxis.z;
336
337 m[0][3] = 0.0F;
338 m[1][3] = 0.0F;
339 m[2][3] = 0.0F;
340 }
341
342 /*---------------------------------------------------------------------------*
343 Name: AnimTick
344
345 Description: Animates the camera and object based on the joystick's
346 state.
347
348 Arguments: m model matrix
349 v view matrix
350 cameraLocScale scale value for the camera's distance
351 to the object.
352
353 Returns: none
354 *---------------------------------------------------------------------------*/
AnimTick(Mtx v)355 static void AnimTick ( Mtx v )
356 {
357 Mtx rot;
358 GXTexObj to;
359 TPLDescriptorPtr tdp;
360
361 u16 buttons = DEMOPadGetButton(0);
362 u16 downs = DEMOPadGetButtonDown(0);
363 s8 stickX = DEMOPadGetStickX(0);
364 s8 stickY = DEMOPadGetStickY(0);
365
366 if(downs & PAD_BUTTON_X)
367 {
368 CurrentControl ++;
369 if(CurrentControl > 4)
370 CurrentControl = 0;
371
372 switch(CurrentControl)
373 {
374 case 0:
375 OSReport("\n\nCamera Control\n\n");
376 break;
377 case 1:
378 OSReport("\n\nLight Position Control\n\n");
379 break;
380 case 2:
381 OSReport("\n\nLight Parameter Control\n\n");
382 break;
383 case 3:
384 OSReport("\n\nModel Select Control\n\n");
385 break;
386 case 4:
387 OSReport("\n\nTexture Select Control\n\n");
388 break;
389 }
390 }
391 if(CurrentControl == 0)
392 {
393 // Move camera
394 if(buttons & PAD_BUTTON_Y)
395 {
396 CameraLocScale *= .95F;
397 if(CameraLocScale < 0.001F)
398 CameraLocScale = 0.001F;
399 }
400 if(buttons & PAD_BUTTON_A)
401 CameraLocScale *= 1.05F;
402
403 // Rotate camera
404 if(stickX || stickY)
405 {
406 if(stickX)
407 {
408 if(stickX > 0)
409 MTXRotAxisDeg(rot, &CamY, 3.0F);
410 else
411 MTXRotAxisDeg(rot, &CamY, -3.0F);
412
413 MTXMultVec(rot, &CamX, &CamX);
414 MTXMultVec(rot, &CamZ, &CamZ);
415 }
416
417 if(stickY)
418 {
419 if(stickY > 0)
420 MTXRotAxisDeg(rot, &CamX, 3.0F);
421 else
422 MTXRotAxisDeg(rot, &CamX, -3.0F);
423
424 MTXMultVec(rot, &CamY, &CamY);
425 MTXMultVec(rot, &CamZ, &CamZ);
426 }
427 }
428 }
429 else if(CurrentControl == 1)
430 {
431 // Rotate light
432 if(stickX || stickY)
433 {
434 if(stickX)
435 {
436 if(stickX > 0)
437 MTXRotAxisDeg(rot, &CamY, 3.0F);
438 else
439 MTXRotAxisDeg(rot, &CamY, -3.0F);
440
441 MTXMultVec(rot, &LightX, &LightX);
442 MTXMultVec(rot, &LightY, &LightY);
443 MTXMultVec(rot, &LightZ, &LightZ);
444 }
445
446 if(stickY)
447 {
448 if(stickY > 0)
449 MTXRotAxisDeg(rot, &CamX, 3.0F);
450 else
451 MTXRotAxisDeg(rot, &CamX, -3.0F);
452
453 MTXMultVec(rot, &LightX, &LightX);
454 MTXMultVec(rot, &LightY, &LightY);
455 MTXMultVec(rot, &LightZ, &LightZ);
456 }
457 }
458 if(buttons & PAD_BUTTON_Y)
459 {
460 distance *= .95F;
461 if(distance > -0.001F)
462 distance = -0.001F;
463 }
464 if(buttons & PAD_BUTTON_A)
465 distance *= 1.05F;
466 }
467 else if(CurrentControl == 2)
468 {
469 if(stickY > 0)
470 {
471 xmax *= .95F;
472 if(xmax < 0.0001F)
473 xmax = 0.0001F;
474 ymin = -xmax;
475 ymax = xmax;
476 xmin = -xmax;
477 }
478 if(stickY < 0)
479 {
480 xmax *= 1.05F;
481 ymin = -xmax;
482 ymax = xmax;
483 xmin = -xmax;
484 }
485 }
486 else if(CurrentControl == 3)
487 {
488 if(downs & PAD_BUTTON_B)
489 {
490 CurrentModel ++;
491 if(CurrentModel > 6)
492 CurrentModel = 0;
493 }
494 }
495 else if(CurrentControl == 4)
496 {
497 if(downs & PAD_BUTTON_B)
498 {
499 CurrentTexture ++;
500 if(CurrentTexture > 1)
501 CurrentTexture = 0;
502 switch(CurrentTexture)
503 {
504 case 1:
505 CurrentTevMode = GX_MODULATE;
506 break;
507 case 0:
508 CurrentTevMode = GX_DECAL;
509 break;
510 }
511 tdp = TPLGet(tpl, CurrentTexture);
512
513 GXInitTexObj(&to,
514 tdp->textureHeader->data,
515 tdp->textureHeader->width,
516 tdp->textureHeader->height,
517 (GXTexFmt)tdp->textureHeader->format,
518 GX_CLAMP,
519 GX_CLAMP,
520 GX_FALSE);
521
522 GXInitTexObjLOD(&to,
523 tdp->textureHeader->minFilter,
524 tdp->textureHeader->magFilter,
525 tdp->textureHeader->minLOD,
526 tdp->textureHeader->maxLOD,
527 tdp->textureHeader->LODBias,
528 GX_FALSE,
529 tdp->textureHeader->edgeLODEnable,
530 GX_ANISO_1);
531
532 GXLoadTexObj(&to, GX_TEXMAP0);
533 }
534 }
535
536 MakeModelMtx(CamX, CamY, CamZ, v); // Make a new model matrix
537 MTXTranspose(v, v);
538 MTXTrans(rot, 0.0F, 0.0F, -8.0F * CameraLocScale);
539 MTXConcat(rot, v, v);
540
541 MakeModelMtx(LightX, LightY, LightZ, lv); // Make a new model matrix
542 MTXTranspose(lv, lv);
543 MTXTrans(rot, 0.0F, 0.0F, distance);
544 MTXConcat(rot, lv, lv);
545 TextureLightInit(lv);
546 MTXInverse(lv, lv);
547
548 }
549
DrawFrust(void)550 static void DrawFrust ( void )
551 {
552 float t = ffar / nnear;
553 Mtx mv;
554
555 MTXConcat(v, lv, mv);
556 GXLoadPosMtxImm(mv, GX_PNMTX0);
557
558 GXBegin(GX_LINESTRIP, GX_VTXFMT0, 17);
559
560 GXPosition3f32(xmin, ymin, -nnear); //n0
561 GXColor4u8(255, 255, 0, 255);
562
563 GXPosition3f32(xmax, ymin, -nnear); //n1
564 GXColor4u8(255, 255, 0, 255);
565
566 GXPosition3f32(xmax, ymax, -nnear); //n2
567 GXColor4u8(255, 255, 0, 255);
568
569 GXPosition3f32(xmin, ymax, -nnear); //n3
570 GXColor4u8(255, 255, 0, 255);
571
572 GXPosition3f32(xmin * t, ymax * t, -ffar); //f3
573 GXColor4u8(255, 255, 0, 255);
574
575 GXPosition3f32(xmax * t, ymax * t, -ffar); //f2
576 GXColor4u8(255, 255, 0, 255);
577
578 GXPosition3f32(xmax * t, ymin * t, -ffar); //f1
579 GXColor4u8(255, 255, 0, 255);
580
581 GXPosition3f32(xmin * t, ymin * t, -ffar); //f0
582 GXColor4u8(255, 255, 0, 255);
583
584 GXPosition3f32(xmin, ymin, -nnear); //n0
585 GXColor4u8(255, 255, 0, 255);
586
587 GXPosition3f32(xmax, ymin, -nnear); //n1
588 GXColor4u8(255, 255, 0, 255);
589
590 GXPosition3f32(xmax * t, ymin * t, -ffar); //f1
591 GXColor4u8(255, 255, 0, 255);
592
593 GXPosition3f32(xmin * t, ymin * t, -ffar); //f0
594 GXColor4u8(255, 255, 0, 255);
595
596 GXPosition3f32(xmin * t, ymax * t, -ffar); //f3
597 GXColor4u8(255, 255, 0, 255);
598
599 GXPosition3f32(xmax * t, ymax * t, -ffar); //f2
600 GXColor4u8(255, 255, 0, 255);
601
602 GXPosition3f32(xmax, ymax, -nnear); //n2
603 GXColor4u8(255, 255, 0, 255);
604
605 GXPosition3f32(xmin, ymax, -nnear); //n3
606 GXColor4u8(255, 255, 0, 255);
607
608 GXPosition3f32(xmin, ymin, -nnear); //n0
609 GXColor4u8(255, 255, 0, 255);
610
611 GXEnd();
612 }
613
TextureLightInit(Mtx rot)614 static void TextureLightInit ( Mtx rot )
615 {
616 Mtx proj;
617 Mtx mv;
618
619 MTXLightFrustum(proj, ymin, ymax, xmin, xmax, nnear,
620 0.5F, 0.5F, 0.5F, 0.5F);
621
622 MTXConcat(rot, m, mv);
623
624 MTXConcat(proj, mv, proj);
625
626 GXLoadTexMtxImm(proj, GX_TEXMTX0, GX_MTX3x4);
627 }
628
629 /*===========================================================================*/
630