PerspectiveCamera class
@author mr.doob / http://mrdoob.com/ @author greggman / http://games.greggman.com/ @author zz85 / http://www.lab4games.net/zz85/blog
Ported to Dart from JS by: @author rob silverton / http://www.unwrong.com/
class PerspectiveCamera extends Camera { double fov; double aspect; double _fullWidth; double _fullHeight; double _x; double _y; double _width; double _height; PerspectiveCamera( [this.fov = 50.0, this.aspect = 1.0, near = 0.1, far = 2000.0] ) : super(near, far){ updateProjectionMatrix(); } /** * Uses Focal Length (in mm) to estimate and set FOV * 35mm (fullframe) camera is used if frame size is not specified; * Formula based on http://www.bobatkins.com/photography/technical/field_of_view.html */ void setLens( double focalLength, double frameSize ) { frameSize = frameSize != null ? frameSize : 43.25; // 36x24mm fov = 2.0 * Math.atan( frameSize / ( focalLength * 2.0 ) ); fov = 180.0 / Math.PI * fov; updateProjectionMatrix(); } /** * Sets an offset in a larger frustum. This is useful for multi-window or * multi-monitor/multi-machine setups. * * For example, if you have 3x2 monitors and each monitor is 1920x1080 and * the monitors are in grid like this * * +---+---+---+ * | A | B | C | * +---+---+---+ * | D | E | F | * +---+---+---+ * * then for each monitor you would call it like this * * var w = 1920; * var h = 1080; * var fullWidth = w * 3; * var fullHeight = h * 2; * * --A-- * camera.setOffset( fullWidth, fullHeight, w * 0, h * 0, w, h ); * --B-- * camera.setOffset( fullWidth, fullHeight, w * 1, h * 0, w, h ); * --C-- * camera.setOffset( fullWidth, fullHeight, w * 2, h * 0, w, h ); * --D-- * camera.setOffset( fullWidth, fullHeight, w * 0, h * 1, w, h ); * --E-- * camera.setOffset( fullWidth, fullHeight, w * 1, h * 1, w, h ); * --F-- * camera.setOffset( fullWidth, fullHeight, w * 2, h * 1, w, h ); * * Note there is no reason monitors have to be the same size or in a grid. */ void setViewOffset( double fullWidth, double fullHeight, double x, double y, double width, double height ) { _fullWidth = fullWidth; _fullHeight = fullHeight; _x = x; _y = y; _width = width; _height = height; updateProjectionMatrix(); } void updateProjectionMatrix() { if ( _fullWidth != null ) { double aspect = _fullWidth / _fullHeight; double top = Math.tan( fov * Math.PI / 360.0 ) * near; double bottom = -top; double left = aspect * bottom; double right = aspect * top; double width = ( right - left ).abs(); double height = ( top - bottom ).abs(); setFrustumMatrix(projectionMatrix, left + _x * width / _fullWidth, left + ( _x + width ) * width / _fullWidth, top - ( _y + height ) * height / _fullHeight, top - _y * height / _fullHeight, near, far ); } else { projectionMatrix = makePerspectiveMatrix(fov * (Math.PI / 180), aspect, near, far); } } }
Extends
Object3D > Camera > PerspectiveCamera
Constructors
new PerspectiveCamera([double fov = 50.0, double aspect = 1.0, near = 0.1, far = 2000.0]) #
Creates a new Object instance.
Object instances have no meaningful state, and are only useful through their identity. An Object instance is equal to itself only.
PerspectiveCamera( [this.fov = 50.0, this.aspect = 1.0, near = 0.1, far = 2000.0] ) : super(near, far){ updateProjectionMatrix(); }
Properties
bool frustumCulled #
bool visible = false, castShadow = false, receiveShadow = false, frustumCulled = false
bool isDynamic #
bool get isDynamic => _dynamic;
set isDynamic(bool flag) => _dynamic = flag;
Matrix4 matrixRotationWorld #
Matrix4 matrix, matrixWorld, matrixRotationWorld
bool matrixWorldNeedsUpdate #
bool matrixAutoUpdate = false, matrixWorldNeedsUpdate = false
bool receiveShadow #
bool visible = false, castShadow = false, receiveShadow = false
Operators
Methods
void add(Object3D object) #
void add( Object3D object ) { if ( object == this ) { print( 'THREE.Object3D.add: An object can\'t be added as a child of itself.' ); return; } if ( object.parent != null ) { object.parent.remove( object ); } object.parent = this; children.add( object ); // add to scene Object3D scene = this; while ( scene.parent != null ) { scene = scene.parent; } if ( scene is Scene ) { scene.addObject( object ); } }
void applyMatrix(Matrix4 matrix) #
void applyMatrix ( Matrix4 matrix ) { this.matrix = matrix * this.matrix; this.scale = getScaleFromMatrix( this.matrix ); Matrix4 mat = extractRotation(new Matrix4.identity(), this.matrix ); this.rotation = calcEulerFromRotationMatrix( mat, this.eulerOrder ); this.position = this.matrix.getTranslation(); }
Object3D getChildByName(String name, bool doRecurse) #
Object3D getChildByName( String name, bool doRecurse ) { int c; int cl = children.length; Object3D child, recurseResult; children.forEach((child){ if ( child.name == name ) { return child; } if ( doRecurse ) { recurseResult = child.getChildByName( name, doRecurse ); if ( recurseResult != null ) { return recurseResult; } } }); return null; }
dynamic localToWorld(Vector3 vector) #
localToWorld(Vector3 vector) => vector.applyProjection(matrixWorld);
void lookAt(Vector3 vector) #
void lookAt(Vector3 vector ) { // TODO: Add hierarchy support. makeLookAt(matrix, position, vector, up); if ( rotationAutoUpdate ) { rotation = calcEulerFromRotationMatrix( matrix, eulerOrder ); } }
void remove(Object3D object) #
void remove( Object3D object ) { int index = children.indexOf( object ); if ( index != - 1 ){ object.parent = null; children.removeAt(index); // remove from scene Object3D scene = this; while ( scene.parent != null ) { scene = scene.parent; } if (scene is Scene ) { scene.removeObject( object ); } } }
void setLens(double focalLength, double frameSize) #
Uses Focal Length (in mm) to estimate and set FOV 35mm (fullframe) camera is used if frame size is not specified; Formula based on http://www.bobatkins.com/photography/technical/fieldofview.html
void setLens( double focalLength, double frameSize ) { frameSize = frameSize != null ? frameSize : 43.25; // 36x24mm fov = 2.0 * Math.atan( frameSize / ( focalLength * 2.0 ) ); fov = 180.0 / Math.PI * fov; updateProjectionMatrix(); }
void setViewOffset(double fullWidth, double fullHeight, double x, double y, double width, double height) #
Sets an offset in a larger frustum. This is useful for multi-window or multi-monitor/multi-machine setups.
For example, if you have 3x2 monitors and each monitor is 1920x1080 and the monitors are in grid like this
+---+---+---+ | A | B | C | +---+---+---+ | D | E | F | +---+---+---+
then for each monitor you would call it like this
var w = 1920; var h = 1080; var fullWidth = w * 3; var fullHeight = h * 2;
--A-- camera.setOffset( fullWidth, fullHeight, w * 0, h * 0, w, h ); --B-- camera.setOffset( fullWidth, fullHeight, w * 1, h * 0, w, h ); --C-- camera.setOffset( fullWidth, fullHeight, w * 2, h * 0, w, h ); --D-- camera.setOffset( fullWidth, fullHeight, w * 0, h * 1, w, h ); --E-- camera.setOffset( fullWidth, fullHeight, w * 1, h * 1, w, h ); --F-- camera.setOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );
Note there is no reason monitors have to be the same size or in a grid.
void setViewOffset( double fullWidth, double fullHeight, double x, double y, double width, double height ) { _fullWidth = fullWidth; _fullHeight = fullHeight; _x = x; _y = y; _width = width; _height = height; updateProjectionMatrix(); }
void translate(num distance, Vector3 axis) #
void translate( num distance, Vector3 axis ) { matrix.rotate3( axis ); axis.normalize(); position.add( axis.scale( distance ) ); }
void translateX(num distance) #
void translateX( num distance ) => translate( distance, _vector.setValues( 1.0, 0.0, 0.0 ) );
void translateY(num distance) #
void translateY( num distance ) => translate( distance, _vector.setValues( 0.0, 1.0, 0.0 ) );
void translateZ(num distance) #
void translateZ( num distance ) => translate( distance, _vector.setValues( 0.0, 0.0, 1.0 ) );
void updateMatrix() #
void updateMatrix() { if ( useQuaternion ) { setRotationFromQuaternion( matrix, quaternion ); } else { setRotationFromEuler( matrix, rotation, eulerOrder ); } matrix.setTranslation( position ); if ( scale.x != 1.0 || scale.y != 1.0 || scale.z != 1.0 ) { matrix.scale( scale ); boundRadiusScale = Math.max( scale.x, Math.max( scale.y, scale.z ) ); } matrixWorldNeedsUpdate = true; }
void updateMatrixWorld({bool force: false}) #
void updateMatrixWorld( {bool force: false} ) { if (matrixAutoUpdate) updateMatrix(); // update matrixWorld if ( matrixWorldNeedsUpdate || force ) { if ( parent != null ) { matrixWorld = parent.matrixWorld * matrix; } else { matrixWorld = matrix.clone(); } matrixWorldNeedsUpdate = false; force = true; } // update children children.forEach((c) => c.updateMatrixWorld( force: force ) ); }
void updateProjectionMatrix() #
void updateProjectionMatrix() { if ( _fullWidth != null ) { double aspect = _fullWidth / _fullHeight; double top = Math.tan( fov * Math.PI / 360.0 ) * near; double bottom = -top; double left = aspect * bottom; double right = aspect * top; double width = ( right - left ).abs(); double height = ( top - bottom ).abs(); setFrustumMatrix(projectionMatrix, left + _x * width / _fullWidth, left + ( _x + width ) * width / _fullWidth, top - ( _y + height ) * height / _fullHeight, top - _y * height / _fullHeight, near, far ); } else { projectionMatrix = makePerspectiveMatrix(fov * (Math.PI / 180), aspect, near, far); } }