UNPKG

@threejs-addons/threejs-addons

Version:

free & opensource threejs addons to boost productivity

271 lines (218 loc) 9.2 kB
import { Vector3 } from 'three/src/math/Vector3'; import { Quaternion } from 'three/src/math/Quaternion'; import { calculateVelocity } from "../../utils/helpers"; import { CameraControllerType } from "../../types"; import { TranslationController } from "./translation-controller"; import { RapierColliderController } from "./rapier-character-controller"; import { CameraController } from "./camera-controller"; interface ControllerAPI { options: any; target: any; _target: any; setTarget(target: any): void; update(delta: number, updateController?: boolean): void; translateXDirection: boolean; setTranslateXDirection(state: boolean, value: number): void; handleTranslateXDirection(): void; translateYDirection: boolean; setTranslateYDirection(state: boolean, value: number): void; handleTranslateYDirection(): void; translateZDirection: boolean; setTranslateZDirection(state: boolean, value: number): void; handleTranslateZDirection(): void; translateXYZDirection: boolean; setTranslateXYZDirection(state: boolean, direction: Vector3): void; handleTranslateXYZDirection(): void; position: Vector3; rotation: Quaternion; velocity: Vector3; direction: Vector3; delta: number; SPEED_UP_CONSTANT: number; SLOW_DOWN_CONSTANT: number; speedFactor: number; desiredMovementVector: Vector3; desiredVelocityVector: Vector3; cameraController?: CameraControllerType; RCC?: RapierColliderController; CCC?: CameraController; TCC?: TranslationController; setRCC(RCC: RapierColliderController): void; setCCC(CCC: CameraController): void; setTCC(TCC: TranslationController): void; updateSpeedFactor(increment: number): void; setSpeedFactor(speedFactor: number): void; /** static methods */ } export class BaseController implements ControllerAPI { options: any; target: any; _target: any; translateXDirection: boolean = false; translateYDirection: boolean = false; translateZDirection: boolean = false; translateXYZDirection: boolean = false; direction: Vector3 = new Vector3(0, 0, 0); position: Vector3 = new Vector3(0, 0, 0); rotation: Quaternion = new Quaternion(0, 0, 0, 0); velocity: Vector3 = new Vector3(0, 0, 0); delta: number = 0; SPEED_UP_CONSTANT: number = 400; SLOW_DOWN_CONSTANT: number = 10; speedFactor: number = 0.15; desiredMovementVector: Vector3 = new Vector3(0,0,0); desiredVelocityVector: Vector3 = new Vector3(0,0,0); cameraController?: CameraControllerType; RCC?: RapierColliderController; CCC?: CameraController; TCC?: TranslationController; constructor({ CCC, RCC, TCC, target, options }: { target: any, options: object, CCC?: CameraController, RCC?: RapierColliderController, TCC?: TranslationController }) { if(target) this.setTarget(target); if(options) this.options = options; if(CCC) this.setCCC(CCC); if(RCC) this.setRCC(RCC); if(TCC) this.setTCC(TCC); } /** * @description setup rapier coontroller class instance * @param RCC RapierColliderController */ setRCC(RCC: RapierColliderController){ this.RCC = RCC; } /** * @description setup up camera controller class instance * @param CCC CameraController * */ setCCC(CCC: CameraController){ this.CCC = CCC; } /** * @description setup up translation controller class instance * @param TCC TranslationController * */ setTCC(TCC: TranslationController){ this.TCC = TCC; } /** * @description set speedfactor * @param speedFactor: number */ setSpeedFactor(speedFactor: number): void { this.speedFactor = speedFactor; } updateSpeedFactor(increment: number): void { this.speedFactor = Math.max(0.01, Math.min((this.speedFactor + increment), 1)); } /** * @description sets camera controller */ setCameraController(cameraController: CameraControllerType) { this.cameraController = cameraController; } /** @description states whether or not we should translate target in x direction */ setTranslateXDirection(state: boolean, value: number) { this.translateXDirection = state; this.direction = new Vector3(value,0,0); } /** @description states whether or not we should translate target in y direction */ setTranslateYDirection(state: boolean, value: number) { this.translateYDirection = state; this.direction = new Vector3(0,value,0); } /** @description states whether or not we should translate target in z direction */ setTranslateZDirection(state: boolean, value: number) { this.translateZDirection = state; this.direction = new Vector3(0,0,value); } /** * @description states whether or not we should translate target in x, y, and z directions * @remarks perfect for applying forces/impulses * */ setTranslateXYZDirection(state: boolean, direction: Vector3) { this.translateXYZDirection = state; this.direction = direction; } /** * @deprecated * @param self * @returns */ static computeTranslationXDirection(self: any): Vector3 { let position = new Vector3(self.target.position.x, self.target.position.y, self.target.position.z); const velocity = calculateVelocity(self); velocity.multiplyScalar(self.delta); if(self.cameraController) velocity.applyQuaternion(self.cameraController.camera.quaternion); position.add(velocity) return position; } /** * * @param * @returns */ static computeTranslationXYZDirection({ translation, direction, SPEED_UP_CONSTANT, delta, cameraController, speedFactor }: { translation: Vector3, direction: Vector3, SPEED_UP_CONSTANT: number, delta: number, speedFactor: number, cameraController?: CameraControllerType | undefined }): { position: Vector3, velocity: Vector3 } | null { const { x, y, z } = translation; const position = new Vector3(x, y, z); const velocity = calculateVelocity({ SPEED_UP_CONSTANT, delta, direction, speedFactor }); velocity.multiplyScalar(delta); if(cameraController !== undefined) velocity.applyQuaternion(cameraController.camera.quaternion); position.add(velocity); return { position, velocity }; } handleTranslateXDirection(): void { let position = new Vector3(this._target.position.x, this._target.position.y, this._target.position.z); const velocity = calculateVelocity(this); position.add(velocity); this.desiredMovementVector = position } handleTranslateYDirection(): void { } handleTranslateZDirection(): void { } handleTranslateXYZDirection(): void { } updateTargetPosition(): Vector3 | null { if(!this.target) return null; this.target.position.copy(this.desiredMovementVector); return this.target.position; } updateTargetQuaternion(): void { if(!this.cameraController)return; if(!this.target) return; this.target.quaternion.copy(this.cameraController.camera.quaternion); return; } /** * @description sets the target of the controller */ setTarget(target: any) { this._target = target; this.target = target; } resetVelocity() { this.velocity = new Vector3(0,0,0); } /** * @description updates the controller */ update(delta: number, updateController?: boolean) { this.delta = delta; // this.resetVelocity(); //reset on every tick if(this.translateXDirection || this.translateYDirection || this.translateZDirection || this.translateXYZDirection) return this.handleTranslateXYZDirection(); // if(this.translateXDirection) return this.handleTranslateXDirection(); // if(this.translateYDirection) return this.handleTranslateYDirection(); // if(this.translateZDirection) return this.handleTranslateZDirection(); // if(this.translateXYZDirection) return this.handleTranslateXYZDirection(); } updateCameraControllerByMovementVector() { if(!this.cameraController) return; this.cameraController.camera.position.copy(this.desiredMovementVector); // TranslationController.translateControls(this.cameraController, this.desiredMovementVector, this); } updateCameraControllerByVelocityVector() { if(!this.cameraController) return; this.cameraController.camera.position.add(this.desiredVelocityVector); // TranslationController.translateControls(this.cameraController, this.desiredMovementVector, this); } }