PDA

View Full Version : Rotating in Papervision



trundrumbalind
June 21st, 2009, 09:03 AM
Hi there, I've got a globe which I'm adding markers too and then I allow the user to spin the globe by click-dragging it. Actually, the globe and markers don't move, the camera moves around them. Anyways, what I need is to be able to spin the camera around to a markers position when it's clicked on. I'm close but I just can't figure out the formula! If you can help, that'd be great. Here's my source code (shortened)...



package
{
import flash.display.BitmapData;
import flash.display.Loader;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.net.URLRequest;

import org.papervision3d.core.math.Number3D;
import org.papervision3d.events.InteractiveScene3DEvent;
import org.papervision3d.materials.BitmapMaterial;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.primitives.Sphere;
import org.papervision3d.view.BasicView;

import com.atticmedia.console.C;

import gs.TweenLite;

public class DocumentClass extends BasicView
{
protected var latitudeDegreeOffset:Number = 90;
protected var longitudeDegreeOffset:Number = 15;

protected var cameraTarget:DisplayObject3D;
protected var globe:Sphere;
protected var globeMouseDiffX:Number = 0;
protected var globeMouseDiffY:Number = 0;
protected var mouseDown:Boolean = false;
private var _texture : Loader;
private var _marker : Marker;
private var markerVector : Number3D;
public function DocumentClass( viewportWidth:Number=1024, viewportHeight:Number=768, scaleToStage:Boolean=true, interactive:Boolean=true, cameraType: String = "FREE" )
{
//Setup the basic view.
super( viewportWidth, viewportHeight, scaleToStage, interactive, cameraType);

var urlRequest : URLRequest = new URLRequest("assets/earthmap1k.jpg");
_texture = new Loader();
_texture.contentLoaderInfo.addEventListener(Event. COMPLETE, init);
_texture.load(urlRequest);
}

protected function init(e : Event):void
{
var bitmapData : BitmapData = new BitmapData(_texture.width, _texture.height);
bitmapData.draw(_texture);

var earthMaterial:BitmapMaterial = new BitmapMaterial(bitmapData);

startRendering();

//Create a null object for the camera to copy.
cameraTarget = new DisplayObject3D();
scene.addChild( cameraTarget );

//Rotate the camera target to have the camera face America.
cameraTarget.yaw( 180 );
camera.focus = 1100;
camera.zoom = 1;

//Create the globe.
globe = new Sphere(earthMaterial, 320, 32, 32);
globe.y = 0;
scene.addChild( globe );

//Listen for mouse events.
addEventListener( MouseEvent.MOUSE_DOWN, mouseDownHandler );
addEventListener( MouseEvent.MOUSE_UP, mouseUpHandler );
addEventListener( MouseEvent.ROLL_OUT, mouseUpHandler );

// Add a marker
addMarker();
}

protected override function onRenderTick( event:Event=null ):void
{
if( mouseDown )
{
//Set the target rotation properties for the camera based on the mouse position.
var rotationY:Number = -( -mouseX - globeMouseDiffX );
var rotationX:Number = -( mouseY - globeMouseDiffY );

//Tween the null object.
TweenLite.to(cameraTarget, 2, {rotationY: rotationY, rotationX: rotationX});
}

//Copy the null object's transform into the camera.
camera.copyTransform( cameraTarget );

//Reposition the camera away from the globe and null object.
camera.moveBackward( 1300 );

//Render as usual
super.onRenderTick( event );
}

protected function mouseDownHandler( evt:MouseEvent ):void
{
//Track the amount the mouse has moved.
globeMouseDiffX = -mouseX + cameraTarget.rotationY;
globeMouseDiffY = mouseY + cameraTarget.rotationX;
mouseDown = true;
}

protected function mouseUpHandler( evt:MouseEvent ):void
{
mouseDown = false;
}

private function markerClickHandler( e:InteractiveScene3DEvent ):void
{
}

private function addMarker() : void
{
_marker = new Marker();
placeMarker( _marker, 54, 5 );
}

private function translateGeoCoords( latitude:Number, longitude:Number, radius:Number ):Number3D
{
//Convert latitude and longitude to radians.
latitude = Math.PI * latitude / 180;
longitude = Math.PI * longitude / 180;

//Adjust latitude and longitude by radians.
latitude -= ( latitudeDegreeOffset * ( Math.PI/180 ) ); // offset latitude by n degrees (in radians).
longitude -= ( longitudeDegreeOffset * ( Math.PI/180 ) ); // offset longitude by n degrees (in radians).

var x:Number = radius * Math.sin( latitude ) * Math.cos( longitude );
var y:Number = radius * Math.sin( latitude ) * Math.sin( longitude );
var z:Number = radius * Math.cos( latitude );

//Switch z and y (since z is forward) (see the right-hand rule).
return new Number3D( x, z, y );
}

protected function placeMarker( marker:Marker, latitude:Number, longitude:Number ):void
{
//Translate the geo coordinates to 3D coordinates.
markerVector = translateGeoCoords( latitude, longitude, 320 );

marker.x = markerVector.x;
marker.y = markerVector.y;
marker.z = markerVector.z;

//Align the marker with the globe's surface.
marker.lookAt( DisplayObject3D.ZERO );

globe.addChild( marker );

C.add("ADD LISTENER");
marker._cube.addEventListener( InteractiveScene3DEvent.OBJECT_PRESS, markerClickHandler );
}

}
}

trundrumbalind
June 22nd, 2009, 05:13 AM
Any ideas guys? Sorry to bump but I'm pretty desperate about this now!

roxychaney
August 3rd, 2009, 07:09 PM
it looks like you are using a tween to rotate your display object (cameraTarget) to face the camera, not the other way around?



Hi there, I've got a globe which I'm adding markers too and then I allow the user to spin the globe by click-dragging it. Actually, the globe and markers don't move, the camera moves around them. Anyways, what I need is to be able to spin the camera around to a markers position when it's clicked on. I'm close but I just can't figure out the formula! If you can help, that'd be great. Here's my source code (shortened)...



package
{
import flash.display.BitmapData;
import flash.display.Loader;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.net.URLRequest;

import org.papervision3d.core.math.Number3D;
import org.papervision3d.events.InteractiveScene3DEvent;
import org.papervision3d.materials.BitmapMaterial;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.primitives.Sphere;
import org.papervision3d.view.BasicView;

import com.atticmedia.console.C;

import gs.TweenLite;

public class DocumentClass extends BasicView
{
protected var latitudeDegreeOffset:Number = 90;
protected var longitudeDegreeOffset:Number = 15;

protected var cameraTarget:DisplayObject3D;
protected var globe:Sphere;
protected var globeMouseDiffX:Number = 0;
protected var globeMouseDiffY:Number = 0;
protected var mouseDown:Boolean = false;
private var _texture : Loader;
private var _marker : Marker;
private var markerVector : Number3D;
public function DocumentClass( viewportWidth:Number=1024, viewportHeight:Number=768, scaleToStage:Boolean=true, interactive:Boolean=true, cameraType: String = "FREE" )
{
//Setup the basic view.
super( viewportWidth, viewportHeight, scaleToStage, interactive, cameraType);

var urlRequest : URLRequest = new URLRequest("assets/earthmap1k.jpg");
_texture = new Loader();
_texture.contentLoaderInfo.addEventListener(Event. COMPLETE, init);
_texture.load(urlRequest);
}

protected function init(e : Event):void
{
var bitmapData : BitmapData = new BitmapData(_texture.width, _texture.height);
bitmapData.draw(_texture);

var earthMaterial:BitmapMaterial = new BitmapMaterial(bitmapData);

startRendering();

//Create a null object for the camera to copy.
cameraTarget = new DisplayObject3D();
scene.addChild( cameraTarget );

//Rotate the camera target to have the camera face America.
cameraTarget.yaw( 180 );
camera.focus = 1100;
camera.zoom = 1;

//Create the globe.
globe = new Sphere(earthMaterial, 320, 32, 32);
globe.y = 0;
scene.addChild( globe );

//Listen for mouse events.
addEventListener( MouseEvent.MOUSE_DOWN, mouseDownHandler );
addEventListener( MouseEvent.MOUSE_UP, mouseUpHandler );
addEventListener( MouseEvent.ROLL_OUT, mouseUpHandler );

// Add a marker
addMarker();
}

protected override function onRenderTick( event:Event=null ):void
{
if( mouseDown )
{
//Set the target rotation properties for the camera based on the mouse position.
var rotationY:Number = -( -mouseX - globeMouseDiffX );
var rotationX:Number = -( mouseY - globeMouseDiffY );

//Tween the null object.
TweenLite.to(cameraTarget, 2, {rotationY: rotationY, rotationX: rotationX});
}

//Copy the null object's transform into the camera.
camera.copyTransform( cameraTarget );

//Reposition the camera away from the globe and null object.
camera.moveBackward( 1300 );

//Render as usual
super.onRenderTick( event );
}

protected function mouseDownHandler( evt:MouseEvent ):void
{
//Track the amount the mouse has moved.
globeMouseDiffX = -mouseX + cameraTarget.rotationY;
globeMouseDiffY = mouseY + cameraTarget.rotationX;
mouseDown = true;
}

protected function mouseUpHandler( evt:MouseEvent ):void
{
mouseDown = false;
}

private function markerClickHandler( e:InteractiveScene3DEvent ):void
{
}

private function addMarker() : void
{
_marker = new Marker();
placeMarker( _marker, 54, 5 );
}

private function translateGeoCoords( latitude:Number, longitude:Number, radius:Number ):Number3D
{
//Convert latitude and longitude to radians.
latitude = Math.PI * latitude / 180;
longitude = Math.PI * longitude / 180;

//Adjust latitude and longitude by radians.
latitude -= ( latitudeDegreeOffset * ( Math.PI/180 ) ); // offset latitude by n degrees (in radians).
longitude -= ( longitudeDegreeOffset * ( Math.PI/180 ) ); // offset longitude by n degrees (in radians).

var x:Number = radius * Math.sin( latitude ) * Math.cos( longitude );
var y:Number = radius * Math.sin( latitude ) * Math.sin( longitude );
var z:Number = radius * Math.cos( latitude );

//Switch z and y (since z is forward) (see the right-hand rule).
return new Number3D( x, z, y );
}

protected function placeMarker( marker:Marker, latitude:Number, longitude:Number ):void
{
//Translate the geo coordinates to 3D coordinates.
markerVector = translateGeoCoords( latitude, longitude, 320 );

marker.x = markerVector.x;
marker.y = markerVector.y;
marker.z = markerVector.z;

//Align the marker with the globe's surface.
marker.lookAt( DisplayObject3D.ZERO );

globe.addChild( marker );

C.add("ADD LISTENER");
marker._cube.addEventListener( InteractiveScene3DEvent.OBJECT_PRESS, markerClickHandler );
}

}
}