vis.js is a dynamic, browser-based visualization library
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

178 lines
5.1 KiB

var Point3d = require('./Point3d');
/**
* @class Camera
* The camera is mounted on a (virtual) camera arm. The camera arm can rotate
* The camera is always looking in the direction of the origin of the arm.
* This way, the camera always rotates around one fixed point, the location
* of the camera arm.
*
* Documentation:
* http://en.wikipedia.org/wiki/3D_projection
*/
function Camera() {
this.armLocation = new Point3d();
this.armRotation = {};
this.armRotation.horizontal = 0;
this.armRotation.vertical = 0;
this.armLength = 1.7;
this.cameraOffset = new Point3d();
this.offsetMultiplier = 0.6;
this.cameraLocation = new Point3d();
this.cameraRotation = new Point3d(0.5*Math.PI, 0, 0);
this.calculateCameraOrientation();
}
/**
* Set offset camera in camera coordinates
* @param {Number} x offset by camera horisontal
* @param {Number} y offset by camera vertical
*/
Camera.prototype.setOffset = function(x, y) {
var abs = Math.abs,
sign = Math.sign,
mul = this.offsetMultiplier,
border = this.armLength * mul;
if (abs(x) > border) {
x = sign(x) * border;
}
if (abs(y) > border) {
y = sign(y) * border;
}
this.cameraOffset.x = x;
this.cameraOffset.y = y;
this.calculateCameraOrientation();
};
/**
* Get camera offset by horizontal and vertical
*/
Camera.prototype.getOffset = function() {
return this.cameraOffset;
};
/**
* Set the location (origin) of the arm
* @param {Number} x Normalized value of x
* @param {Number} y Normalized value of y
* @param {Number} z Normalized value of z
*/
Camera.prototype.setArmLocation = function(x, y, z) {
this.armLocation.x = x;
this.armLocation.y = y;
this.armLocation.z = z;
this.calculateCameraOrientation();
};
/**
* Set the rotation of the camera arm
* @param {Number} horizontal The horizontal rotation, between 0 and 2*PI.
* Optional, can be left undefined.
* @param {Number} vertical The vertical rotation, between 0 and 0.5*PI
* if vertical=0.5*PI, the graph is shown from the
* top. Optional, can be left undefined.
*/
Camera.prototype.setArmRotation = function(horizontal, vertical) {
if (horizontal !== undefined) {
this.armRotation.horizontal = horizontal;
}
if (vertical !== undefined) {
this.armRotation.vertical = vertical;
if (this.armRotation.vertical < 0) this.armRotation.vertical = 0;
if (this.armRotation.vertical > 0.5*Math.PI) this.armRotation.vertical = 0.5*Math.PI;
}
if (horizontal !== undefined || vertical !== undefined) {
this.calculateCameraOrientation();
}
};
/**
* Retrieve the current arm rotation
* @return {object} An object with parameters horizontal and vertical
*/
Camera.prototype.getArmRotation = function() {
var rot = {};
rot.horizontal = this.armRotation.horizontal;
rot.vertical = this.armRotation.vertical;
return rot;
};
/**
* Set the (normalized) length of the camera arm.
* @param {Number} length A length between 0.71 and 5.0
*/
Camera.prototype.setArmLength = function(length) {
if (length === undefined)
return;
this.armLength = length;
// Radius must be larger than the corner of the graph,
// which has a distance of sqrt(0.5^2+0.5^2) = 0.71 from the center of the
// graph
if (this.armLength < 0.71) this.armLength = 0.71;
if (this.armLength > 5.0) this.armLength = 5.0;
this.setOffset(this.cameraOffset.x, this.cameraOffset.y);
this.calculateCameraOrientation();
};
/**
* Retrieve the arm length
* @return {Number} length
*/
Camera.prototype.getArmLength = function() {
return this.armLength;
};
/**
* Retrieve the camera location
* @return {Point3d} cameraLocation
*/
Camera.prototype.getCameraLocation = function() {
return this.cameraLocation;
};
/**
* Retrieve the camera rotation
* @return {Point3d} cameraRotation
*/
Camera.prototype.getCameraRotation = function() {
return this.cameraRotation;
};
/**
* Calculate the location and rotation of the camera based on the
* position and orientation of the camera arm
*/
Camera.prototype.calculateCameraOrientation = function() {
// calculate location of the camera
this.cameraLocation.x = this.armLocation.x - this.armLength * Math.sin(this.armRotation.horizontal) * Math.cos(this.armRotation.vertical);
this.cameraLocation.y = this.armLocation.y - this.armLength * Math.cos(this.armRotation.horizontal) * Math.cos(this.armRotation.vertical);
this.cameraLocation.z = this.armLocation.z + this.armLength * Math.sin(this.armRotation.vertical);
// calculate rotation of the camera
this.cameraRotation.x = Math.PI/2 - this.armRotation.vertical;
this.cameraRotation.y = 0;
this.cameraRotation.z = -this.armRotation.horizontal;
var xa = this.cameraRotation.x;
var za = this.cameraRotation.z;
var dx = this.cameraOffset.x;
var dy = this.cameraOffset.y;
var sin = Math.sin, cos = Math.cos;
this.cameraLocation.x = this.cameraLocation.x + dx * cos(za) + dy * - sin(za) * cos(xa);
this.cameraLocation.y = this.cameraLocation.y + dx * sin(za) + dy * cos(za) * cos(xa);
this.cameraLocation.z = this.cameraLocation.z + dy * sin(xa);
};
module.exports = Camera;