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