rotation

Dragging an object to rotate

Thursday, January 15th, 2009 | examples | Comments

The cool thing about this example is you can really just drop any DisplayObject3D in to rotate it around. It’s not super exciting, but I bet many of you will find it useful.


source

package
{
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;
 
	import org.papervision3d.core.math.Matrix3D;
	import org.papervision3d.core.math.Number3D;
	import org.papervision3d.lights.PointLight3D;
	import org.papervision3d.materials.shadematerials.FlatShadeMaterial;
	import org.papervision3d.objects.primitives.Sphere;
	import org.papervision3d.view.BasicView;
 
	[SWF(width="640", height="480", backgroundColor="#000000", frameRate="60")]
	public class Trackball extends BasicView
	{
		private static const FORWARD:Number3D = new Number3D(0, 0, 1);
 
		private var sphere:Sphere;
		private var previousMousePoint:Point = new Point();
		private var isMouseDown:Boolean = false;
 
		public function Trackball()
		{
			var light:PointLight3D = new PointLight3D();
			var flatShadeMaterial:FlatShadeMaterial = new FlatShadeMaterial(light, 0xcc0000, 0x222222);
			sphere = new Sphere(flatShadeMaterial, 500, 32, 24);
 
			scene.addChild(sphere);
			startRendering();
 
			stage.addEventListener(MouseEvent.MOUSE_DOWN, stage_mouseDownHandler);
			stage.addEventListener(MouseEvent.MOUSE_UP, stage_mouseUpHandler);
		}		
 
		private function stage_mouseDownHandler(event:MouseEvent):void
		{
			isMouseDown = true;
		}
 
		private function stage_mouseUpHandler(event:MouseEvent):void
		{
			isMouseDown = false;	
		}
 
		override protected function onRenderTick(event:Event=null):void
		{
			var currentMousePoint:Point = new Point(viewport.containerSprite.mouseX, viewport.containerSprite.mouseY);
 
			if(isMouseDown)
			{
				var difference:Point = currentMousePoint.subtract(previousMousePoint);
	 			var vector:Number3D = new Number3D(difference.x, difference.y, 0);
 
				var rotationAxis:Number3D = Number3D.cross(vector, FORWARD);
				rotationAxis.normalize();
 
				var distance:Number = Point.distance(currentMousePoint, previousMousePoint);
				var rotationMatrix:Matrix3D = Matrix3D.rotationMatrix(rotationAxis.x, -rotationAxis.y, rotationAxis.z, distance/250);
 
				sphere.transform.calculateMultiply3x3(rotationMatrix, sphere.transform);
			}
 
			previousMousePoint = currentMousePoint;
 
			super.onRenderTick(event);
		}
	}
}

Tags: , ,

Rolling a Sphere with Keyboard and Box2DFlash Physics

Thursday, January 15th, 2009 | examples | Comments

You really didn’t think I was just going to leave yesterday’s example with just one ball rolling around, did you? :)

Remember to click the .swf to give it focus. The main rolling ball is randomized, so the .swf will look different each time you open it.


source

The source is a mess. I basically copied and pasted code from my other Box2DFlash examples. The only real new stuff here is using the “gravityOffset” to cancel out gravity and the m_linearVelocity to set the velocity within Box2DFlash.

package
{
	import Box2D.Collision.Shapes.b2CircleDef;
	import Box2D.Collision.Shapes.b2PolygonDef;
	import Box2D.Collision.b2AABB;
	import Box2D.Common.Math.b2Vec2;
	import Box2D.Dynamics.b2Body;
	import Box2D.Dynamics.b2BodyDef;
	import Box2D.Dynamics.b2World;
 
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.ui.Keyboard;
 
	import org.papervision3d.core.math.Matrix3D;
	import org.papervision3d.core.math.Number3D;
	import org.papervision3d.lights.PointLight3D;
	import org.papervision3d.materials.shadematerials.FlatShadeMaterial;
	import org.papervision3d.objects.DisplayObject3D;
	import org.papervision3d.objects.primitives.Sphere;
	import org.papervision3d.view.BasicView;
 
	[SWF(width="640", height="480", backgroundColor="#000000", frameRate="60")]
	public class RollingASphereWithTheKeyboardAndBox2D extends BasicView
	{
		private static const FORWARD:Number3D = new Number3D(0, 0, 1);
		private var WORLD_SCALE:Number = 30;
		private var WIDTH:Number = 640;
		private var HEIGHT:Number = 480;
 
		private var world:b2World;
 
		private var iterations:int = 10;
		private var timeStep:Number = 1.0/30.0;
 
		private var mainBody:b2Body;
 
 		private var isDown:Boolean = false;
		private var isUp:Boolean = false;
		private var isLeft:Boolean = false;
		private var isRight:Boolean = false;
 
		public function RollingASphereWithTheKeyboardAndBox2D()
		{
			setupPapervision3D();
			createWorld();
			createFloor();
			createCeiling();
			createWalls();
			createShapes();
 
			startRendering();
 
			stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
			stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
		}
 
		private function keyDownHandler(event:KeyboardEvent):void
		{
			switch(event.keyCode)
			{
				case Keyboard.DOWN:
					isDown = true;
					break;
				case Keyboard.UP:
					isUp = true;
					break;
				case Keyboard.LEFT:
					isLeft = true;
					break;
				case Keyboard.RIGHT:
					isRight = true;
					break;
			}
		}
 
		private function keyUpHandler(event:KeyboardEvent):void
		{
			switch(event.keyCode)
			{
				case Keyboard.DOWN:
					isDown = false;
					break;
				case Keyboard.UP:
					isUp = false;
					break;
				case Keyboard.LEFT:
					isLeft = false;
					break;
				case Keyboard.RIGHT:
					isRight = false;
					break;
			}
		}
 
 
		private function createWalls():void
		{
			 var wallShapeDef:b2PolygonDef = new b2PolygonDef();
			var wallBodyDef:b2BodyDef = new b2BodyDef();
			var wall:b2Body;
 
			//Left and Right Shape Definition
			wallShapeDef.SetAsBox(100/WORLD_SCALE, (HEIGHT+40)/WORLD_SCALE/2);
 
			// Left
			wallBodyDef.position = new b2Vec2(-95 / WORLD_SCALE, HEIGHT/WORLD_SCALE/2);
			wall = world.CreateBody(wallBodyDef);
			wall.CreateShape(wallShapeDef);
 
			// Right
			wallBodyDef.position = new b2Vec2((WIDTH+95) / WORLD_SCALE, HEIGHT/WORLD_SCALE/2);
			wall = world.CreateBody(wallBodyDef);
			wall.CreateShape(wallShapeDef);
		}
 
		private function setupPapervision3D():void
		{
			camera.y = -300;
			camera.z = -300;
		}
 
		private function createWorld():void {
			var worldBounds:b2AABB = new b2AABB();
			worldBounds.lowerBound = new b2Vec2( 0, 0 );
			worldBounds.upperBound = new b2Vec2(WIDTH/WORLD_SCALE, HEIGHT/WORLD_SCALE);
 
 			var gravity:b2Vec2 = new b2Vec2(0.0, 10.0);
			var sleep:Boolean = true;
 
			world = new b2World(worldBounds, gravity, sleep);
		}
 
		private function createFloor():void
		{
			// Create border of boxes
			var floorShapeDef:b2PolygonDef = new b2PolygonDef();
			var floorBodyDef:b2BodyDef = new b2BodyDef();
			var floor:b2Body;
 
			//bottom shape definition
			floorShapeDef.SetAsBox((WIDTH+40)/WORLD_SCALE/2, 100/WORLD_SCALE);
 
			// Bottom
			floorBodyDef.position = new b2Vec2(WIDTH/WORLD_SCALE/2, (HEIGHT+95)/WORLD_SCALE);
			floor = world.CreateBody(floorBodyDef);
			floor.CreateShape(floorShapeDef);
 
			floor.SetMassFromShapes();
		}
 
		private function createCeiling():void
		{
			var ceilingShapeDef:b2PolygonDef = new b2PolygonDef();
			var ceilingBodyDef:b2BodyDef = new b2BodyDef();
			var ceiling:b2Body;
			//Top and bottom shape definition
			ceilingShapeDef.SetAsBox((WIDTH+40)/WORLD_SCALE/2, 100/WORLD_SCALE);
 
			// Top
			ceilingBodyDef.position = new b2Vec2(WIDTH/WORLD_SCALE/2, -95/WORLD_SCALE);
			ceiling = world.CreateBody(ceilingBodyDef);
			ceiling.CreateShape(ceilingShapeDef);
		}
 
		private function createShapes():void
		{
			var light:PointLight3D = new PointLight3D();
			for (var i:Number = 0; i < 20; i++)
			{
				//radius for physics circle and sphere
				var radius:Number = Math.random() * 50 + 10;
 
				var bodyDef:b2BodyDef = new b2BodyDef();
				//random position toward the top of the stage
				bodyDef.position = new b2Vec2(Math.random() * WIDTH / WORLD_SCALE, Math.random() * HEIGHT /WORLD_SCALE);
 
				var body:b2Body = world.CreateBody(bodyDef);
 
				var shapeDef:b2CircleDef = new b2CircleDef();
				shapeDef.radius = radius/WORLD_SCALE;
				shapeDef.density = 1;
				shapeDef.friction = .7;
				shapeDef.restitution = .7;
				body.CreateShape(shapeDef);
				body.SetMassFromShapes();
 				var flatShadeMaterial:FlatShadeMaterial = new FlatShadeMaterial(light, Math.random() * 0xffffff, 0x111111);
				var sphere:Sphere = new Sphere(flatShadeMaterial, radius);
 
				scene.addChild(sphere);
				body.m_userData = sphere;
 
				mainBody = body;
			}
		}
 
		override protected function onRenderTick(event:Event=null):void
		{
			if(isDown) mainBody.m_linearVelocity.y += .2;
			if(isUp) mainBody.m_linearVelocity.y -= .2;
			if(isLeft) mainBody.m_linearVelocity.x -= .2;
			if(isRight) mainBody.m_linearVelocity.x += .2;
 
			//sets the position of any DisplayObject3D to the body position
			for (var bb:b2Body = world.m_bodyList; bb; bb = bb.m_next)
			{
				var gravityOffset:b2Vec2 = world.m_gravity.Copy();
				gravityOffset.Multiply(-bb.m_mass);
				bb.ApplyForce(gravityOffset, bb.GetWorldCenter() );
                if (bb.m_userData is DisplayObject3D)
                {
                        bb.m_userData.x = bb.GetPosition().x * WORLD_SCALE - WIDTH * .5;
                        bb.m_userData.y = -bb.GetPosition().y * WORLD_SCALE + HEIGHT * .5;
                        var distance:Number = Math.sqrt(bb.m_linearVelocity.x * bb.m_linearVelocity.x + bb.m_linearVelocity.y * bb.m_linearVelocity.y);
 
						var rotationAxis:Number3D = Number3D.cross(new Number3D(bb.m_linearVelocity.x, bb.m_linearVelocity.y, 0), FORWARD);
						rotationAxis.normalize();
 
						var rotationMatrix:Matrix3D = Matrix3D.rotationMatrix(rotationAxis.x, -rotationAxis.y, rotationAxis.z, distance/30);
 
						bb.m_userData.transform.calculateMultiply3x3(rotationMatrix, bb.m_userData.transform);
                }
			}
			renderer.renderScene(scene, camera, viewport);
			world.Step(timeStep, iterations);
		}
	}
}

Tags: , , ,

Rolling a sphere with the keyboard

Wednesday, January 14th, 2009 | examples | Comments

Jim Foley pinged me and said he’s running a contest about creating a pv3d soccer ball:

http://madvertices.yuku.com/topic/11/master/1/?page=1

The contest made me think up this little example (make sure you click on the .swf to give it keyboard focus):


source

package
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.ui.Keyboard;
 
	import org.papervision3d.core.math.Matrix3D;
	import org.papervision3d.core.math.Number3D;
	import org.papervision3d.lights.PointLight3D;
	import org.papervision3d.materials.shadematerials.FlatShadeMaterial;
	import org.papervision3d.objects.primitives.Sphere;
	import org.papervision3d.view.BasicView;
 
	[SWF(width="640", height="480", backgroundColor="#000000", frameRate="60")]
	public class RollingASphereWithTheKeyboard extends BasicView
	{
		private static const UP:Number3D = new Number3D(0, 1, 0);
 
		private var sphere:Sphere;
		private var velocity:Number3D = new Number3D();
		private var friction:Number = .98;
 
		private var isDown:Boolean = false;
		private var isUp:Boolean = false;
		private var isLeft:Boolean = false;
		private var isRight:Boolean = false;
 
		public function RollingASphereWithTheKeyboard()
		{
			//move camera up to look down on sphere
			camera.y = 300;
 
			//create a faux horizon line
			var whiteBackground:Sprite = new Sprite();
			whiteBackground.graphics.beginFill(0xeeeeee);
			whiteBackground.graphics.drawRect(0, 0, width, 140);
			whiteBackground.graphics.endFill();
			addChildAt(whiteBackground, 0);
 
			var light:PointLight3D = new PointLight3D();
			var flatShadeMaterial:FlatShadeMaterial = new FlatShadeMaterial(light, 0xcc0000, 0x222222);
			sphere = new Sphere(flatShadeMaterial, 100, 16, 8);
 
			scene.addChild(sphere);
			startRendering();
 
			stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
			stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
		}
 
		private function keyDownHandler(event:KeyboardEvent):void
		{
			switch(event.keyCode)
			{
				case Keyboard.DOWN:
					isDown = true;
					break;
				case Keyboard.UP:
					isUp = true;
					break;
				case Keyboard.LEFT:
					isLeft = true;
					break;
				case Keyboard.RIGHT:
					isRight = true;
					break;
			}
		}
 
		private function keyUpHandler(event:KeyboardEvent):void
		{
			switch(event.keyCode)
			{
				case Keyboard.DOWN:
					isDown = false;
					break;
				case Keyboard.UP:
					isUp = false;
					break;
				case Keyboard.LEFT:
					isLeft = false;
					break;
				case Keyboard.RIGHT:
					isRight = false;
					break;
			}
		}
 
		override protected function onRenderTick(event:Event=null):void
		{
			if(isDown) velocity.z -= .5;
			if(isUp) velocity.z += .5;
			if(isLeft) velocity.x -= .5;
			if(isRight) velocity.x += .5;
 
			//gradually slow down velocity
			velocity.multiplyEq(friction);
 
			sphere.x += velocity.x;
			sphere.z += velocity.z;
 
			//where the ball is headed
			var distance:Number = Math.sqrt(velocity.x * velocity.x + velocity.z * velocity.z);
 
 			//Since the ball is rolling around back, forth, left, right
 			//it's rolling on the "XZ plane". Ignore the ball and think how
 			//the XZ plane would rotate around the y-axis (just like rotationY) 
 			//which is defined here as "UP". So you find the "cross" (the axis
 			//the ball will rotate around) by finding where the ball
 			//is heading and the axis the of the plane the ball is rolling on.
 			//I hope that makes sense :)
			var rotationAxis:Number3D = Number3D.cross(velocity, UP);
			rotationAxis.normalize();
 
			//create a matrix from the axis and the angle 
			var rotationMatrix:Matrix3D = Matrix3D.rotationMatrix(rotationAxis.x, rotationAxis.y, rotationAxis.z, distance/100);
 
 			//apply the rotation to the ball
			sphere.transform.calculateMultiply3x3(rotationMatrix, sphere.transform);
 
			super.onRenderTick(event);
		}
	}
}

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

Search

Recommended Books

Speaking at FITC Toronto

 

February 2012
M T W T F S S
« May    
 12345
6789101112
13141516171819
20212223242526
272829  

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