Archive for December 6th, 2008
Embedding a Collada File
package { import flash.display.Bitmap; import flash.events.MouseEvent; import flash.utils.ByteArray; import org.papervision3d.materials.BitmapMaterial; import org.papervision3d.objects.parsers.DAE; import org.papervision3d.render.QuadrantRenderEngine; import org.papervision3d.view.BasicView; [SWF(width="640", height="480", backgroundColor="#000000", frameRate="60")] public class ColladaExample extends BasicView { [Embed(source="assets/c.DAE", mimeType = "application/octet-stream")] private var daeAsset:Class; [Embed(source="assets/materials/c.png")] private var materialAsset:Class; private var cameraPitch:Number = 90; private var cameraYaw:Number = 270; private var isOrbiting:Boolean = false; private var previousMouseX:Number; private var previousMouseY:Number; public function ColladaExample() { var byteArray:ByteArray = new daeAsset() as ByteArray; var dae:DAE = new DAE(); dae.load(byteArray); var bitmap:Bitmap = new materialAsset() as Bitmap; var bitmapMaterial:BitmapMaterial = new BitmapMaterial(bitmap.bitmapData, true); dae.materials.addMaterial(bitmapMaterial, "cMaterial"); scene.addChild(dae); startRendering(); stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp); stage.addEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandler); } private function mouseWheelHandler(event:MouseEvent):void { camera.moveForward(10 * event.delta); } private function onMouseDown(event:MouseEvent):void { isOrbiting = true; previousMouseX = event.stageX; previousMouseY = event.stageY; } private function onMouseUp(event:MouseEvent):void { isOrbiting = false; } private function onMouseMove(event:MouseEvent):void { var differenceX:Number = event.stageX - previousMouseX; var differenceY:Number = event.stageY - previousMouseY; if(isOrbiting) { cameraPitch += differenceY; cameraYaw += differenceX; cameraPitch %= 360; cameraYaw %= 360; cameraPitch = cameraPitch > 0 ? cameraPitch : 0.0001; cameraPitch = cameraPitch < 90 ? cameraPitch : 89.9999; previousMouseX = event.stageX; previousMouseY = event.stageY; camera.orbit(cameraPitch, cameraYaw); } } } }
Papervision3D Sound Spectrum
This example is a remake of something Andy Zupko did about a year and a half ago. I just updated it to work with the latest version of Papervision3D and organized some of the code.
The song is by an indie group called Wolf Parade.
The .swf is about 4 megs (it has an embedded .mp3), so be patient while it downloads.
Click to change the layout.

source
You won’t be able to just copy and paste this. You will need the layout classes included in the source download.
package { import flash.display.BitmapData; import flash.display.Shape; import flash.events.Event; import flash.events.MouseEvent; import flash.filters.BlurFilter; import flash.geom.ColorTransform; import flash.geom.Matrix; import flash.geom.Point; import flash.media.Sound; import flash.media.SoundMixer; import flash.utils.ByteArray; import org.papervision3d.materials.ColorMaterial; import org.papervision3d.materials.utils.MaterialsList; import org.papervision3d.objects.DisplayObject3D; import org.papervision3d.objects.primitives.Cube; import org.papervision3d.view.BasicView; import org.papervision3d.view.BitmapViewport3D; [SWF(width="640", height="480", backgroundColor="#000000", frameRate="60")] public class Papervision3DSoundSpectrum extends BasicView { [Embed(source="assets/WolfParade-CallItARitual.mp3")] private var soundAsset:Class; private const HEIGHT:int = 800; private const blur:BlurFilter = new BlurFilter(3, 3, 2); private const alphaTrans:ColorTransform = new ColorTransform(1, 1, 1, 1, 4, 5, 3, -10); private var point:Point = new Point(); private var bytes:ByteArray = new ByteArray(); private var sound:Sound; private var gradient:Array; private var bitmapViewport:BitmapViewport3D; public var layout:ILayout; public var circleLayout:CircleLayout; public var lineLayout:LineLayout; public var squareLayout:SquareLayout; public var cubes:Array = []; public static const CHANNELS:int = 40; public function Papervision3DSoundSpectrum() { sound = new soundAsset() as Sound; sound.play(); //we'll need a bitmapViewport to access bitmapData bitmapViewport = new BitmapViewport3D(); //allow the blurring bitmapViewport.fillBeforeRender = false; addChild(bitmapViewport); camera.extra = {goPosition: DisplayObject3D.ZERO, goTarget: DisplayObject3D.ZERO}; camera.x = 0, camera.y = 300, camera.z = 500; camera.zoom = 10; gradient = createColors(); createCubes(); startRendering(); stage.addEventListener(MouseEvent.MOUSE_DOWN, onClick); circleLayout = new CircleLayout(this); lineLayout = new LineLayout(this); squareLayout = new SquareLayout(this); layout = circleLayout; layout.setAndAssignNext(); } private function createColors(): Array { var gradient: Array = new Array(); var shape:Shape = new Shape(); var bitmapData:BitmapData = new BitmapData( 256, 1, true, 0 ); var colors:Array = [0xff0000, 0xff0000, 0xffff00, 0x00ff00, 0x00ffff]; var alphas:Array = [100, 100, 100, 100, 100]; var ratios:Array = [0, 16, 128, 192, 255]; var matrix:Matrix = new Matrix(); matrix.createGradientBox(CHANNELS, 1, 0, 0, 0 ); shape.graphics.beginGradientFill('linear', colors, alphas, ratios, matrix); shape.graphics.drawRect(0, 0, CHANNELS, 1); shape.graphics.endFill(); bitmapData.draw(shape); for(var i:int = 0; i < CHANNELS; i++) { gradient[i] = bitmapData.getPixel32(i, 0); } return gradient; } private function createCubes():void { var cubeMaterial:ColorMaterial; var angleOffset:Number = Math.PI*2/CHANNELS; var radius:Number = 400; var angle:Number = 180; var cubeX:Number, cubeZ:Number; var cube:Cube; for(var i:int =0;i<CHANNELS;i++) { cubeMaterial = new ColorMaterial(gradient[i]); cubeMaterial.lineColor = 0x222222; cubeMaterial.lineAlpha = 1; cubeX = Math.cos(angle)*radius; cubeZ = Math.sin(angle)*radius; var materialsList:MaterialsList = new MaterialsList(); materialsList.addMaterial(cubeMaterial, "all"); cube = new Cube(materialsList, 50, 50, HEIGHT); cubes[i] = cube; cubes[i].rotationY = 90; scene.addChild(cube); } } private function onClick(e:MouseEvent):void { layout.setAndAssignNext(); } override protected function onRenderTick(event:Event = null):void { SoundMixer.computeSpectrum(bytes, true, 2); var channelModulo:int = int(256/CHANNELS); var average:Number = 0; var temp:Number = 0; var currentChannel:Number = 0; for(var i:int =1;i<=256;i++) { temp = bytes.readFloat(); average += temp; if(i%channelModulo == 0) { //set the cur channel to this! if(currentChannel < cubes.length) { average /=channelModulo; if(average > cubes[currentChannel].scaleY) { cubes[currentChannel].scaleY = average; } else { cubes[currentChannel].scaleY -= 0.04; if(cubes[currentChannel].scaleY <= 0) { cubes[currentChannel].scaleY = 0; } } cubes[currentChannel].x += (cubes[currentChannel].extra.goX - cubes[currentChannel].x)/32; cubes[currentChannel].y = cubes[currentChannel].scaleY*HEIGHT/2; cubes[currentChannel].z += (cubes[currentChannel].extra.goZ - cubes[currentChannel].z)/32; } currentChannel++; average = 0; } } camera.orbit(bitmapViewport.containerSprite.mouseY, bitmapViewport.containerSprite.mouseX); renderer.renderScene(scene, camera, bitmapViewport); bitmapViewport.bitmapData.applyFilter(bitmapViewport.bitmapData, bitmapViewport.bitmapData.rect, point, blur); bitmapViewport.bitmapData.colorTransform(bitmapViewport.bitmapData.rect, alphaTrans); } } }
What is BasicView?
I use BasicView in all of my examples. This post explains why:
1. BasicView is a Sprite
Every ActionScript 3 project requires a “document class“. Since BasicView subclasses Sprite, you can extend BasicView to create your document class:
public class MyAwesomeDocumentClass extends BasicView
*note – You’ve probably heard the terms subclass, inherits, inheritance, extends, or others before. All those terms just mean you take advantage of the variables and functions of a specific class by writing another class that extends it. See Wikipedia’s Inheritance Page.
If you look at the docs, you’ll see the inheritance chain: BasicView->AbstractView->Sprite.
2. BasicView provides a viewport, scene, camera, and renderer
Every Papervision3D project requires a viewport, scene, camera, and renderer which are all classes in the Papervision3D library. If you don’t use BasicView, you have to do something like this:
package { import flash.display.Sprite; import flash.events.Event; import org.papervision3d.cameras.Camera3D; import org.papervision3d.objects.primitives.Sphere; import org.papervision3d.render.BasicRenderEngine; import org.papervision3d.scenes.Scene3D; import org.papervision3d.view.Viewport3D; [SWF(width="640", height="480", backgroundColor="#000000", frameRate="60")] public class ImTooCoolForBasicView extends Sprite { private var viewport:Viewport3D; private var scene:Scene3D; private var camera:Camera3D; private var renderer:BasicRenderEngine; public function ImTooCoolForBasicView() { viewport = new Viewport3D(); addChild(viewport); scene = new Scene3D(); camera = new Camera3D(); renderer = new BasicRenderEngine(); var sphere:Sphere = new Sphere(); scene.addChild(sphere); addEventListener(Event.ENTER_FRAME, enterFrameHandler); } private function enterFrameHandler(event:Event):void { renderer.renderScene(scene, camera, viewport); } } }
Phew, that was a lot of work! Let’s look at what it looks like when you use BasicView:
package { import org.papervision3d.objects.primitives.Sphere; import org.papervision3d.view.BasicView; [SWF(width="640", height="480", backgroundColor="#000000", frameRate="60")] public class SmartGuysUseBasicView extends BasicView { public function SmartGuysUseBasicView() { var sphere:Sphere = new Sphere(); scene.addChild(sphere); startRendering(); } } }
Much better!
You probably also noticed that the second example has the handy little “startRendering()” function. StartRendering does the exact same thing as the addEventListener(Event.ENTER_FRAME, enterFrameHandler); line in the first example. The addEventListener line is hidden away in AbstractView:
Hiding functionality like that example is called encapsulation, but who really cares what it’s called as long as it makes it easier
3. What’s this override protected function onRenderTick thing in the examples?
onRenderTick is the enter frame event listener called when you use startRendering(). If you look at the code, you’ll notice onRenderTick is a protected function. Using protected allows you to change what the function does by overriding it.
*note – The keyword
protectedis one of ActionScript 3’s “accessibility modifiers”. You may be familiar with other keywords: public, private, internal, and final. To learn how each of these “control access” to functions, read through adobe’s keyword page: http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/statements.html
By default, you just type startRendering(); and onRenderTick will just do the following each frame (you don’t have to type this out since it’s included in AbstractView):
renderer.renderScene(scene, camera, viewport);
You can change what onRenderTick does by writing it out like this:
override protected function onRenderTick(event:Event=null):void { sphere.yaw(1); renderer.renderScene(scene, camera, viewport); }
When overriding a function, remember that the parameters (event:Event=null) and the return type (void) have to remain exactly the same.
4. I get it! BasicView simply sets up what you need for Papervision3D!
Bingo! But that doesn’t mean you have to use BasicView. In fact, maybe your project requires multiple viewports or cameras and you’ll need to write out the code without BasicView. In the end, use what’s best for you.
As for me and my examples, I’ll be sticking with BasicView.
*final note – If you found how BasicView works interesting, I recommend reading up on the Template Pattern and the Facade Pattern.
Search
Recommended Books
Speaking at FITC Toronto
Recent Posts
- haXe Tutorial
- AS3 Signals Tutorial
- Preferred Video Tutorial Resolution?
- TweenMax – Tweening a timeline (Advanced Tweening)
- Robotlegs + Flight + Union Platform
- Back in the saddle
- Eclipse Theme Designer Preview
- RobotLegs Hello World Video Tutorial
- 10 Things Every Senior Flash Developer Should Know
- Efflex – 3D Effects for Flex
- MorphController – Mighty Morphing Papervision3D
- End dump
- Test if a plane is within the view of the camera (aka testing if culled)
- Materials Reference
- Perlin Blob
Recent Comments
- BAM5 on haXe Tutorial
- AlexG on Finding 2D Coordinates of a DisplayObject3D
- Josh on ActionScript 3 – Model View Controller (MVC)
- martin everett on requests
- martin everett on requests
- lillacska on Dragging Spheres
- Guy Ritchie on MXML without the Flex framework
- Pedro on ActionScript 3 – Namespaces
- daveevolve on AS3DMod Perlin Noise
- sebomoto on haXe Tutorial
Categories
Archives
Preferred Video Tutorial Resolution
- 1024x768 (53%, 85 Votes)
- 1280x1024 (15%, 24 Votes)
- 1920x1080 (15%, 24 Votes)
- 800x600 (13%, 20 Votes)
- 480x320 (4%, 6 Votes)
- 640x480 (0%, 2 Votes)
Total Voters: 160


