This tutorial is part of what I had the opportunity to present at RIA Unleashed in Boston just a few weeks ago. The basic premise of this tutorial is to arrange objects into different patterns as the whole group animates.
After the initial setup of our View3D we create a container to hold all of our card items. This container will allow us to animate the entire group as we animate it’s contents in a different way.
private function createContainer():void { cardContainer = new ObjectContainer3D(); view.scene.addChild(cardContainer); }
Next we can create our cards (Plane objects), add them to our container object, apply a material, and store a reference to the card in an array so we can access it easily later.
private function createCards():void { var len:int = 6; for(var i:int = 0;i<len;i++) { var bitmapMaterial:BitmapFileMaterial = new BitmapFileMaterial("images/drawing.jpg"); bitmapMaterial.smooth = true; var plane:Plane = new Plane( { material:bitmapMaterial, width:200, height:200 } ); plane.bothsides = true; plane.yUp = false; cards.push(plane); cardContainer.addChild(plane); } }
The next thing we do is create a few different arrangements for our items. I’ve created 3 here; random, carousel, and flat. You can really create as many as you like. Let’s review just the random arrangement.
public function setInRandom():void { cardPositions = []; var len:int = cards.length; for(var i:int = 0;i<len;i++) { var positionVO:PositionVO = new PositionVO(); positionVO.x = Math.random() * 2000 - 1000; positionVO.y = Math.random() * 1000 - 500; positionVO.z = Math.random() * 200 - 200; positionVO.rotationY = Math.random() * 360 - 360; positionVO.rotationX = Math.random() * 360 - 360; cardPositions.push(positionVO); } arrageCards(); }
We start off by clearing our cardPositions array. We will use this array to store some value objects, a value object is nothing more than a class to store some properties like x, y, z, rotationX but if you’re using Flex or FlashDevelop you’ll get code hinting whenever you use it.
Next we loop through our total number of items we have on the stage and apply random numbers to all of our positionVO’s properties, and then push each of those items to our cardPositions array.
Finally we call arrangeCards()
private function arrageCards():void { TweenMax.killAll(false); var len:int = cards.length; for(var i:int = 0;i<len;i++) { var positionVO:PositionVO = cardPositions[i]; var plane:Plane = cards[i]; TweenMax.to(plane, 1,{ x:positionVO.x, y:positionVO.y, z:positionVO.z, rotationY:positionVO.rotationY, ease:Quint.easeInOut }); } }
Inside of the arrangeCards method we loop through our total number of items again this time passing along the card we want to animate, along with the properties from the positionVO to TweenMax. For one glorious second these will animate to their next position.
Here is the full code:
PositionVO.as
package { public class PositionVO { public var rotationX:Number = 0; public var rotationY:Number = 0; public var z:Number = 0; public var x:Number = 0; public var y:Number = 0; } }
Main.as
package { import away3d.containers.ObjectContainer3D; import away3d.containers.View3D; import away3d.materials.BitmapFileMaterial; import away3d.primitives.Plane; import flash.display.Sprite; import flash.events.MouseEvent; import flash.events.Event; import gs.TweenMax; import gs.easing.Quint; public class Main extends Sprite { private var cards:Array = []; private var cardContainer:ObjectContainer3D private var cardPositions:Array; private var view:View3D; private var toRandomButton:Sprite; private var toFlatButton:Sprite; private var toCarouselButton:Sprite; public static const CARD_SPACING:int = 210; public function Main() { super(); addEventListener(Event.ADDED_TO_STAGE, onAddedToStage); } protected function onAddedToStage(event:Event):void { createView(); createContainer(); createCards(); createNavButtons(); setInRandom(); startRendering(); view.camera.focus = 40; } private function createView():void { view = new View3D( { x:stage.stageWidth / 2, y:stage.stageHeight / 2 } ); addChild(view); } private function createContainer():void { cardContainer = new ObjectContainer3D(); view.scene.addChild(cardContainer); } private function createCards():void { var len:int = 6; for(var i:int = 0;i<len;i++) { var bitmapMaterial:BitmapFileMaterial = new BitmapFileMaterial("images/drawing.jpg"); bitmapMaterial.smooth = true; var plane:Plane = new Plane( { material:bitmapMaterial, width:200, height:200 } ); plane.bothsides = true; plane.yUp = false; cards.push(plane); cardContainer.addChild(plane); } } public function setFlat():void { cardPositions = []; var len:int = cards.length; //We use this offset to center the items in the scene var totalWidth:Number = len * CARD_SPACING; var offset:Number = totalWidth * .5 - CARD_SPACING *.5; for(var i:int = 0;i<len;i++) { var positionVO:PositionVO = new PositionVO(); positionVO.x = CARD_SPACING * i - offset; cardPositions.push(positionVO); } arrageCards(); } public function setInCarousel():void { cardPositions = []; var len:int = cards.length; var radius:int = 400; for(var i:int = 0;i<len;i++) { var positionVO:PositionVO = new PositionVO(); var angle:Number = Math.PI * 2 / len * i; positionVO.x = Math.cos(angle) * radius; positionVO.z = Math.sin(angle) * radius; positionVO.rotationY = -360 / len * i - 90; cardPositions.push(positionVO); } arrageCards(); } public function setInRandom():void { cardPositions = []; var len:int = cards.length; for(var i:int = 0;i<len;i++) { var positionVO:PositionVO = new PositionVO(); positionVO.x = Math.random() * 2000 - 1000; positionVO.y = Math.random() * 1000 - 500; positionVO.z = Math.random() * 200 - 200; positionVO.rotationY = Math.random() * 360 - 360; positionVO.rotationX = Math.random() * 360 - 360; cardPositions.push(positionVO); } arrageCards(); } private function createNavButtons():void { toRandomButton = createButton(); toCarouselButton = createButton(); toFlatButton = createButton(); toRandomButton.x = 20; toCarouselButton.x = 140; toFlatButton.x = 260 toRandomButton.y = 20; toCarouselButton.y = 20; toFlatButton.y = 20 toFlatButton.addEventListener(MouseEvent.CLICK, toFlatClick); toRandomButton.addEventListener(MouseEvent.CLICK, toRandomClick); toCarouselButton.addEventListener(MouseEvent.CLICK, toCarouselClick); } private function arrageCards():void { TweenMax.killAll(false); var len:int = cards.length; for(var i:int = 0;i<len;i++) { var positionVO:PositionVO = cardPositions[i]; var plane:Plane = cards[i]; TweenMax.to(plane, 1,{ x:positionVO.x, y:positionVO.y, z:positionVO.z, rotationY:positionVO.rotationY, ease:Quint.easeInOut }); } } private function createButton():Sprite { var button:Sprite = new Sprite(); button.graphics.beginFill(0x36414B); button.graphics.drawRect(0, 0, 100, 10); button.graphics.endFill(); addChild(button); return button; } //Mouse Event handlers private function toFlatClick(event:MouseEvent):void { setFlat(); } private function toRandomClick(event:MouseEvent):void { setInRandom(); } private function toCarouselClick(event:MouseEvent):void { setInCarousel(); } //Add an enterFrame for rendering the engine private function startRendering():void { addEventListener(Event.ENTER_FRAME, onRenderTick); } protected function onRenderTick(event:Event=null):void { view.render(); cardContainer.yaw(2); } } }



Pingback: Away3D Tutorial : Reposition and Arrange Objects in 3D Space | Papervision 3D Tutorials
Pingback: Tweets that mention Reposition and Arrange Objects in 3D Space with Away3D | Flash 3D Tutorials -- Topsy.com
Charlie, Thanks for posting those examples up! It was really inspiring to hear you speak at RIA event in Boston and I’ll be sure to keep checking on this site. I am digging away3d/papervision. Thanks.
@Daigo – Thanks for checking in, I’m glad I could help inspire at least one person. It makes the work all worth it.
I promise there is more to come.
Charlie
Hello,
I am very happy for this site. Some stuff is quite problematic during migration from pv3d to away3d. Like Quaternions
Is it possible that you could post something similar to http://pv3d.org/2008/11/29/free-rotation-using-quaternions/ converted to away3d?
I like slerp idea from pv3d and I miss it.
Good luck!
To Michal:
You can find a converted tutorial but with some minor changes at my blog:
http://blog.alladvanced.net
Pingback: Weekly Shared Items – 6. December, 2010 | TOXIN LABS - weblog of a german design student from wuerzburg