@threejs-addons/threejs-addons
Version:
free & opensource threejs addons to boost productivity
271 lines (218 loc) • 9.2 kB
text/typescript
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);
}
}