slerp

Slerp Explorer

Tuesday, December 30th, 2008 | how it works | Comments

Slerp allows you to find the quickest path from one rotation to another rotation. In Papervision3D, slerp is a static function of the Quaternion class. The following code shows all the pieces you’ll need to use slerp in your projects:

//the values from your start axis and rotation (x,y,z,rotation)
startQuaternion = new Quaternion(0, 1, 0, 1);
//the values from your end axis and rotation
endQuaternion = new Quaternion(0, 1, 0, 1);
 
/* the next section would go in an update event, like Event.ENTER_FRAME or TimerEvent.TIMER */
 
//if slerp is 0, the rotation will reflect the startQuaternion
//if slerp is 1, the rotation will reflect the endQuaternion
//any value between 0 and 1 will be a percentage of the rotation
//between the start and end. For example, .5 would be halfway between
//start and end.
slerp = 0; //transition this up to 1, something like slerp += .01;
 
//the main quaternion that you copy the rotation from
quaternion = Quaternion.slerp(startQuaternion, endQuaternion, slerp);
//Copies the rotation from the main quaternion into the cube's matrix
cube.transform.copy3x3(quaternion.matrix);

To use this example:

  1. Move the axis and rotation sliders then click “set start”.
  2. Move the axis and rotation sliders and click “set end”
  3. Click “slerp from start to end” and you’ll see the cube rotate from the start rotation to the end rotation.

Focus on how the cube is rotating and how you could use that in your projects. Don’t get distracted by the reference axis.

Tags: ,

Click then Tween Camera to Plane

Sunday, December 28th, 2008 | examples | Comments

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

Carousel with proper rotation and reflection

Monday, December 1st, 2008 | examples | Comments

I’m going to go out on a limb and say that this post will be popular ;)


source

package
{
	import flash.display.Bitmap;
	import flash.events.Event;
	import flash.filters.BlurFilter;
 
	import org.papervision3d.core.effects.view.ReflectionView;
	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;
 
	[SWF(width="640", height="480", backgroundColor="#000000", frameRate="60")]
	public class ClickThenRotateCarousel extends ReflectionView
	{
		[Embed(source="assets/pic.jpg")]
		private var picAsset:Class;
 
		private const RADIUS:Number = 400;
		private const NUM_OF_PLANES:int = 9;
		private var carousel:DisplayObject3D = new DisplayObject3D();
 
		private var currentQuat:Quaternion = new Quaternion();		
		private var targetQuat:Quaternion = new Quaternion();
		private var slerp:Number = 0;
 
 
		public function ClickThenRotateCarousel()
		{
			viewportReflection.filters = [new BlurFilter(3,3,3)];
			viewport.interactive = true;
			surfaceHeight = -100; 
			camera.z = 800; //move camera to the front
 
			var pic:Bitmap = Bitmap(new picAsset());
 
			for(var i:int = 0; i < NUM_OF_PLANES; i++)
			{
				var material:BitmapMaterial = new BitmapMaterial(pic.bitmapData, true);
				material.doubleSided = true;
				material.interactive = true;
 
				var plane:Plane = new Plane(material, 100, 100);
				plane.rotationY = 360 / NUM_OF_PLANES * i;
				plane.moveForward(RADIUS);
 
				plane.addEventListener(InteractiveScene3DEvent.OBJECT_OVER, objectOverHandler);
				plane.addEventListener(InteractiveScene3DEvent.OBJECT_OUT, objectOutHandler);
				plane.addEventListener(InteractiveScene3DEvent.OBJECT_CLICK, objectClickHandler);
 
				carousel.addChild(plane);
			}
 
			scene.addChild(carousel);
 
			addEventListener(Event.ENTER_FRAME, enterFrameHandler);
		}
 
		private function objectOverHandler(event:InteractiveScene3DEvent):void
		{
			viewport.buttonMode = true;
		}
 
		private function objectOutHandler(event:InteractiveScene3DEvent):void
		{
			viewport.buttonMode = false;
		}
 
		private function objectClickHandler(event:InteractiveScene3DEvent):void
		{
			var radians:Number = (carousel.rotationY - event.displayObject3D.rotationY) * Quaternion.DEGTORAD;
 
			slerp = 0;
			currentQuat = Quaternion.createFromMatrix(carousel.transform);
			targetQuat = Quaternion.createFromAxisAngle(0, 1, 0, radians);
		}
 
		private function enterFrameHandler(event:Event):void
		{
			slerp += (1 - slerp) * .05;
			var quat:Quaternion = Quaternion.slerp(currentQuat, targetQuat, slerp);
 
			carousel.transform = quat.matrix;
 
			singleRender();
		}
	}
}

Tags: , , , ,

Using Slerp to move around a Sphere

Saturday, November 29th, 2008 | examples, requests | Comments


source

package
{
	import flash.events.Event;
 
	import org.papervision3d.core.math.Quaternion;
	import org.papervision3d.core.utils.Mouse3D;
	import org.papervision3d.events.InteractiveScene3DEvent;
	import org.papervision3d.lights.PointLight3D;
	import org.papervision3d.materials.ColorMaterial;
	import org.papervision3d.materials.shadematerials.FlatShadeMaterial;
	import org.papervision3d.objects.primitives.Plane;
	import org.papervision3d.objects.primitives.Sphere;
	import org.papervision3d.view.BasicView;
	import org.papervision3d.view.layer.ViewportLayer;
	import org.papervision3d.view.layer.util.ViewportLayerSortMode;
 
	[SWF(width="640", height="480", backgroundColor="#000000", frameRate="60")]
	public class SlerpExample extends BasicView
	{
		private const RADIUS:Number = 400;
 
		private var planeQuat:Quaternion = new Quaternion();
		private var mouseQuat:Quaternion = new Quaternion();
		private var slerpQuat:Quaternion = new Quaternion();
		private var plane:Plane;
		private var sphere:Sphere;
		private var mouse3D:Mouse3D;
 
		private var slerp:Number = 0;
 
		public function SlerpExample() 
		{
			viewport.interactive = true;
			Mouse3D.enabled = true;
			mouse3D = viewport.interactiveSceneManager.mouse3D;
 
			var light:PointLight3D = new PointLight3D();
			var material:FlatShadeMaterial = new FlatShadeMaterial(light, 0xffffff);
			material.interactive = true;
			plane = new Plane(new ColorMaterial(0xcc0000), 50, 50);
 
			plane.z = -RADIUS;
 
			viewport.containerSprite.sortMode = ViewportLayerSortMode.INDEX_SORT;
			var planeViewportLayer:ViewportLayer = new ViewportLayer(viewport, plane);
			planeViewportLayer.layerIndex = 1;
			viewport.containerSprite.addLayer(planeViewportLayer);
 
			sphere = new Sphere(material, RADIUS, 30, 30);		
			sphere.addEventListener(InteractiveScene3DEvent.OBJECT_CLICK, objectClickHandler);
 
			scene.addChild(sphere);
			scene.addChild(plane);
 
			startRendering();
		}
 
		private function resetQuats():void
		{
			slerp = 0;
			planeQuat = Quaternion.createFromMatrix(plane.transform);
			mouseQuat = Quaternion.createFromMatrix(mouse3D.transform);
		}
 
		private function objectClickHandler(event:InteractiveScene3DEvent):void
		{
			resetQuats();
		}
 
		override protected function onRenderTick(event:Event=null):void
		{
			slerp += (1 - slerp) * .1;
			slerpQuat = Quaternion.slerp(planeQuat, mouseQuat, slerp);
 
			plane.transform = slerpQuat.matrix;
			plane.moveBackward(RADIUS);
 
			renderer.renderScene(scene, camera, viewport);
		}
 
	}
}

Tags: , ,

Search

Recommended Books

Speaking at FITC Toronto

 

May 2012
M T W T F S S
« May    
 123456
78910111213
14151617181920
21222324252627
28293031  

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