1 /*---------------------------------------------------------------------------*
2 Project: 3D sound demo for AX
3 File: axart3ddemo.c
4
5 Copyright (C)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 $Log: axart3ddemo.c,v $
14 Revision 1.8 2006/03/06 09:59:03 kawaset
15 Eliminated warnings.
16
17 Revision 1.7 02/21/2006 01:04:15 mitu
18 modified am.h path.
19
20 Revision 1.6 02/20/2006 04:13:07 mitu
21 changed include path from dolphin/ to revolution/.
22
23 Revision 1.5 02/02/2006 07:44:31 aka
24 Modified using MEM functions instead of OSAlloc()/OSFree().
25
26 Revision 1.4 02/01/2006 07:59:03 aka
27 Added #ifndef(#ifdef) HOLLYWOOD_REV - #else - #endif.
28
29 Revision 1.3 02/01/2006 04:26:20 aka
30 Added cast from u32 to u8* in relation to changing API around ARAM.
31
32 Revision 1.2 11/08/2005 02:55:02 aka
33 Changed suiting to Revolution's audio spec.
34
35 Revision 1.1 11/04/2005 05:01:39 aka
36 Imported from dolphin tree.
37
38 9 03/04/24 11:43:00 Suzuki
39 Changed the effect from reverbHiDpl2 to reverbHi(This part is commented
40 out).
41
42 8 03/04/09 15:23 Suzuki
43 shift AuxA and AuxB volume left by 16bit.
44
45 7 03/04/01 16:19:00 Sak
46 murakami: modify to use atan2f in place of atan
47
48 7 02/10/23 3:13p Suzuki
49 replaced the turn of AXARTServiceSounds and MIXUpdateSettings.
50
51 5 4/11/02 1:59p Billyjack
52
53 4 1/08/02 6:42p Billyjack
54 - Added DPL2 support
55
56 3 9/05/01 4:33p Eugene
57 Updated AM API.
58
59 2 8/29/01 1:52p Billyjack
60
61 1 8/20/01 6:05p Billyjack
62 created
63
64 1 7/06/01 11:50a Billyjack
65 created
66 $NoKeywords: $
67
68 *---------------------------------------------------------------------------*/
69
70 #include <math.h>
71 #include <demo.h>
72 #include <revolution/mix.h>
73 #include <revolution/axart.h>
74 #include <revolution/sp.h>
75 #ifndef HOLLYWOOD_REV
76 #include <dolphin/am.h> // ARAM manager used for AX demos
77 #else
78 #include <revolution/mem.h>
79 #include <string.h>
80 #endif
81
82 #include "axartdemo.h" // symbols from sndconv
83
84 #ifndef HOLLYWOOD_REV
85 /*---------------------------------------------------------------------------*
86 * ARAM initialization
87 *---------------------------------------------------------------------------*/
88
89 #define MAX_ARAM_BLOCKS 2
90 static u32 aramMemArray[MAX_ARAM_BLOCKS];
91
92 #else
93 /*---------------------------------------------------------------------------*
94 * Exp Heap
95 *---------------------------------------------------------------------------*/
96
97 static MEMHeapHandle hExpHeap;
98
99 /*---------------------------------------------------------------------------*
100 * Zero Buffer
101 *---------------------------------------------------------------------------*/
102
103 #define ZEROBUFFER_BYTES 256
104 #endif
105
106 /*---------------------------------------------------------------------------*
107 local type used for 3D sound object
108 *---------------------------------------------------------------------------*/
109 typedef struct
110 {
111
112 AXVPB *voice;
113 SPSoundEntry *sound;
114 AXART_SOUND axartSound;
115 AXART_3D axart3d;
116 AXART_PITCH axartPitch; // additional pitch cents
117 AXART_VOLUME axartVolume; // additional attenuation
118 AXART_AUXA_VOLUME axartAuxAVolume;// set volume for aux A
119 AXART_AUXB_VOLUME axartAuxBVolume;// set volume for aux B
120 AXART_AUXC_VOLUME axartAuxCVolume;// set volume for aux C
121
122 } soundObject;
123
124 // two sound objects used by demo
125 static soundObject helicopter;
126 static soundObject cube;
127
128 // additional articulators for making LFO effects with cube
129 static AXART_PITCH_MOD cubePitchMod[2];
130 static AXART_VOLUME_MOD cubeVolumeMod[2];
131
132 static u8 *soundSamples;
133 static SPSoundTable *soundTable;
134
135 /*---------------------------------------------------------------------------*
136 Callback for AX audio frames, for this demo we need to tell AX3D to update
137 sound sources then run the mixer as AX3D will apply setting to the mixer
138 *---------------------------------------------------------------------------*/
callbackAudioFrame(void)139 static void callbackAudioFrame(void)
140 {
141 AXARTServiceSounds();
142 MIXUpdateSettings();
143 }
144
145
146 /*---------------------------------------------------------------------------*
147 Some stuff for video
148 *---------------------------------------------------------------------------*/
149 // Constants
150 #define GRID_LENGTH 95
151 #define GRID_SEGS 19
152
153 // Local structures
154 typedef struct
155 {
156 Vec xAxis;
157 Vec yAxis;
158 Vec zAxis;
159 Vec translate;
160
161 f32 fov;
162 f32 aspect;
163 f32 near;
164 f32 far;
165
166 Mtx viewMtx;
167
168 } CameraObj;
169
170 // Forward references
171 void main ( void );
172
173 static void DrawInit ( void );
174 static void DrawTick ( void );
175 static void AnimTick ( void );
176
177 static void CameraLoad ( CameraObj *newCam );
178 static void CameraUpdate ( CameraObj *camera );
179
180 static void DrawGrid ( void );
181 static void DrawUI ( void );
182
183 // Global variables
184 CameraObj DefaultCamera =
185 {
186 {1.0f, 0.0f, 0.0f},
187 {0.0f, 0.0f, 1.0f},
188 {0.0f,-1.0f, 0.0f},
189 {0.0f, 0.0f, 2.0f},
190 45.0f,
191 4.0f / 3.0f,
192 0.1f,
193 1024.0f
194 };
195
196 u32 Quit = 0;
197 CameraObj Camera;
198 GXLightObj Light;
199
200 Vec WorldXAxis = { 1, 0, 0 };
201 Vec WorldYAxis = { 0, 1, 0 };
202 Vec WorldZAxis = { 0, 0, 1 };
203
204 Vec BallPosition = { 40, 0, 0 };
205 f32 BallRotation = 0.0f;
206 Mtx ModelMtx;
207
208 Vec CubePosition = { 0, 0, 0 };
209
210 f32 CubeRadius = 5.0f;
211
212 GXRenderModeObj *RenderMode;
213
214 /*---------------------------------------------------------------------------*
215 *---------------------------------------------------------------------------*/
voiceDrop(void * p)216 static void voiceDrop(void *p)
217 {
218 // if a voice is dropped we need to get rid of references to it so it is
219 // no longer serviced for that instance of soundObject...
220 // we stored the pointer to the soundObject in the voice for just such an
221 // occasion
222 soundObject *so = (soundObject*)(((AXVPB*)p)->userContext);
223
224 if (so)
225 {
226 // we are using the so->voice as a flag to service the axart3D
227 so->voice = NULL;
228
229 // remove the sound from AXART
230 AXARTRemoveSound(&so->axartSound);
231 }
232 }
233
234
235 /*---------------------------------------------------------------------------*
236 Name: startSound
237
238 Description: start helicopter and cube sound
239
240 Arguments: so , pointer to static soundObject
241 st , pointer to sound table
242 i , index of sound to start
243
244 Returns: none
245 *---------------------------------------------------------------------------*/
startSound(soundObject * so,SPSoundTable * st,u32 i)246 static void startSound(soundObject *so, SPSoundTable *st, u32 i)
247 {
248 // allocate voice for sound object
249 so->voice = AXAcquireVoice(15, &voiceDrop, (u32)so);
250
251 if (so->voice)
252 {
253 // get sound entry
254 so->sound = SPGetSoundEntry(st, i);
255
256 if (so->sound)
257 {
258 // prepare the sound addressing
259 SPPrepareSound(so->sound, so->voice, 0);
260
261 // initialize the AXART_SOUND
262 AXARTInitSound (&so->axartSound, so->voice, so->sound->sampleRate);
263
264 // initialize articulators
265 AXARTInitArt3D (&so->axart3d);
266 AXARTInitArtPitch (&so->axartPitch);
267 AXARTInitArtVolume (&so->axartVolume);
268 AXARTInitArtAuxAVolume (&so->axartAuxAVolume);
269 AXARTInitArtAuxBVolume (&so->axartAuxBVolume);
270 AXARTInitArtAuxCVolume (&so->axartAuxCVolume);
271
272 // turn the Aux sends to 0
273 so->axartAuxAVolume.attenuation = -904 << 16;
274 so->axartAuxBVolume.attenuation = -904 << 16;
275 so->axartAuxCVolume.attenuation = -904 << 16;
276
277 // add articulators to sound
278 AXARTAddArticulator (&so->axartSound, (AXART_ART*)&so->axart3d);
279 AXARTAddArticulator (&so->axartSound, (AXART_ART*)&so->axartPitch);
280 AXARTAddArticulator (&so->axartSound, (AXART_ART*)&so->axartVolume);
281 AXARTAddArticulator (&so->axartSound, (AXART_ART*)&so->axartAuxAVolume);
282 AXARTAddArticulator (&so->axartSound, (AXART_ART*)&so->axartAuxBVolume);
283 AXARTAddArticulator (&so->axartSound, (AXART_ART*)&so->axartAuxCVolume);
284
285 // add sound to sound list
286 AXARTAddSound(&so->axartSound);
287
288 // start the sound
289 AXSetVoiceState(so->voice, AX_PB_STATE_RUN);
290 }
291 else
292 {
293 // free the voice if we are not going to use it
294 AXFreeVoice(so->voice);
295 }
296 }
297 }
298
299
300 /*---------------------------------------------------------------------------*
301 *---------------------------------------------------------------------------*/
addModToCube(void)302 static void addModToCube(void)
303 {
304 // adjust volume on cube using volume articulator already installed
305 // cube.axartVolume.attenuation = -960 << 16;
306 cube.axartVolume.attenuation = -150 << 16;
307 // cube.axartPitch.cents = -1200 << 16;
308
309 // initialize articulators
310 AXARTInitArtPitchMod(&cubePitchMod[0]);
311 AXARTInitArtPitchMod(&cubePitchMod[1]);
312 AXARTInitArtVolumeMod(&cubeVolumeMod[0]);
313 AXARTInitArtVolumeMod(&cubeVolumeMod[1]);
314
315 // initialize LFOs
316 AXARTInitLfo(&cubePitchMod[0].lfo, AXARTSine, AXART_SINE_SAMPLES, (0.3f * AXART_SINE_SAMPLES) / 200);
317 AXARTInitLfo(&cubePitchMod[1].lfo, AXARTSine, AXART_SINE_SAMPLES, (5.0f * AXART_SINE_SAMPLES) / 200);
318 AXARTInitLfo(&cubeVolumeMod[0].lfo, AXARTSaw, AXART_SAW_SAMPLES, (1.0f * AXART_SAW_SAMPLES) / 200);
319 AXARTInitLfo(&cubeVolumeMod[1].lfo, AXARTSine, AXART_SINE_SAMPLES, (3.0f * AXART_SINE_SAMPLES) / 200);
320
321 // assign pitch and attenuation for articulators
322 cubePitchMod[0].cents = -500 << 16;
323 cubePitchMod[1].cents = 500 << 16;
324 cubeVolumeMod[0].attenuation = -30 << 16;
325 cubeVolumeMod[1].attenuation = 30 << 16;
326
327 // add articulators to sound
328 AXARTAddArticulator(&cube.axartSound, (AXART_ART*)&cubePitchMod[0]);
329 AXARTAddArticulator(&cube.axartSound, (AXART_ART*)&cubePitchMod[1]);
330 AXARTAddArticulator(&cube.axartSound, (AXART_ART*)&cubeVolumeMod[0]);
331 AXARTAddArticulator(&cube.axartSound, (AXART_ART*)&cubeVolumeMod[1]);
332 }
333
334
335 /*---------------------------------------------------------------------------*
336 *---------------------------------------------------------------------------*/
killSound(soundObject * so)337 static void killSound(soundObject *so)
338 {
339 if (so->voice)
340 {
341 // remove the sound from AXART
342 AXARTRemoveSound(&so->axartSound);
343
344 // free the voice
345 AXFreeVoice(so->voice);
346
347 // we are using the so->voice as a flag to service the axart3D
348 so->voice = NULL;
349 }
350 }
351
352 #ifdef HOLLYWOOD_REV
353 /*---------------------------------------------------------------------------*
354 *---------------------------------------------------------------------------*/
LoadFileIntoRam(char * path)355 static void* LoadFileIntoRam(char *path)
356 {
357 DVDFileInfo handle;
358 u32 round_length;
359 s32 read_length;
360 void *buffer;
361
362 // Open File
363 if (!DVDOpen(path, &handle))
364 {
365 OSReport("WARNING! Failed to open %s\n", path);
366 return NULL;
367 }
368
369 // Make sure file length is not 0
370 if (DVDGetLength(&handle) == 0)
371 {
372 OSReport("WARNING! File length is 0\n");
373 return NULL;
374 }
375
376 round_length = OSRoundUp32B(DVDGetLength(&handle));
377 buffer = MEMAllocFromExpHeapEx(hExpHeap, round_length, 32);
378
379 // Make sure we got a buffer
380 if (buffer == NULL)
381 {
382 OSReport("WARNING! Unable to allocate buffer\n");
383 return NULL;
384 }
385
386 // Read Files
387 read_length = DVDRead(&handle, buffer, (s32)(round_length), 0);
388
389 // Make sure we read the file correctly
390 if (read_length <= 0)
391 {
392 OSReport("WARNING! File lenght is wrong\n");
393 return NULL;
394 }
395
396 return buffer;
397 }
398 #endif
399
400 /*---------------------------------------------------------------------------*
401 Name: main
402
403 Description: The main application loop
404
405 Arguments: none
406
407 Returns: none
408 *---------------------------------------------------------------------------*/
main(void)409 void main (void)
410 {
411 #ifndef HOLLYWOOD_REV
412 u32 aramBase;
413 u32 aramSize;
414 #else
415 void *arenaMem2Lo;
416 void *arenaMem2Hi;
417 u8 *zeroBuffer;
418 #endif
419
420 DEMOInit( NULL );
421 DrawInit();
422
423 #ifndef HOLLYWOOD_REV
424 // initialize ARAM w/ stack allocator
425 ARInit(aramMemArray, MAX_ARAM_BLOCKS);
426 ARQInit();
427 #else
428 // initialize Exp Heap on MEM2
429 arenaMem2Lo = OSGetMEM2ArenaLo();
430 arenaMem2Hi = OSGetMEM2ArenaHi();
431 hExpHeap = MEMCreateExpHeap(arenaMem2Lo, (u32)arenaMem2Hi - (u32) arenaMem2Lo);
432 #endif
433
434 // initialize AI subsystem
435 AIInit(NULL);
436
437 // initialize AX, MIXer and AXART
438 AXInit();
439 MIXInit();
440 AXARTInit();
441
442 // start the system in stereo mode
443 AXSetMode(AX_MODE_STEREO);
444 MIXSetSoundMode(MIX_SOUND_MODE_STEREO);
445
446 AXARTSet3DDopplerScale(20.0f);
447 AXARTSet3DDistanceScale(40.0f);
448
449 AXRegisterCallback(&callbackAudioFrame);
450
451 #ifndef HOLLYWOOD_REV
452 // for the purpose of this demo we take all the ARAM *chuckle*
453 aramSize = ARGetSize() - ARGetBaseAddress();
454 aramBase = ARAlloc(aramSize);
455 AMInit(aramBase, aramSize);
456 #endif
457
458 // push sound samples into ARAM
459 #ifndef HOLLYWOOD_REV
460 soundSamples = (u8*)AMPush("/axdemo/axart/axartdemo.spd");
461 #else
462 soundSamples = LoadFileIntoRam("/axdemo/axart/axartdemo.spd");
463 #endif
464
465 // load sound table into main memory
466 #ifndef HOLLYWOOD_REV
467 soundTable = AMLoadFile("/axdemo/axart/axartdemo.spt", NULL);
468 #else
469 soundTable = LoadFileIntoRam("/axdemo/axart/axartdemo.spt");
470 #endif
471
472 #ifdef HOLLYWOOD_REV
473 zeroBuffer = MEMAllocFromExpHeapEx(hExpHeap, ZEROBUFFER_BYTES, 8);
474 memset(zeroBuffer, 0, ZEROBUFFER_BYTES);
475 DCFlushRange(zeroBuffer, ZEROBUFFER_BYTES);
476 #endif
477
478 // initialize the sound table
479 #ifndef HOLLYWOOD_REV
480 SPInitSoundTable(soundTable, soundSamples, (u8*)AMGetZeroBuffer());
481 #else
482 SPInitSoundTable(soundTable, soundSamples, zeroBuffer);
483 #endif
484
485 // start sounds
486 startSound(&helicopter, soundTable, SND_HELICOPTER);
487 startSound(&cube, soundTable, SND_CUBE);
488 addModToCube();
489
490 while( !Quit )
491 {
492 // Get input and animate
493 AnimTick();
494
495 DEMOBeforeRender();
496
497 // Draw the scene
498 DrawTick();
499
500 DEMODoneRender();
501 }
502
503 killSound(&helicopter);
504 killSound(&cube);
505
506 AXARTQuit();
507 MIXQuit();
508 AXQuit();
509
510 OSReport( "End of demo.\n" );
511 }
512
513
514 /*---------------------------------------------------------------------------*
515 Name: DrawInit
516
517 Description: Initialize
518
519 Arguments: none
520
521 Returns: none
522 *---------------------------------------------------------------------------*/
523 static void
DrawInit(void)524 DrawInit( void )
525 {
526 GXColor black = {0,0,0,0};
527
528 RenderMode = DEMOGetRenderModeObj();
529
530 // Set background color
531 GXSetCopyClear( black, GX_MAX_Z24 );
532
533 // Initialize the camera
534 Camera = DefaultCamera;
535 }
536
537
538 static GXColor change = { 0, 64, 128, 255 };
539 static BOOL delta_r = 1;
540 static BOOL delta_g = 1;
541 static BOOL delta_b = 1;
542
543
544 /*---------------------------------------------------------------------------*
545 Name: DrawTick
546
547 Description: Draw the current scene.
548
549 Arguments: none
550
551 Returns: none
552 *---------------------------------------------------------------------------*/
553 static void
DrawTick()554 DrawTick ( )
555 {
556 GXColor green = { 0, 255, 0, 100 };
557 GXColor red = { 255, 0, 0, 255 };
558 GXColor lightGrey = { 220, 220, 220, 255 };
559 GXColor darkGrey = { 35, 35, 35, 255 };
560 Mtx mv, scale;
561
562 // Load up the camera
563 CameraLoad( &Camera );
564
565 // Set the blend mode for transparencies
566 GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR);
567 GXSetAlphaCompare(GX_GREATER, 0, GX_AOP_AND, GX_GREATER, 0);
568 GXSetZCompLoc(GX_FALSE);
569
570 // Pass register color in TEV
571 GXSetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0 );
572 GXSetTevOp( GX_TEVSTAGE0, GX_PASSCLR );
573 GXSetNumTexGens( 0 );
574 GXSetNumTevStages( 1 );
575 GXSetNumChans( 1 );
576
577 // Enable lighting
578 GXSetChanCtrl( GX_COLOR0A0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT0, GX_DF_CLAMP, GX_AF_NONE );
579 GXSetChanAmbColor( GX_COLOR0A0, darkGrey );
580
581 // Initialize light w/ pre-lighting
582 GXInitLightPos( &Light, 0, 0, 1024.0f );
583 GXInitLightColor( &Light, lightGrey );
584 GXLoadLightObjImm( &Light, GX_LIGHT0 );
585
586 // Load in the modelview matrix for sphere
587 MTXConcat( Camera.viewMtx, ModelMtx, mv );
588 GXLoadPosMtxImm( mv, GX_PNMTX0 );
589 GXSetCurrentMtx( GX_PNMTX0 );
590
591 // Draw unit sphere with model matrix
592 GXSetChanMatColor( GX_COLOR0A0, red );
593 GXDrawSphere( 20, 20 );
594
595 // draw cube
596 MTXScale(scale, CubeRadius, CubeRadius, CubeRadius);
597 MTXConcat(Camera.viewMtx, scale, mv);
598 GXLoadPosMtxImm(mv, GX_PNMTX0);
599 GXSetCurrentMtx( GX_PNMTX0 );
600 GXSetChanMatColor( GX_COLOR0A0, change );
601 GXDrawCube();
602
603
604 if (delta_r)
605 {
606 change.r++;
607 if (255 == change.r)
608 {
609 delta_r = 0;
610 }
611 }
612 else
613 {
614 change.r--;
615 if (0 == change.r)
616 {
617 delta_r = 1;
618 }
619 }
620
621 if (delta_g)
622 {
623 change.g++;
624 if (255 == change.g)
625 {
626 delta_g = 0;
627 }
628 }
629 else
630 {
631 change.g--;
632 if (0 == change.g)
633 {
634 delta_g = 1;
635 }
636 }
637
638 if (delta_b)
639 {
640 change.b++;
641 if (255 == change.b)
642 {
643 delta_b = 0;
644 }
645 }
646 else
647 {
648 change.b--;
649 if (0 == change.b)
650 {
651 delta_b = 1;
652 }
653 }
654
655
656 // Disable lighting
657 GXSetChanCtrl( GX_COLOR0A0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );
658
659 // Load in the modelview matrix for grid
660 // Assume identity model matrix
661 GXLoadPosMtxImm( Camera.viewMtx, GX_PNMTX0 );
662
663 // Draw green grid (transparent so draw last )
664 GXSetChanMatColor( GX_COLOR0A0, green );
665 DrawGrid();
666
667 // Draw text, do this last since it clobbers lots of GX state
668 DrawUI();
669 }
670
toggleAxMode(void)671 static void toggleAxMode(void)
672 {
673
674 switch (AXGetMode())
675 {
676 case AX_MODE_STEREO:
677
678 AXSetMode(AX_MODE_SURROUND);
679 MIXSetSoundMode(MIX_SOUND_MODE_SURROUND);
680
681 break;
682
683 case AX_MODE_SURROUND:
684
685 AXSetMode(AX_MODE_DPL2);
686 MIXSetSoundMode(MIX_SOUND_MODE_DPL2);
687
688 break;
689
690 case AX_MODE_DPL2:
691
692 AXSetMode(AX_MODE_STEREO);
693 MIXSetSoundMode(MIX_SOUND_MODE_STEREO);
694
695 break;
696 }
697
698 }
699
700 static int buttonDown = FALSE;
701 /*---------------------------------------------------------------------------*
702 Name: AnimTick
703
704 Description: Animates the scene
705
706 Arguments: none
707
708 Returns: none
709 *---------------------------------------------------------------------------*/
710 static void
AnimTick(void)711 AnimTick ( void )
712 {
713 u16 buttons;
714 u16 buttonsDown;
715 s8 stickX;
716 s8 stickY;
717 s8 subStickX;
718 s8 subStickY;
719 u8 triggerL;
720 u8 triggerR;
721 Mtx rot;
722 static f32 digAYBtnScale;
723
724
725 // Get the pad status
726 DEMOPadRead();
727 buttons = DEMOPadGetButton(0);
728 buttonsDown = DEMOPadGetButtonDown(0);
729 stickX = DEMOPadGetStickX(0);
730 stickY = DEMOPadGetStickY(0);
731 subStickX = DEMOPadGetSubStickX(0);
732 subStickY = DEMOPadGetSubStickY(0);
733 triggerL = DEMOPadGetTriggerL(0);
734 triggerR = DEMOPadGetTriggerR(0);
735
736
737 // Quit
738 if(buttonsDown & PAD_BUTTON_MENU)
739 {
740 Quit = 1;
741 }
742
743 // toggle AX mode
744 if (buttons & PAD_BUTTON_X)
745 {
746 if (buttonDown == FALSE)
747 {
748 buttonDown = TRUE;
749 toggleAxMode();
750 }
751 }
752 else
753 {
754 buttonDown = FALSE;
755 }
756
757 // Reset Camera
758 if(buttonsDown & PAD_TRIGGER_L)
759 {
760 Camera = DefaultCamera;
761 }
762
763 // Shift button
764 if( buttons & PAD_TRIGGER_R )
765 {
766 // Roll the camera about its z axis
767 if(stickX != 0)
768 {
769 MTXRotAxis(rot, &Camera.zAxis, -stickX * 5.0f / 128.0f);
770 MTXMultVec(rot, &Camera.xAxis, &Camera.xAxis);
771 MTXMultVec(rot, &Camera.yAxis, &Camera.yAxis);
772 }
773 }
774 else
775 {
776 // Zoom camera
777 if( buttons & (PAD_BUTTON_Y | PAD_BUTTON_A) )
778 {
779 if( buttonsDown & (PAD_BUTTON_Y | PAD_BUTTON_A) )
780 {
781 digAYBtnScale = 0.05f;
782 }
783
784 // If Y button, reverse the direction of zoom
785 if( buttons & PAD_BUTTON_Y )
786 digAYBtnScale = -digAYBtnScale;
787
788 Camera.translate.x += digAYBtnScale * Camera.zAxis.x;
789 Camera.translate.y += digAYBtnScale * Camera.zAxis.y;
790 Camera.translate.z += digAYBtnScale * Camera.zAxis.z;
791
792 // Restore the scale
793 if( buttons & PAD_BUTTON_Y )
794 digAYBtnScale = -digAYBtnScale;
795
796 digAYBtnScale += 0.05f;
797 if( digAYBtnScale > 5.0f )
798 digAYBtnScale = 5.0f;
799 }
800
801 if(stickX != 0)
802 {
803 // Rotate camera about world Z Axis
804 MTXRotAxis(rot, &WorldZAxis, -stickX * 5.0f / 128.0f);
805 MTXMultVec(rot, &Camera.xAxis, &Camera.xAxis);
806 MTXMultVec(rot, &Camera.yAxis, &Camera.yAxis);
807 MTXMultVec(rot, &Camera.zAxis, &Camera.zAxis);
808 }
809 if(stickY != 0)
810 {
811 // Rotate camera about camera x axis
812 MTXRotAxis(rot, &Camera.xAxis, -stickY * 5.0f / 128.0f);
813 MTXMultVec(rot, &Camera.yAxis, &Camera.yAxis);
814 MTXMultVec(rot, &Camera.zAxis, &Camera.zAxis);
815 }
816
817 if( subStickX != 0 )
818 {
819 // Dolly the camera relative to camera x axis
820 f32 translate = subStickX * 5.0f / 128.0f;
821 Camera.translate.x += translate * Camera.xAxis.x;
822 Camera.translate.y += translate * Camera.xAxis.y;
823 Camera.translate.z += translate * Camera.xAxis.z;
824 }
825 if( subStickY != 0 )
826 {
827 // Dolly the camera relative to camera y axis
828 f32 translate = subStickY * 5.0f / 128.0f;
829 Camera.translate.x += translate * Camera.yAxis.x;
830 Camera.translate.y += translate * Camera.yAxis.y;
831 Camera.translate.z += translate * Camera.yAxis.z;
832 }
833 }
834
835 if (!(buttons & PAD_TRIGGER_Z))
836 {
837 MTXRotDeg( rot, 'z', 1.5f );
838 MTXMultVec( rot, &BallPosition, &BallPosition );
839 MTXTrans( ModelMtx, BallPosition.x, BallPosition.y, BallPosition.z );
840 }
841
842 // Update any changes to the camera
843 CameraUpdate( &Camera );
844 }
845
846
847 /*---------------------------------------------------------------------------*
848 Name: CameraLoad
849
850 Description: Initialize the projection matrix and load into hardware.
851
852 Arguments: newCam - camera to switch projection to
853
854 Returns: none
855 *---------------------------------------------------------------------------*/
856 static void
CameraLoad(CameraObj * newCam)857 CameraLoad( CameraObj *newCam )
858 {
859 Mtx44 p;
860
861 MTXPerspective( p, newCam->fov, newCam->aspect, newCam->near, newCam->far );
862 GXSetProjection(p, GX_PERSPECTIVE);
863 }
864
865
866 /*---------------------------------------------------------------------------*
867 Name: CameraUpdate
868
869 Description: Updates the camera's view matrix.
870
871 Arguments: camera - camera's view matrix to update
872
873 Returns: none
874 *---------------------------------------------------------------------------*/
875 static void
CameraUpdate(CameraObj * camera)876 CameraUpdate ( CameraObj *camera )
877 {
878 Mtx transMtx;
879
880 VECNormalize( &camera->xAxis, &camera->xAxis );
881 VECNormalize( &camera->yAxis, &camera->yAxis );
882 VECNormalize( &camera->zAxis, &camera->zAxis );
883
884 MTXRowCol(camera->viewMtx,0,0) = camera->xAxis.x;
885 MTXRowCol(camera->viewMtx,0,1) = camera->xAxis.y;
886 MTXRowCol(camera->viewMtx,0,2) = camera->xAxis.z;
887 MTXRowCol(camera->viewMtx,0,3) = 0.0F;
888
889 MTXRowCol(camera->viewMtx,1,0) = camera->yAxis.x;
890 MTXRowCol(camera->viewMtx,1,1) = camera->yAxis.y;
891 MTXRowCol(camera->viewMtx,1,2) = camera->yAxis.z;
892 MTXRowCol(camera->viewMtx,1,3) = 0.0F;
893
894 MTXRowCol(camera->viewMtx,2,0) = camera->zAxis.x;
895 MTXRowCol(camera->viewMtx,2,1) = camera->zAxis.y;
896 MTXRowCol(camera->viewMtx,2,2) = camera->zAxis.z;
897 MTXRowCol(camera->viewMtx,2,3) = 0.0F;
898
899 MTXTrans(transMtx, -camera->translate.x, -camera->translate.y, -camera->translate.z);
900 MTXConcat(camera->viewMtx, transMtx, camera->viewMtx);
901
902 if (helicopter.voice)
903 {
904 f32 oldDist, newDist, hAngle, vAngle;
905 int old;
906 Vec ballPosInCamera;
907
908 // Find position of ball in camera space
909 MTXMultVec( Camera.viewMtx, &BallPosition, &ballPosInCamera );
910
911 // Compute horizontal and vertical angle
912 if (ballPosInCamera.x > 0)
913 hAngle = -atan2f( ballPosInCamera.x, ballPosInCamera.z ) + 3.14f;
914 else
915 hAngle = -atan2f( ballPosInCamera.x, ballPosInCamera.z ) - 3.14f;
916
917 if (ballPosInCamera.y > 0)
918 vAngle = -atan2f( ballPosInCamera.y, ballPosInCamera.z ) + 3.14f;
919 else
920 vAngle = -atan2f( ballPosInCamera.y, ballPosInCamera.z ) - 3.14f;
921
922 oldDist = helicopter.axart3d.dist;
923 newDist = sqrtf(((ballPosInCamera.x * ballPosInCamera.x) +
924 (ballPosInCamera.y * ballPosInCamera.y) +
925 (ballPosInCamera.z * ballPosInCamera.z)));
926
927 old = OSDisableInterrupts();
928
929 helicopter.axart3d.hAngle = hAngle;
930 helicopter.axart3d.vAngle = vAngle;
931 helicopter.axart3d.dist = newDist;
932 helicopter.axart3d.closingSpeed = oldDist - newDist;
933 helicopter.axart3d.update = TRUE;
934
935 OSRestoreInterrupts(old);
936 }
937
938 if (cube.voice)
939 {
940 f32 oldDist, newDist, hAngle, vAngle;
941 int old;
942 Vec cubePosInCamera;
943
944 // Find position of cube in camera space
945 MTXMultVec( Camera.viewMtx, &CubePosition, &cubePosInCamera );
946
947 // Compute horizontal and vertical angle
948 if (cubePosInCamera.x > 0)
949 hAngle = -atan2f( cubePosInCamera.x, cubePosInCamera.z ) + 3.14f;
950 else
951 hAngle = -atan2f( cubePosInCamera.x, cubePosInCamera.z ) - 3.14f;
952
953 if (cubePosInCamera.y > 0)
954 vAngle = -atan2f( cubePosInCamera.y, cubePosInCamera.z ) + 3.14f;
955 else
956 vAngle = -atan2f( cubePosInCamera.y, cubePosInCamera.z ) - 3.14f;
957
958 oldDist = cube.axart3d.dist;
959 newDist = sqrtf(((cubePosInCamera.x * cubePosInCamera.x) +
960 (cubePosInCamera.y * cubePosInCamera.y) +
961 (cubePosInCamera.z * cubePosInCamera.z)));
962
963 old = OSDisableInterrupts();
964
965 cube.axart3d.hAngle = hAngle;
966 cube.axart3d.vAngle = vAngle;
967 cube.axart3d.dist = newDist;
968 cube.axart3d.closingSpeed = oldDist - newDist;
969 cube.axart3d.update = TRUE;
970
971 OSRestoreInterrupts(old);
972 }
973 }
974
975
976 /*---------------------------------------------------------------------------*
977 Name: DrawGrid
978
979 Description: Draws a square grid of length GRID_LENGTH centered about
980 the origin lying on the XY world plane. GRID_SEGS is the
981 number of vertices per side.
982
983 Arguments: none
984
985 Returns: none
986 *---------------------------------------------------------------------------*/
987 static void
DrawGrid()988 DrawGrid ( )
989 {
990 u32 i, j;
991 f32 position[2];
992 f32 increment;
993
994 // Draw grid
995 GXClearVtxDesc();
996 GXSetVtxDesc( GX_VA_POS, GX_DIRECT );
997 GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );
998
999 increment = ((f32)GRID_LENGTH) / GRID_SEGS;
1000
1001 position[1] = -GRID_LENGTH * 0.5f;
1002 for( i = 0; i < GRID_SEGS; i++ )
1003 {
1004 position[0] = -GRID_LENGTH * 0.5f;
1005 GXBegin( GX_LINESTRIP, GX_VTXFMT0, GRID_SEGS );
1006 for( j = 0; j < GRID_SEGS; j++ )
1007 {
1008 GXPosition3f32( position[0], position[1], 0 );
1009 position[0] += increment;
1010 }
1011 position[1] += increment;
1012 GXEnd();
1013 }
1014
1015 position[0] = -GRID_LENGTH * 0.5f;
1016 for( i = 0; i < GRID_SEGS; i++ )
1017 {
1018 position[1] = -GRID_LENGTH * 0.5f;
1019 GXBegin( GX_LINESTRIP, GX_VTXFMT0, GRID_SEGS );
1020 for( j = 0; j < GRID_SEGS; j++ )
1021 {
1022 GXPosition3f32( position[0], position[1], 0 );
1023 position[1] += increment;
1024 }
1025 position[0] += increment;
1026 GXEnd();
1027 }
1028 }
1029
1030 /*---------------------------------------------------------------------------*
1031 Name: DrawUI
1032
1033 Description: Draw text onto the scene
1034
1035 Arguments: none
1036
1037 Returns: none
1038 *---------------------------------------------------------------------------*/
1039 static void
DrawUI()1040 DrawUI ()
1041 {
1042 s16 textX = 20;
1043 s16 textY = 20;
1044
1045 // Initialize GX for drawing text
1046 DEMOInitCaption( DM_FT_OPQ, RenderMode->fbWidth, RenderMode->xfbHeight );
1047
1048 switch (AXGetMode())
1049 {
1050 case AX_MODE_STEREO:
1051
1052 DEMOPrintf( textX, textY, 0, "AX mode: AX_MODE_STEREO");
1053
1054 break;
1055
1056 case AX_MODE_SURROUND:
1057
1058 DEMOPrintf( textX, textY, 0, "AX mode: AX_MODE_SURROUND");
1059
1060 break;
1061
1062 case AX_MODE_DPL2:
1063
1064 DEMOPrintf( textX, textY, 0, "AX mode: AX_MODE_DPL2");
1065
1066 break;
1067 }
1068 textY += 20;
1069 DEMOPrintf( textX, textY, 0, "helicopter.voice: %.8xh", helicopter.voice);
1070 textY += 10;
1071 DEMOPrintf( textX, textY, 0, "helicopter.sound.sampleRate: %dHz", helicopter.sound->sampleRate);
1072 textY += 20;
1073 DEMOPrintf( textX, textY, 0, "helicopter.axart3d.hAngle: %f", helicopter.axart3d.hAngle);
1074 textY += 10;
1075 DEMOPrintf( textX, textY, 0, "helicopter.axart3d.vAngle: %f", helicopter.axart3d.vAngle);
1076 textY += 10;
1077 DEMOPrintf( textX, textY, 0, "helicopter.axart3d.dist: %f", helicopter.axart3d.dist);
1078 textY += 10;
1079 DEMOPrintf( textX, textY, 0, "helicopter.axart3d.closingSpeed: %f", helicopter.axart3d.closingSpeed);
1080 }
1081