Tweening rotated planes to you

Sunday, January 11th, 2009 | examples

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: ,

  • chui chui
    thank you so much! i love your blog!
  • Paul
    John - Thanks very much for this and all your other excellent examples. I'm afraid I'm a little out of my depth here, so I apologise in advance if this question appears foolish. I've been trying to work out what defines the scale of the plane at the end of the tweenForward. I've played around with it, but have only managed to alter the scale of the planes in the initial state, which doesn't affect it's scale/ z position when it's zoomed forward.

    Any help would be greatly appreciated.
  • cicit
    how to rotate all the planes just like to browse them thru?
  • Alessandro
    Same error as charles, what could be the problem ? Thanks !
  • using Flash 9 and the latest PV3D (Papervision3D 2.0.869 zip) , i get:

    TypeError: Error #1007: Instantiation attempted on a non-constructor.
    at TweenPlanesToYou/createRandomBitmapMaterial()
    at TweenPlanesToYou/setupPlanes()
    at TweenPlanesToYou()

    any suggestions?
  • Great example! I was looking for something like this. Thanks!
  • Giulio
    Yeah, there's a lot of love in this blog.
  • John Lindquist
    @Trevor - and this blog loves you ;)
  • i love this blog. so much
  • Giulio
    Looks great man, even if I think the camera movement it's much more impressive...
blog comments powered by Disqus

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 ...