Click then Tween Camera to Plane

Sunday, December 28th, 2008 | examples

I posted a similar example in the archive over a year ago now that turned out to be quite popular. Since that’s now outdated, here’s a quick n’ dirty updated version:

All images come from dryicons.com/


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 TweenToSpatialPlanes 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 static const DISTANCE_FROM_PLANE:Number = 500;
 
		private var cameraWithSlerp:CameraWithSlerp = new CameraWithSlerp();
 
		private var cameraStart:DisplayObject3D = new DisplayObject3D();
		private var cameraTarget:DisplayObject3D = new DisplayObject3D();
 
		private var startQuaternion:Quaternion = null;
		private var endQuaternion:Quaternion = null;
		private var currentQuaternion:Quaternion = null;
 
		public function TweenToSpatialPlanes()
		{
			setupPapervision3D();			
			setupBackground();
			setupPlanes();
 
			singleRender();
		}
 
		private function setupPapervision3D():void
		{
			viewport.interactive = true;
			cameraWithSlerp.target = null;
			cameraWithSlerp.slerp = 0;
			cameraStart.z = -1000;
			scene.addChild(cameraStart);
		}
 
		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:Plane = new Plane(bitmapMaterial);
 
				plane.x = Math.random() * 5000 - 2500;
				plane.y = Math.random() * 5000 - 2500;
				plane.z = Math.random() * 2500;
				plane.rotationX = Math.random() * 180 -90;
				plane.rotationY = Math.random() * 180 -90;
				plane.rotationZ = Math.random() * 180 -90;
 
				scene.addChild(plane);
 
				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
		{
			var plane:Plane = Plane(event.target);
			//put the target behind the plane
			cameraTarget.copyTransform(plane);
			cameraTarget.moveBackward(DISTANCE_FROM_PLANE);
 
			createTween(cameraTarget);
		}
 
		private function backgroundSprite_clickHandler(event:MouseEvent):void
		{
			createTween(cameraStart);
		}
 
		private function createTween(displayObject3d:DisplayObject3D):void
		{
			//when "slerping", this value is a range from 0 to 1
			//0 being the starting total rotation (AKA transformation)
			//1 being the ending total rotation
			cameraWithSlerp.slerp = 0;
 
			var tweenObject:Object = {};
			tweenObject.x = displayObject3d.x;
			tweenObject.y = displayObject3d.y;
			tweenObject.z = displayObject3d.z;
			tweenObject.bezierThrough = [{x:0, y:0, z:0, slerp:.1}];
			tweenObject.ease = Cubic.easeInOut;
			tweenObject.slerp = 1;
			tweenObject.onUpdate = camera_updateCallback;
 
			startQuaternion = Quaternion.createFromMatrix(cameraWithSlerp.transform);
			endQuaternion = Quaternion.createFromMatrix(displayObject3d.transform);
 
			TweenMax.to(cameraWithSlerp, TWEEN_TIME, tweenObject);
		}
 
		private function camera_updateCallback():void
		{
			currentQuaternion = Quaternion.slerp(startQuaternion, endQuaternion, cameraWithSlerp.slerp);
			cameraWithSlerp.transform.copy3x3(currentQuaternion.matrix);
			singleRender();
		}
 
		override public function singleRender():void
		{
			renderer.renderScene(scene, cameraWithSlerp, viewport);
		}
	}
}
 
//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.cameras.Camera3D;
class CameraWithSlerp extends Camera3D
{
	public var slerp:Number = 0;
}

Tags: , ,

28 Comments to Click then Tween Camera to Plane

Rafael Lima
December 28, 2008

Very Awesome!

Mark Mun
December 30, 2008

Quaternion? wow.. things have changed a lot since the previous version of this implementation.

Guy Anderson
January 3, 2009

This is such a great example!

While I am rather experienced with Flash and AS2, I am a novice with AS3 & PV3D. I apologize if this is an ignorant question but what steps need to be take to I migrate this code into an entirely local example?

I have the most recent version of the PV3D library and I have tried importing this code to a new fla but I can’t seem to get things hooked up properly. Please feel free to email me. Thank you in advance for any help.

Sameer Gupta
January 5, 2009

Source is missing.

Mark Mun
January 5, 2009

Hi Guy,

John’s source files works perfectly locally. Just download the source, and import the zip file as an archive in flex 3. All the packages his using is included as a .swc

Giulio
January 5, 2009

Hi, in Flash I cannot use tag ‘Embed’
[Embed(source="assets/1.jpg")]

Any suggestion?
Thanx,
G.

John Lindquist
January 6, 2009

@Giulio - When I get back home next week, I’ll go over the things that differ when importing these to Flash.

mark mun
January 6, 2009

You can add it to your flash library with a linkage name and use it as :

var bitmapMaterial:BitmapAssetMaterial = new BitmapAssetMaterial(”linkageName”);

Giulio
January 7, 2009

@mark mun
I get an error:
1046: Type was not found or was not a compile-time constant: BitmapAssetMaterial.

mark mun
January 7, 2009

import org.papervision3d.materials.BitmapAssetMaterial;

sandro ieva
January 9, 2009

Great Example but doesnt work in FDT.
Try to change the example with BitmapAssetMaterial but no chance.
Can somebody help?

David Buchan
January 10, 2009

Great Stuff John,

@Sandro / Giulio

I made some updates to the the main document class and imported the assets into the Flash IDE to get the example to work in Flash.

It’s quick and dirty and it would be better to load the assets from an external as external assets like in the flex example, but this will work for you in the meantime.

You can download the FLA and AS files from the following location. The class is setup as a
document class.

http://www.visitframe.co.uk/downloads/pv_3d_updated.zip

Giulio
January 11, 2009

@mark mum…
I wrote
var bitmapMaterial:BitmapAssetMaterial = new BitmapAssetMaterial(”oneAsset”);

private var assets:Array = [oneAsset];

but I got a ArgumentError: Error #1063

David Buchan
January 11, 2009

@Giulio

You need make the reference to the class in the array a String:

private var assets:Array = ["oneAsset"];

Giulio
January 12, 2009

OMG…thanks David…but now I met an old friend: error #1007…aaargh!

INFO: Papervision3D Public Beta 2.0 - Great White (December 3rd, 2008)

INFO: Viewport autoScaleToStage : Papervision has changed the Stage scale mode.
TypeError: Error #1007: Instantiation attempted on a non-constructor.
at TweenToSpatialPlanes/createRandomBitmapMaterial()
at TweenToSpatialPlanes/setupPlanes()
at TweenToSpatialPlanes()

Any idea? I’m getting lost :(

sandro ieva
January 12, 2009

@David Buchan….thx for your help! But wanna do the sample in FDT. Cant use the EMBED Tagg, do u know how i can get the sample to run with BitmapFilematerial . Iam thankful for every kind of help!

David Buchan
January 14, 2009

@Gulio - ^ Download the example file from the link I provided previously. It should work without any problems

@sandro, I will try to modify the example and resend when I have more time. BitmapFileMaterial should work fine - you just need to make sure that you are not trying to apply the material to a plane before it’s fully loaded. You could write another method to preload all bitmaps, possibly into an array then setup the planes once you are sure they were loaded.

Giulio
January 19, 2009

Wow…works greatly man…thanks…
damn…this makes me really sad…I see a long, long walk beforev being able to master this stuff…it’s really a challange.
Thanks you again…

armitage case
February 1, 2009

hi, i cant create new CameraWithSlerp(), someone can help me pls.

alex_ex
February 4, 2009

hello i try to learn pv3d
i know some stuff about AS but not much about classes, packages etc
i made a project in flash, and i have this error:
5007: An ActionScript file must have at least one externally visible definition.
what went wrong?

alex_ex
February 9, 2009

hello all again
i was able to load the project correctly as my problem was that the libraries where old version.
one question, how would it be possible to make this with movie clips than bitmaps?
i understand that the class flash.display.Bitmap will work only for assets as jpg etc
can somebody point me what to look?

Matt
February 10, 2009

Hi John

amazing code. Thank you.
I’m being really dim though.
I’ve imported the archive into Flex, but am now stuck. :(

I cant create an mxml file in the src folder. How can I access/create this application? I have the source you provided, but dont kno how to plug it in to enjoy it.

Any help anyone can provide me would be great. Thanks guys

digitalsi
March 7, 2009

fantastic code.

Umm
April 23, 2009

Hi All,
Excellent code, just wondering how can I adjust the Alpha value of the background when a plane zooms in? It’ll also be nice if I can add extra descriptive paragraph outside the bordered item when it’s zoomed. Thanks all

benjamin
April 28, 2009

HI, and congrats for your talent !

I implemented some PV3D quaternion method for away3D (i’m not an official contributor, this is for me, even if I’ll share them later) inspired by the pv3d class…
and found your process for tween/target camera I decided to implement it with away3D (for the need of a personnal work).
But what is strange is that when using it the camera (or whatever object )
just don’t lookat the target but turn it’s back to it instead of being face to face…
and I currently don’t understand why (and not so many peoples in the away dev group gave me answers):note:
I have access to the same method as you.
do you know how I could inverse the rotation of the quaternion so that it look back:

here is an example of what i’m gettin :

http://www.agence-anonyme.com/lab/islandtest.swf
(note: the object is not double-sided so what you see is the front…and it should be the back…)

any point of view will be fully apreciated !!!

benjamin
April 28, 2009

I mean, for the example:
click on the plane to see another one tweens…
;-)

Andrew
June 1, 2009

John, can you post an example or explain how to actually have a button when clicked accesses the certain plane and tweens to that?

I rewrote some of the source to have a MovieClip display on the plane without using:

for(var i:int = 0; i < NUM_PLANES; i++)

Im basically creating each plane as a movieClip and giving them different names. Is there a way to use an event Listener for a button to call a certain plane to tween to camera when the button is pressed?

Im basically using this:

private function setupNav():void
{
var newbtn:button1 = new button1();
addChild(newbtn);
newbtn.buttonMode = true;
newbtn.x = 150;
newbtn.y = 150;
newbtn.addEventListener(MouseEvent.CLICK, onClickHandler);
}

private function onClickHandler(event:InteractiveScene3DEvent):void
{
trace(”CLICK”);

var plane:Plane = Plane(event.target);
//put the target behind the plane
cameraTarget.copyTransform(plane);
cameraTarget.moveBackward(DISTANCE_FROM_PLANE);
createTween(cameraTarget);
}

I obviously have no idea how to do this and this example is completely wrong.

Thanks.

Andrew
June 1, 2009

I actually got it working, I was semi close. Had to define the var for the plane so the event could find it and change a few things around.

Leave a comment