UNPKG

mlightcad

Version:

A highly customizable standalone view cube addon for three.js

105 lines (89 loc) 2.93 kB
import * as THREE from 'three' interface OrbitControlsLike { target: THREE.Vector3 addEventListener: (eventName: string, listener: () => void) => void removeEventListener: (eventName: string, listener: () => void) => void update(): void } /** * A highly customizable standalone view cube addon for three.js. */ export class SimpleCameraControls { private camera: THREE.PerspectiveCamera | THREE.OrthographicCamera private animating: boolean private turnRate: number private radius: number private q1: THREE.Quaternion private q2: THREE.Quaternion private controls: OrbitControlsLike | undefined private target: THREE.Vector3 private clock: THREE.Clock /** * Construct one instance of view cube helper * @param camera Camera used in your canvas * @param renderer Renderer used in your canvas * @param options Options to customize view cube helper */ constructor(camera: THREE.PerspectiveCamera | THREE.OrthographicCamera) { this.camera = camera this.animating = false this.turnRate = 2 * Math.PI // turn rate in angles per second this.target = new THREE.Vector3() this.q1 = new THREE.Quaternion() this.q2 = new THREE.Quaternion() this.radius = 0 this.clock = new THREE.Clock() } /** * Set associated obit controls * @param controls The associated orbit controls */ setControls(controls: OrbitControlsLike) { if (!controls) return this.controls = controls } /** * Animation loop */ update() { if (this.animating === false) return const delta = this.clock.getDelta() const step = delta * this.turnRate // animate position by doing a slerp and then scaling the position on the unit sphere this.q1.rotateTowards(this.q2, step) this.camera.position .set(0, 0, 1) .applyQuaternion(this.q1) .multiplyScalar(this.radius) .add(this.target) // animate orientation this.camera.quaternion.rotateTowards(this.q2, step) this.camera.updateProjectionMatrix() this.controls?.update() if (this.q1.angleTo(this.q2) <= 0.00001) { this.animating = false this.clock.stop() } } /** * Fly with the target quaterion * @param quaternion */ flyTo(quaternion: THREE.Quaternion) { const focusPoint = new THREE.Vector3() const targetPosition = new THREE.Vector3(0, 0, 1) this.radius = this.camera.position.distanceTo(focusPoint) targetPosition .applyQuaternion(quaternion) .multiplyScalar(this.radius) .add(focusPoint) const dummy = new THREE.Object3D() dummy.position.copy(focusPoint) dummy.lookAt(this.camera.position) this.q1.copy(dummy.quaternion) dummy.lookAt(targetPosition) this.q2.copy(dummy.quaternion) this.animating = true this.clock.start() } }