Archive for January 11th, 2009

Tweening rotated planes to you

Sunday, January 11th, 2009 | examples | Comments

I just got back from a week long trip to Los Angeles for work. I wrote this on the plane on the way home. It’s kind of the opposite of the camera tweening thing I wrote a little while ago. I probably need to add some more comments, but I just wanted to post it before I get settled in and relax for a bit.


source

package
{
	import flash.display.Bitmap;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
 
	import gs.TweenMax;
	import gs.easing.Cubic;
 
	import org.papervision3d.core.math.Quaternion;
	import org.papervision3d.events.InteractiveScene3DEvent;
	import org.papervision3d.materials.BitmapMaterial;
	import org.papervision3d.objects.DisplayObject3D;
	import org.papervision3d.objects.primitives.Plane;
	import org.papervision3d.view.BasicView;
 
	[SWF(width="640", height="480", backgroundColor="#000000", frameRate="60")]
	public class TweenPlanesToYou extends BasicView
	{
		[Embed(source="assets/1.jpg")]
		private var oneAsset:Class;
		[Embed(source="assets/2.jpg")]
		private var twoAsset:Class;
		[Embed(source="assets/3.jpg")]
		private var threeAsset:Class;
		[Embed(source="assets/4.jpg")]
		private var fourAsset:Class;
		[Embed(source="assets/5.jpg")]
		private var fiveAsset:Class;
		[Embed(source="assets/6.jpg")]
		private var sixAsset:Class;
 
		private var assets:Array = [oneAsset, twoAsset, threeAsset, fourAsset, fiveAsset, sixAsset];
 
		private static const NUM_PLANES:int = 40;
		private static const TWEEN_TIME:Number = 2;
 
		private var previousPlane:PlaneWithSlerp;
 
		private var startQuaternion:Quaternion = null;
		private var endQuaternion:Quaternion = null;
		private var currentQuaternion:Quaternion = null;
 
		public function TweenPlanesToYou()
		{
			setupPapervision3D();			
			setupBackground();
			setupPlanes();
 
			startRendering();
		}
 
		private function setupPapervision3D():void
		{
			viewport.interactive = true;
		}
 
		private function setupBackground():void
		{
			//the background is for the "click outside" events
			var backgroundSprite:Sprite = new Sprite();
 
			backgroundSprite.graphics.beginFill(0x000000);
			backgroundSprite.graphics.drawRect(0, 0, width, height);
			backgroundSprite.graphics.endFill();
 
			addChildAt(backgroundSprite, getChildIndex(viewport));
 
			backgroundSprite.addEventListener(MouseEvent.CLICK, backgroundSprite_clickHandler);
		}
 
		private function setupPlanes():void
		{
			for(var i:int = 0; i < NUM_PLANES; i++)
			{
				var bitmapMaterial:BitmapMaterial = createRandomBitmapMaterial();
				bitmapMaterial.interactive = true;
				bitmapMaterial.doubleSided = true;
				bitmapMaterial.precise = true;
 
				var plane:PlaneWithSlerp = new PlaneWithSlerp(bitmapMaterial);
 
				plane.x = Math.random() * 5000 - 2500;
				plane.y = Math.random() * 5000 - 2500;
				plane.z = Math.random() * 2500;
				plane.originalX = plane.x;
				plane.originalY = plane.y;
				plane.originalZ = plane.z;
				plane.rotationX = Math.random() * 180 -90;
				plane.rotationY = Math.random() * 180 -90;
				plane.rotationZ = Math.random() * 180 -90;
				plane.slerp = 0;
 
				scene.addChild(plane);
 
				singleRender();			
				plane.startQuaternion = Quaternion.createFromMatrix(plane.transform);	
				plane.endQuaternion = Quaternion.createFromMatrix(DisplayObject3D.ZERO.transform);	
 
				plane.addEventListener(InteractiveScene3DEvent.OBJECT_CLICK, plane_objectClickHandler);
			}
		}
 
		private function createRandomBitmapMaterial():BitmapMaterial
		{
			//grab a bitmapAsset from the array (this is very ugly, but not important to the concept :) )
			var bitmap:Bitmap = Bitmap(new assets[Math.floor(Math.random() * assets.length)]);
			var bitmapMaterial:BitmapMaterial = new BitmapMaterial(bitmap.bitmapData);
 
			return bitmapMaterial;
		}
 
		private function plane_objectClickHandler(event:InteractiveScene3DEvent):void
		{
			tweenPreviousPlane();
 
			var plane:PlaneWithSlerp = PlaneWithSlerp(event.target);
			if(previousPlane != plane)
			{
				tweenForward(plane);
			}
			if(plane.isAtStartingPoint)
			{
				previousPlane = null; 
			}else
			{
				previousPlane = plane;
			}
		}
 
		private function tweenPreviousPlane():void
		{
			if(previousPlane && !previousPlane.isAtStartingPoint)tweenBack(previousPlane);
		}
		private function backgroundSprite_clickHandler(event:MouseEvent):void
		{
			tweenPreviousPlane();
		}
 
		private function tweenForward(plane:PlaneWithSlerp):void
		{
			plane.isAtStartingPoint = false;
 
			var tweenObject:Object = {};
			tweenObject.x = 0;
			tweenObject.y = 0;
			tweenObject.z = 0;
			tweenObject.slerp = 1;
 
			tweenObject.bezierThrough = [{x:-plane.x/4, y:-plane.y/4, z:700}];
			tweenObject.ease = Cubic.easeInOut;
 
			tweenObject.onUpdate = plane_updateCallback;
			tweenObject.onUpdateParams = [plane];
 
			TweenMax.to(plane, TWEEN_TIME, tweenObject);
		}
 
		private function tweenBack(plane:PlaneWithSlerp):void
		{
			plane.isAtStartingPoint = true;
 
			var tweenObject:Object = {};
			tweenObject.x = plane.originalX;
			tweenObject.y = plane.originalY;
			tweenObject.z = plane.originalZ;
			tweenObject.slerp = 0;
 
			tweenObject.bezierThrough = [{x:-plane.x/4, y:-plane.y/4, z:700}];
			tweenObject.ease = Cubic.easeInOut;
 
			tweenObject.onUpdate = plane_updateCallback;
			tweenObject.onUpdateParams = [plane];
 
			TweenMax.to(plane, TWEEN_TIME, tweenObject);
		}
 
		private function plane_updateCallback(plane:PlaneWithSlerp):void
		{
			plane.currentQuaternion = Quaternion.slerp(plane.startQuaternion, plane.endQuaternion, plane.slerp);
			plane.transform.copy3x3(plane.currentQuaternion.matrix);
		}
	}
}
 
//a helper class whose sole purpose is to add the slerp property
//I use this for the sake of brevity, but for production code
//you would move this into a new ActionScript file
import org.papervision3d.objects.primitives.Plane;
import org.papervision3d.core.proto.MaterialObject3D;
import org.papervision3d.core.math.Quaternion;
class PlaneWithSlerp extends Plane
{
	public var slerp:Number = 0;
	public var startQuaternion:Quaternion = new Quaternion();
	public var endQuaternion:Quaternion = new Quaternion();
	public var currentQuaternion:Quaternion = new Quaternion();
	public var originalX:Number = 0;
	public var originalY:Number = 0;
	public var originalZ:Number = 0;
	public var isAtStartingPoint:Boolean = true;
	public function PlaneWithSlerp(material:MaterialObject3D)
	{
		super(material);
	}
}

Tags: ,

Search

Recommended Books

Speaking at FITC Toronto

 

January 2009
M T W T F S S
« Dec   Feb »
 1234
567891011
12131415161718
19202122232425
262728293031  

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

Loading ... Loading ...