UNPKG

@awayjs/scene

Version:
92 lines (71 loc) 2.91 kB
import { Vector3D } from '@awayjs/core'; import { DisplayObject } from '../display/DisplayObject'; import { LookAtController } from '../controllers/LookAtController'; /** * Uses spring physics to animate the target object towards a position that is * defined as the lookAtTarget object's position plus the vector defined by the * positionOffset property. */ export class SpringController extends LookAtController { private _velocity: Vector3D; private _dv: Vector3D; private _stretch: Vector3D; private _force: Vector3D; private _acceleration: Vector3D; private _desiredPosition: Vector3D; /** * Stiffness of the spring, how hard is it to extend. The higher it is, the more "fixed" the cam will be. * A number between 1 and 20 is recommended. */ public stiffness: number; /** * Damping is the spring internal friction, * or how much it resists the "boinggggg" effect. Too high and you'll lose it! * A number between 1 and 20 is recommended. */ public damping: number; /** * Mass of the camera, if over 120 and it'll be very heavy to move. */ public mass: number; /** * Offset of spring center from target in target object space, * ie: Where the camera should ideally be in the target object space. */ public positionOffset: Vector3D = new Vector3D(0, 500, -1000); constructor(targetObject: DisplayObject = null, lookAtObject: DisplayObject = null, stiffness: number = 1, mass: number = 40, damping: number = 4) { super(targetObject, lookAtObject); this.stiffness = stiffness; this.damping = damping; this.mass = mass; this._velocity = new Vector3D(); this._dv = new Vector3D(); this._stretch = new Vector3D(); this._force = new Vector3D(); this._acceleration = new Vector3D(); this._desiredPosition = new Vector3D(); } public update(interpolate: boolean = true): void { if (!this._pLookAtObject || !this._pTargetObject) return; this._pControllerDirty = true; const offs: Vector3D = this._pLookAtObject.transform.matrix3D.deltaTransformVector(this.positionOffset); this._desiredPosition.x = this._pLookAtObject.x + offs.x; this._desiredPosition.y = this._pLookAtObject.y + offs.y; this._desiredPosition.z = this._pLookAtObject.z + offs.z; this._stretch = this._pTargetObject.transform.position.add(this._desiredPosition); this._stretch.scaleBy(-this.stiffness); this._dv.copyFrom(this._velocity); this._dv.scaleBy(this.damping); this._force.x = this._stretch.x - this._dv.x; this._force.y = this._stretch.y - this._dv.y; this._force.z = this._stretch.z - this._dv.z; this._acceleration.copyFrom(this._force); this._acceleration.scaleBy(1 / this.mass); this._velocity.incrementBy(this._acceleration); const position: Vector3D = this._pTargetObject.transform.position.add(this._velocity); this._pTargetObject.transform.moveTo(position.x, position.y, position.z); super.update(); } }