Dragging mouse for camera orbit

Wednesday, November 19th, 2008 | examples

This little gem comes from a chat I had a while back with Tim Knip:


source

package
{
	import flash.events.MouseEvent;
 
	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 OrbitingCameraExample extends BasicView
	{
		private var isOribiting:Boolean;
		private var cameraPitch:Number = 90;
		private var cameraYaw:Number = 270;
		private var cameraTarget:DisplayObject3D = DisplayObject3D.ZERO;
		private var previousMouseX:Number;
		private var previousMouseY:Number;
 
		private var light:PointLight3D;
 
		public function OrbitingCameraExample()
		{
			light = new PointLight3D();
			var material:FlatShadeMaterial = new FlatShadeMaterial(light, 0xcc0000);
 
			var sphere1:Sphere = new Sphere(material, 300, 10, 10);
			var sphere2:Sphere = new Sphere(material, 100, 10, 10);
			sphere2.x = 300;
			sphere2.y = 300;
			sphere2.z = 700
			var sphere3:Sphere = new Sphere(material, 100, 10, 10);
			sphere3.x = 600;
			sphere3.y = -400;
			sphere3.z = -200;
			var sphere4:Sphere = new Sphere(material, 100, 10, 10);
			sphere4.x = -700;
			sphere3.z = -100;
 
			scene.addChild(sphere1);
			scene.addChild(sphere2);
			scene.addChild(sphere3);
			scene.addChild(sphere4);
 
			stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
			stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
			stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
 
			startRendering();
		}
 
		private function onMouseDown(event:MouseEvent):void
		{
			isOribiting = true;
			previousMouseX = event.stageX;
			previousMouseY = event.stageY;
		}
 
		private function onMouseUp(event:MouseEvent):void
		{
			isOribiting = false;
		}
 
		private function onMouseMove(event:MouseEvent):void
		{
			var differenceX:Number = event.stageX - previousMouseX;
			var differenceY:Number = event.stageY - previousMouseY;
 
			if(isOribiting)
			{
				cameraPitch += differenceY;
				cameraYaw += differenceX;
 
				cameraPitch %= 360;
				cameraYaw %= 360;
 
				cameraPitch = cameraPitch > 0 ? cameraPitch : 0.0001;
				cameraPitch = cameraPitch < 90 ? cameraPitch : 89.9999;
 
				previousMouseX = event.stageX;
				previousMouseY = event.stageY;
 
				camera.orbit(cameraPitch, cameraYaw, true, cameraTarget);
			}
		}
	}
}

Tags: , , ,

  • Kevin Burke

    How can I get the Camera3D to orbit with an elliptical path as opposed to perfectly circular? Something like this:
    http://www.kevinburkeportfolio...

    public override function orbit(pitch:Number, yaw:Number, useDegrees:Boolean=true, target:DisplayObject3D=null):void
    {
    target = target || _target;
    target = target || DisplayObject3D.ZERO;

    if(useDegrees)
    {
    pitch *= (Math.PI/180);
    yaw *= (Math.PI/90);
    }

    // Number3D.sub
    var dx :Number = target.world.n14 - this.x;
    var dy :Number = target.world.n24 - this.y;
    var dz :Number = target.world.n34 - this.z;

    // Rotations
    var rx :Number = Math.cos(yaw) * Math.sin(pitch);
    var rz :Number = Math.sin(yaw) * Math.sin(pitch);
    var ry :Number = Math.cos(pitch);

    // Number3D.modulo
    var distance :Number = Math.sqrt(dx*dx+dy*dy+dz*dz);

    // Move to specified location
    this.x = target.world.n14 + (rx * distance);
    this.y = target.world.n24 + (ry * distance);
    this.z = target.world.n34 + (rz * distance);
    this.lookAt(target);
    }

  • Kevin Burke

    For those seeking an easing camera orbit:
    http://blog.yoz.sk/2010/04/smo...

  • Soapstar

    Hey, is there anyway to use this on a .dae model? Ive tried to integrate a dae model but nothing happens! Im sure its something to do with the ' cameraTarget:DisplayObject3D = DisplayObject3D.ZERO; ' ? Should this be different for a dae model?

    thanks

  • NuttyMonk

    Thanks for the tutorial and code examples John.

    i have a couple of suggestions to changes in this code which makes the camera orbit feel more natural and also gives the user the ability to look at the bottom of the objects.

    change these 3 lines of code in the onMouseMove event function...

    cameraPitch += differenceY;
    cameraYaw += differenceX;

    cameraPitch = cameraPitch < 90 ? cameraPitch : 89.9999;

    ...to this...

    cameraPitch -= differenceY;
    cameraYaw -= differenceX;

    cameraPitch = cameraPitch < 180 ? cameraPitch : 179.9999;

    Hope that helps someone.

    Cheers

    NM

  • marco

    if you use a camera.moveRight(5); somewhere, and then rotate ....the movement done by camera.moveRight is resetted.

  • wonky rat

    Hi how would you add an easeOut tween on the camera orbit when the mouse is released... I've tried this but just end up making the object zoom in and out instead of keeping it going round the direction it was going... :S

  • Dan

    Great post! Many thanks. Your "oribiting" solution was very helpful! :p

  • lilly

    when i try to load this as. file into a .fla-file

    import flash.display.Loader;

    var loadSWF:Loader = new Loader();
    loadSWF.x = 100;
    loadSWF.y = 100;

    loadSWF.load(new URLRequest("test.swf"));
    addChild(loadSWF);

    i get this error message:

    TypeError: Error #1009: Cannot access a property or method of a null object reference.
    at papervisionclass()

    i debugged it and it throws the error here:

    stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);

    any idea how to fix it?

  • lilly

    is there a way to fully orbit around the object, in every direction?

  • Mattyluv

    this is awesome, any clues how to add simple throw physics to to the target object?

  • Joe

    following on the above, i attached two events to the stage (Mouse over and out).
    Now when the Mouse is Over an interactive material,the correct 3D Object event is triggered, but at the same time the stage OUT event is triggered altho the mouse never leaved the stage!

  • Joe

    Ok I was messing around with this and found some issues. If the spheres have interactive materials and the viewport is set to interactive. there will be a lot of snapping! for some reason sometimes when the mouse is over an object and we have an event listener the differenceX and differenceY become very large (>200) :/

  • Hi,

    nice but what if we comment those lines:

    //cameraPitch = cameraPitch > 0 ? cameraPitch : 0.0001;
    //cameraPitch = cameraPitch < 90 ? cameraPitch : 89.9999;
    and allow camera to go beyond 0 or 90? when cameraPitch reaches 181 it "jumps" upside down.

    Do you have any idea how to avoid this?

    btw. love your blog :)

  • John Lindquist

    @sascha- It looks like they're just using a bit of easing to smooth out the movement. Maybe I'll put demo together showing just that.

  • Is there anything in PV3D like the HoverCamera3D Wrapper in Away3D? Here's an example where it's used http://www.flashmagazine.com/T... and this works a lot smoother. Any methods to get a similar result in PV3D?

  • John Lindquist

    Just noticed I butchered the spelling of orbiting. Oh well :/

  • BeechyBoy

    Fixdit! It was this on my Collada object's material:
    material.interactive = true;

    Was now using ViewportLayers, so didn't need it.

  • BeechyBoy

    Will do ;) I'll report back on what happens.

  • John Lindquist

    It could be wide variety of things interfering. If you think it's another mouse listener, try disabling it. You know, do the trial and error approach :)

  • BeechyBoy

    It couldn't be another mouse event listener interfering?

  • John Lindquist

    @BeechyBoy - The camera movement should be completely independent of whatever object it's orbiting. If you could post a link where I could check out your project, I could probably look at it tomorrow.

  • BeechyBoy

    I'm having a problem with this when using a Collada model imported into the scene. It's very glitchy and keeps jumping when you move the mouse over the object?

    Here is an example of the traced readout when I drag the mouse straight from right to left, the jump in number is happening when I come into contact with a part of the object:

    Pitch: 130 Yaw: 157
    Pitch: 129 Yaw: 156
    Pitch: 128 Yaw: 155
    Pitch: 128 Yaw: 154
    Pitch: 0.0001 Yaw: -42
    Pitch: 179.9999 Yaw: 150
    Pitch: 178.9999 Yaw: 149
    Pitch: 176.9999 Yaw: 145
    Pitch: 0.0001 Yaw: -42
    Pitch: 179.9999 Yaw: 142
    Pitch: 174.9999 Yaw: 138
    Pitch: 173.9999 Yaw: 137
    Pitch: 172.9999 Yaw: 136
    Pitch: 172.9999 Yaw: 135
    Pitch: 171.9999 Yaw: 135
    Pitch: 170.9999 Yaw: 134

    I extended the rotation code a little, but shouldn't effect it:

    cameraPitch = cameraPitch > 0 ? cameraPitch : 0.0001;
    cameraPitch = cameraPitch < 180 ? cameraPitch : 179.9999;
    trace("Pitch: " + cameraPitch + " Yaw: " + cameraYaw);

    Any clue as to a cause for why it's glitching?
    many thanks

  • Trevor

    dude, your posts are pretty much awesome.

  • BeechyBoy

    Can this be made to orbit fully around the object targeted?

  • Can this be made to orbit fully around the object targeted?

blog comments powered by Disqus

Search

Recommended Books

Speaking at FITC Toronto

 

November 2008
M T W T F S S
    Dec »
 12
3456789
10111213141516
17181920212223
24252627282930

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