package org.papervision3d.objects.special { import flash.media.Sound; import flash.media.SoundChannel; import flash.media.SoundTransform; import org.papervision3d.core.proto.CameraObject3D; import org.papervision3d.core.render.data.RenderSessionData; import org.papervision3d.objects.DisplayObject3D; public class Sound3D extends DisplayObject3D { //any sound object public var sound:Sound; //This is used for sound via SoundChannel, FLV or video to be transformed. public var soundChannel : SoundChannel; //maximum distance the sound can travel public var maxSoundDistance:Number; /* * This is used to control the volume and could also be used to control the pitch and/or fader * if a sound engine that supports it is used. It puts out values from -1 to 1. Values from 0 to -1 is * when the object is behind the camera. */ public var soundDistance :Number; //Controls the pan. It puts out values from -1 to 1. public var soundPan :Number; //Works only for sound public function play(startTime:Number = 0, loops:int = 0,sndTransform:SoundTransform = null):void { soundChannel = sound.play(startTime, loops, sndTransform); if (soundChannel){ setVolume(0); setPan(0); } } public function stop(startTime:Number = 0, loops:int = 0, sndTransform:SoundTransform = null):void { soundChannel.stop(); } private function setPan(pan:Number):void { var transform:SoundTransform = SoundTransform(soundChannel.soundTransform); transform.pan = pan; soundChannel.soundTransform = transform; } private function setVolume(volume:Number):void { var transform:SoundTransform = soundChannel.soundTransform; transform.volume = volume; soundChannel.soundTransform = transform; } //Controls the 3d position of the sound public function updateSound ( camera:CameraObject3D ):void { var dist:Number; var newX:Number = this.world.n14 - camera.x; var newY:Number = this.world.n24 - camera.y; var newZ:Number = this.world.n34 - camera.z; if(!maxSoundDistance) maxSoundDistance = 4000; var Sdist:Number = Math.sqrt(newX*newX+newY*newY+newZ*newZ); var Angle:Number = int(Math.atan(newX/newZ)*180/Math.PI) - camera.rotationY; if (Angle>359) Angle = (Angle%360); else if(Angle<=0) Angle = 360+(Angle%360); if (newZ<0) Angle = ((Angle)+180)%360; else if(newZ>0) Angle = Angle; if (Sdist<=maxSoundDistance) dist = 1-(Sdist/maxSoundDistance); else dist = 0; var ang:Number = Angle - 179; var Pan:Number = (ang - 180)/180; if ( ang >= -180 && ang <= 0) Pan = ((ang + 180)/90); //left ear else if (ang<179 && ang>0) Pan = ((ang - 179)/90); //right ear if(Pan<-1) Pan = -(Pan%1 + 1); else if(Pan>1) Pan = .99 - (Pan%1); soundPan = Pan; soundDistance = dist*(view.n34/Math.abs(view.n34)); if(soundChannel){ setVolume(Math.abs(soundDistance)); setPan(soundPan); } } public function Sound3D( soundObj:Sound=null ):void { if(soundObj){ this.sound = soundObj; //this.soundChannel = new SoundChannel(); } } public override function project(parent:DisplayObject3D, renderSessionData:RenderSessionData):Number { //if( ! sorted ) this._sorted = sorted = new Array(); if( this._transformDirty ) updateTransform(); calculateScreenCoords( renderSessionData.camera ); if (soundChannel) updateSound(renderSessionData.camera);//Updates 3D Sound this.view.calculateMultiply( parent.view, this.transform ); this.world.calculateMultiply( parent.world, this.transform ); var screenZs :Number = 0; var children :Number = 0; return this.screenZ = screenZs / children; } } }