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