Skip to content

Instantly share code, notes, and snippets.

@abarax
Last active August 29, 2015 14:13
Show Gist options
  • Save abarax/5ca1f9e0f95002c82571 to your computer and use it in GitHub Desktop.
Save abarax/5ca1f9e0f95002c82571 to your computer and use it in GitHub Desktop.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Camera Rotate
//
// Give the camera rotate tool some mass so that
// camera motion is smoothed out
//
// Directions:
// Adjust the properties of the camera rotation by calling the various
// set____() methods of the cameraController object at the end of the script.
// The script attempts to calculate some defaults values based on the size
// of your model so it might work right out of the box.
//
// Daniel Beardsley, Adobe Systems, Inc.
// March, 2006
//
// Updated: 07/14/06
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
console.println( "* The Javascript 'CameraRotate.js' is now being read..." );
//----------------------------------------------------------------
// Camera Position Class
//----------------------------------------------------------------
function CameraPosition(inTargetPosition, inPitch, inYaw, inDistance)
{
this.TargetPosition = inTargetPosition;
this.CamVector = new Vector3(inPitch, inYaw, inDistance);
this.getPitch = function(){return this.CamVector.x;}
this.getYaw = function(){return this.CamVector.y;}
this.getDistance = function(){return this.CamVector.z;}
this.setPitch = function(val){this.CamVector.x = val;}
this.setYaw = function(val){this.CamVector.y = val;}
this.setDistance = function(val){this.CamVector.z = val;}
}//----------------------------------------------------------------
function SetDefaultCameraPosition(myCameraRotate)
{
var scenebounds = scene.computeBoundingBox();
var scenesize = scenebounds.max.subtract(scenebounds.min).length;
cameraDistance = scenesize * 2;
trueCameraPos = scenebounds.center;
myCameraRotate.setMaxZoom(scenesize*4);
myCameraRotate.setMinZoom(scenesize/2);
myCameraRotate.setCameraPos(new CameraPosition(scenebounds.center, 0, 0, cameraDistance));
}
//---------------------------------------------
//---------------------------------------------
// CameraRotate Class
//---------------------------------------------
//---------------------------------------------
function CameraRotate(inCamera)
{
cameraRotate = this;
//----------------------------------------------------------------
// constants
//----------------------------------------------------------------
var GLOBAL_UP_DIRECTION = new Vector3( 0.0, 0.0, 1.0 );
var DEFAULT_FRICTION = 8.0;
var DEFAULT_MOUSE_FORCE = 0.025;
var DEFAULT_MAX_PITCH = Math.PI * 0.4999; // just a bit less than rotated 90 degrees
var MAX_MOUSE_FORCE = 0.3;
var MAX_YAW_SPEED = 16;
var MIN_SPEED = 0.005;
var PI_2 = Math.PI / 2;
//----------------------------------
// private members
//----------------------------------
var camera = inCamera;
var generalMouseEventHandler = new MouseEventHandler();
//Camera Orientation Variables
var cameraDirection = new Vector3();
var trueCameraPos = new Vector3();
var yaw = 0.0;
var pitch = 0.3;
var targetPosition = new Vector3();
var yawDelta = 0.0;
var pitchDelta = 0.0;
var cameraDistance = 80;
var mouse_XPrevious = 0;
var mouse_YPrevious = 0;
var originalCameraDistance = 0;
//Control parameters
var friction = DEFAULT_FRICTION;
var mouseForce = DEFAULT_MOUSE_FORCE;
var maxPitch = DEFAULT_MAX_PITCH;
var minPitch = 0;
var maxZoom = 0;
var minZoom = 0;
var GlobalZoomScale = 1;
//Effect Flags
var yawCoast = false;
var allowZoom = true;
//Internal State variables
this.ShouldUpdate = true;
var mouseButtonDown = false;
var FOV = inCamera.fov;
var clockwise = true;
//------------------------------------------------------
// General Mouse Event Handler for whole 3D Annotation
//------------------------------------------------------
generalMouseEventHandler.onMouseDown = true;
generalMouseEventHandler.onMouseMove = true;
generalMouseEventHandler.onMouseUp = true;
generalMouseEventHandler.reportAllTargets = false;
generalMouseEventHandler.onEvent = function( event )
{
//-----------------------------------------------
// mouse is dragging left button
//-----------------------------------------------
if ( event.isMouseMove && mouseButtonDown && event.leftButtonDown )
{
yawDelta += ( event.mouseX - mouse_XPrevious ) * mouseForce;
pitchDelta += ( event.mouseY - mouse_YPrevious ) * mouseForce * 0.8;
if (yawDelta > MAX_YAW_SPEED) yawDelta = MAX_YAW_SPEED;
else if (yawDelta < -MAX_YAW_SPEED) yawDelta = -MAX_YAW_SPEED;
mouse_XPrevious = event.mouseX;
mouse_YPrevious = event.mouseY;
cameraRotate.ShouldUpdate = true;
}
//-----------------------------------------------
// mouse is dragging right button - Zoom In/Out
//-----------------------------------------------
if (allowZoom && event.isMouseMove && mouseButtonDown && event.rightButtonDown )
{
var scale = Math.abs(mouse_YPrevious - event.mouseY) / 300 + 1;
if(mouse_YPrevious > event.mouseY)
scale = 1 / scale;
cameraDistance = (scale * scale) * originalCameraDistance;
if(maxZoom > 0)
cameraDistance = Math.min(maxZoom, cameraDistance);
cameraDistance = Math.max(minZoom, cameraDistance);
cameraRotate.ShouldUpdate = true;
}
//-----------------------------------------------
// mouse button is down
//-----------------------------------------------
if ( event.isMouseDown )
{
mouseButtonDown = true;
cameraRotate.saveCameraDistance();
originalCameraDistance = cameraDistance;
mouse_XPrevious = event.mouseX;
mouse_YPrevious = event.mouseY;
}
//-----------------------------------------------
// mouse button is released
//-----------------------------------------------
if ( event.isMouseUp )
{
mouseButtonDown = false;
cameraRotate.saveCameraDistance();
}
}//--------------------------------------------------------
runtime.addEventHandler( generalMouseEventHandler );
//---------------------------------------------
// Grabs the current Camera distance from the target
//---------------------------------------------
this.saveCameraDistance = function()
{
var cameraVector = new Vector3( camera.position );
cameraVector.subtractInPlace( camera.targetPosition );
cameraDistance = cameraVector.length / GlobalZoomScale;
}
//---------------------------------------------
this.registerOwnEventHandler = function()
{
var mytimer = new TimeEventHandler();
mytimer.onEvent = function (event)
{
// if(cameraRotate.ShouldUpdate)
cameraRotate.Update(event.deltaTime);
};
runtime.addEventHandler(mytimer);
}//---------------------------------------------
//---------------------------------------------
this.Update = function( deltaTime )
{
cameraRotate.applyPitchFriction( deltaTime );
if(!yawCoast || mouseButtonDown)
cameraRotate.applyYawFriction( deltaTime );
if(Math.abs(yawDelta) < MIN_SPEED &&
Math.abs(pitchDelta) < MIN_SPEED)
this.ShouldUpdate = false;
//---------------------------------------------
// Update by delta
//---------------------------------------------
if (yaw + (0.5 * deltaTime) < 0.5 && !clockwise){
yaw += 0.5 * deltaTime;
}
else {
clockwise = true;
}
if (yaw - (0.5 * deltaTime) > -0.5 && clockwise) {
yaw -= 0.5 * deltaTime;
} else {
clockwise = false;
}
pitch += pitchDelta * deltaTime;
//---------------------------------------------
// max pitch
//---------------------------------------------
if ( pitch > maxPitch ) { pitch = maxPitch; }
if ( pitch < minPitch ) { pitch = minPitch; }
if(yaw > Math.PI) yaw = yaw - Math.PI*2;
else if(yaw < -Math.PI) yaw = yaw + Math.PI*2;
cameraRotate.updateCameraPosition();
}//---- Update function-----------------------------------------
//--------------------------------------------------
this.updateCameraPosition = function()
{
//-----------------------------------------------
// Update camera direction
//-----------------------------------------------
var x = Math.sin( yaw ) * Math.cos( pitch );
var y = Math.cos( yaw ) * Math.cos( pitch );
var z = Math.sin( pitch );
cameraDirection.set( x, y, z );
//-----------------------------------------------
// Update camera position
//-----------------------------------------------
trueCameraPos.set(targetPosition);
trueCameraPos.addScaledInPlace(cameraDirection, cameraDistance * GlobalZoomScale);
camera.up.set(targetPosition.x, targetPosition.y, targetPosition.z + cameraDistance);
camera.position.set(trueCameraPos);
camera.targetPosition.set(targetPosition);
}//--------------------------------------------------
//--------------------------------------------------
this.setCameraPos = function(CamPos)
{
yaw = CamPos.getYaw();
cameraDistance = CamPos.getDistance();
pitch = CamPos.getPitch();
if (CamPos.TargetPosition != null)
targetPosition = CamPos.TargetPosition;
cameraRotate.updateCameraPosition();
}//--------------------------------------------------
//--------------------------------------------------
this.getCameraPos = function(CamPos)
{
return new CameraPosition(targetPosition, pitch, yaw, cameraDistance);
}//--------------------------------------------------
//--------------------------------------------------
this.applyYawFriction = function( deltaTime )
{
yawDelta *= Math.max(0, 1.0 - ( friction * deltaTime ));
}//-------------------------------------------------
//---------------------------------------------------
this.applyPitchFriction = function( deltaTime )
{
pitchDelta *= Math.max(0, 1.0 - ( friction * deltaTime ));
}//--------------------------------------------------
//----------------------------------------------------
// FOV = Camera Field of View
// Expressed in Radians from 0 to PI
// When this is altered, the Camera distance is adjusted
// so that the target remains the same visual size.
//----------------------------------------------------
this.setFOV = function(fov)
{
var oldFOV = FOV;
FOV = fov;
camera.fov = fov;
GlobalZoomScale *= Math.tan(oldFOV/2) / Math.tan(fov/2);
this.Update(0.0001);
scene.update();
}//--------------------------------------------------
//----------------------------------------------------
// Max Pitch = Maximum angle between the horizon and
// the camera. Expressed in Radians from -PI/2 to PI/2
// PI/2 = 90 degrees up from horizontal (looking down the -z axis)
// -PI/2 = 90 degrees down from horizontal (looking up the +z axis)
//----------------------------------------------------
this.setMaxPitch = function( p )
{
p = Math.max(-DEFAULT_MAX_PITCH, p);
p = Math.min(DEFAULT_MAX_PITCH, p);
maxPitch = p;
}//--------------------------------------------------
//----------------------------------------------------
// Min Pitch = Minimum angle between the horizon and
// the camera. Expressed in Radians from -PI/2 to PI/2
// PI/2 = 90 degrees up from horizontal (looking down the -z axis)
// -PI/2 = 90 degrees down from horizontal (looking up the +z axis)
//----------------------------------------------------
this.setMinPitch = function( p )
{
p = Math.max(-DEFAULT_MAX_PITCH, p);
p = Math.min(DEFAULT_MAX_PITCH, p);
minPitch = p;
}//--------------------------------------------------
//----------------------------------------------------
// MouseForce = amount of effect the mouse dragging has on Camera movement.
// 0 - 30 (Default = 2.5)
//----------------------------------------------------
this.setMouseForce = function( f )
{
mouseForce = f/100;
if ( mouseForce < 0.0 )
mouseForce = 0.0;
else if ( mouseForce > MAX_MOUSE_FORCE )
mouseForce = MAX_MOUSE_FORCE;
}//---------------------------------------------------
//----------------------------------------------------
// Friction = How quickly the camera slows to a stop after mouse dragging
// 0 - infinity (Default = 8.0)
//----------------------------------------------------
this.setFriction = function( f )
{
friction = f;
if (friction < 0.0 )
friction = 0.0;
}//----------------------------------------------------
//----------------------------------------------------
// setYawCoast(bool) (Default = false)
// If set to true, the camera will ignore friction in the
// horizontal direction and will continue to orbit it's target
//-----------------------------------------------------
this.setYawCoast = function( b )
{
yawCoast = (b == true);
}//----------------------------------------------------
//----------------------------------------------------
// setAllowZoom(bool) (Default = true)
// Sets wether or not to allow the Camera to zoom in/out
// (i.e. get closer or further from the target)
// When set to true, you can zoom in/out by clicking and
// dragging with the right mouse button held down.
//----------------------------------------------------
this.setAllowZoom = function( allow )
{
allowZoom = (allow == true);
}//----------------------------------------------------
//----------------------------------------------------
// setMinZoom(float) (Default = 0)
// Sets how close the Camera is allowed to get to the
// target in the same units as the scene.
//----------------------------------------------------
this.setMinZoom = function( z )
{
minZoom = Math.max(0, z);
}//--------------------------------------------------
//----------------------------------------------------
// setMaxZoom(float) (Default = 0)
// Sets how far the Camera is allowed to get from the
// target in the same units as the scene.
// Setting this to 0 = No Maximum Zoom
//----------------------------------------------------
this.setMaxZoom = function( z )
{
maxZoom = Math.max(0, z);
}//--------------------------------------------------
//---------------------------------------------------
// This will be used in a future release
//---------------------------------------------------
/*
this.printCameraView = function()
{
console.println("viewManager.AddView('View"+ Math.round(Math.random()*1000) +"', TargetPos, "+pitch+", "+yaw+", "+cameraDistance+");");
}
*/
}//--------------------------------------------------------------
cameraController = new CameraRotate(scene.cameras.getByIndex(0));
SetDefaultCameraPosition(cameraController);
cameraController.registerOwnEventHandler();
console.println( "* The Javascript 'CameraRotate.js' has been read to the end." );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment