Home > Lab, as3, papervision3d > Exploring a Papervision3D class – Sound3D

Exploring a Papervision3D class – Sound3D

February 4th, 2009

So, this weekend I was working on a project; I use Flex Builder to code and as I was casting a class, I noticed “Sound3D” in the code completion and immediately got intrigued. I have heard of that class being buried deep in the Papervision packages before, but really didn’t pay much attention to it, till now.

Before we jump into anything, check out the example below. It uses the FirstPersonCamera3D class so you can move around and get a sense of what the Sound3D class does.

How cool is that?! I recently developed a game in which that would have worked out pretty well. No complaints though :) One thing about the Sound3D class in the Papervision3D packages is that it does not have the ability to load sounds, it only accepts a sound object as a parameter in the constructor, so, I decided to to add the functionality in there myself by creating an EnhancedSound3D class which extends the Sound3D, and here it is:

package
{
    import flash.events.Event;
    import flash.events.ProgressEvent;
    import flash.media.Sound;
    import flash.media.SoundLoaderContext;
    import flash.net.URLRequest;
   
    import org.papervision3d.objects.special.Sound3D;

    public class EnhancedSound3D extends Sound3D
    {
       
        private var soundObjectParams:Object = {};
       
        public function EnhancedSound3D(soundObj:Sound = null)
        {
            super(soundObj);
        }
       
        public function load(soundPath:String, startTime:Number = 0, loops:int = 0, soundTransform:SoundTransform = null):void{
            var soundRequest:URLRequest = new URLRequest(soundPath);
            sound = new Sound();
            sound.load(soundRequest, new SoundLoaderContext());
            sound.addEventListener(Event.COMPLETE, handleSoundLoaded);
            sound.addEventListener(ProgressEvent.PROGRESS, handleLoadProgress);
            soundObjectParams = {startTime:startTime, loops:loops, soundTransform:soundTransform}
        }
       
        private function handleSoundLoaded(e:Event):void
        {
            sound.removeEventListener(ProgressEvent.PROGRESS, handleLoadProgress);
            sound.removeEventListener(Event.COMPLETE, handleSoundLoaded);
            play(soundObjectParams.startTime, soundObjectParams.loops, soundObjectParams.soundTransform);
            dispatchEvent(e.clone());
        }
       
        private function handleLoadProgress(e:ProgressEvent):void
        {
            dispatchEvent(e.clone());
        }
       
    }
}

The Sound3D class extends DisplayObject3D, so it inherits all its properties such as x, y and z so you can basically place the sound anywhere you like in 3D space. A few added properties are maxSoundDistance and soundDistance. “maxSoundDistance” determines the maximum distance the sound can travel and “soundDistance” is used to control the volume. It puts out values ranging from -1 to 1 where 0 to -1 represent the sound being behind the camera.

You can basically attach your sound to anything, a car, a plane an enemy walking behind in your first person shooter game [wink, wink].

Below is the code I used for the example you just saw. Remember that you’ll need to grab the FirstPersonCamera3D class if you don’t have it yet.

package
{
    import flash.events.Event;
    import flash.events.ProgressEvent;
    import flash.text.TextField;
   
    import org.papervision3d.materials.ColorMaterial;
    import org.papervision3d.materials.WireframeMaterial;
    import org.papervision3d.materials.special.CompositeMaterial;
    import org.papervision3d.materials.utils.MaterialsList;
    import org.papervision3d.objects.primitives.Cube;
    import org.papervision3d.objects.primitives.Plane;
    import org.papervision3d.view.BasicView;

        import FirstPersonCamera3D;
        import EnhancedSound3D;

    public class CameraTest extends BasicView
    {
       
        private var firstPersonCamera:FirstPersonCamera3D;
        private var cubes:Array = [];
        private var sounds:Array = [];
       
        private var SIZE:Number;
        private var DISTANCE:Number;
       
        public function CameraTest()
        {
            super(640, 480, true, false);
            SIZE = 30000;
            DISTANCE = (SIZE * 0.5) - 250;
            setupCamera();
            createObjects3D();
            startRendering()
        }
       
        private function setupCamera():void
        {
            firstPersonCamera = new FirstPersonCamera3D();
            firstPersonCamera.initialize(viewport, 0.8, 0.2);
            firstPersonCamera.mode = "manual";
            firstPersonCamera.y = 750;
            firstPersonCamera.moveBounds = {left:-DISTANCE + 750, right:DISTANCE - 750, front:DISTANCE - 750, back:-DISTANCE + 750};
            firstPersonCamera.mapKeys(FirstPersonCamera3D.WASD_AND_ARROWS);
        }
       
        private function createObjects3D():void
        {
            var positions:Array = [{x:DISTANCE, y:750, z:DISTANCE},
                                   {x:-DISTANCE, y:750, z:DISTANCE},
                                   {x:DISTANCE, y:750, z:-DISTANCE},
                                   {x:-DISTANCE, y:750, z:-DISTANCE}];
           
            var cubeMat:WireframeMaterial = new WireframeMaterial(0xFF0000);
            var colorMat:ColorMaterial = new ColorMaterial(0x00FF00);
            var compMat:CompositeMaterial = new CompositeMaterial();
            compMat.addMaterial(cubeMat);
            compMat.addMaterial(colorMat);
           
            var materialsList:MaterialsList = new MaterialsList({ all:compMat });
           
            for(var a:Number = 0; a<4; a++){
                var cube:Cube = new Cube(materialsList);
                cube.x = positions[a].x;
                cube.y = positions[a].y;
                cube.z = positions[a].z;
                cube.lookAt(firstPersonCamera);
                cubes[a] = cube;
                               
                var sound3D:EnhancedSound3D = new EnhancedSound3D();
                sound3D.load(a+".mp3");
                sound3D.x = positions[a].x;
                sound3D.y = positions[a].y;
                sound3D.z = positions[a].z;
                sound3D.maxSoundDistance = SIZE * 0.75;
                sound3D.addEventListener(ProgressEvent.PROGRESS, handleSoundLoadProgress);
                sounds[a] = {sound:sound3D, tf:TextField(this["soundLoad"+a])};        
               
                scene.addChild(cube);
                scene.addChild(sound3D);
            }
           
            var floor:Plane = new Plane(new WireframeMaterial(0xFFFFFF), SIZE, SIZE, SIZE*0.001, SIZE*0.001);
            floor.rotationX = 90;
            scene.addChild(floor);
        }
       
        private function focusCubesOnCamera():void
        {
            for(var a:Number = 0; a<cubes.length; a++){
                cubes[a].lookAt(firstPersonCamera)
            }
        }
       
        private function handleSoundLoadProgress(e:ProgressEvent):void
        {
            for(var a:Number = 0; a<sounds.length; a++){
                if(e.target == sounds[a].sound){
                    sounds[a].tf.text = "Sound"+a+" -- "+Number(Math.round((e.bytesLoaded/e.bytesTotal)*100))+"% loaded."
                }
            }
        }
       
        override protected function onRenderTick(event:Event=null):void
        {
            firstPersonCamera.look(0.5);
            focusCubesOnCamera();
           
            renderer.renderScene(scene, firstPersonCamera, viewport);
        }
       
    }
}

Lab, as3, papervision3d

  1. Rafael Lima
    February 5th, 2009 at 07:37 | #1

    Wow, very awesome.
    I keep following the blog, each tutorial more learning. xD

  2. David NiƱo
    February 5th, 2009 at 13:54 | #2

    Awesome, nice reverberation effect in paper, i cant belive
    Congrats

  3. February 6th, 2009 at 10:38 | #3

    this is great, i have been wondering how the sounds would work out in a scene

  4. Kamalesh
    September 8th, 2009 at 20:17 | #4

    this is really great ! Thank you.

  5. Julius
    October 22nd, 2009 at 01:37 | #5

    Hi! :)
    I get a 1046 error:
    1046: Type was not found or was not a compile-time constant: SoundTransform.

    Any guess?
    thanx
    J.

  6. Julius
    October 22nd, 2009 at 01:38 | #6

    It’s in EnhancedSound3D.as, Line 21
    thx
    J

  1. No trackbacks yet.
Comments are closed.