@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
171 lines (170 loc) • 6.29 kB
JavaScript
"use strict";
import { Vector3 } from "three";
import { PhysicsPlayerType } from "./PhysicsPlayer";
import { createCharacterController } from "./CharacterController";
import { _physicsRBDResetAll } from "../PhysicsRBD";
import { CorePhysicsAttribute } from "../PhysicsAttribute";
import { CorePath } from "../../geometry/CorePath";
import { CoreCameraControlsController } from "../../camera/CoreCameraControlsController";
const torqueLR = new Vector3();
const torqueFB = new Vector3();
const up = new Vector3(0, 1, 0);
const DEFAULT_FORWARD_DIR = new Vector3(0, 0, -1);
const forwardDir = new Vector3().copy(DEFAULT_FORWARD_DIR);
const currentTarget = new Vector3();
const delta = new Vector3();
const newCameraPosition = new Vector3();
const newTarget = new Vector3();
const LERP = 0.2;
export class CorePlayerPhysics {
constructor(options) {
this.options = options;
// private _inputData: CorePlayerPhysicsInputData = {
// forward: false,
// backward: false,
// left: false,
// right: false,
// run: false,
// jump: false,
// };
// private _computeInputData: CorePlayerPhysicsComputeInputData = {
// speed: 1,
// runAllowed: true,
// runSpeedMult: 2,
// jumpAllowed: true,
// jumpStrength: 1,
// resetIfBelowThreshold: true,
// resetThreshold: -5,
// };
// private _mass = 1;
this._userTorques = new Vector3(0, 0, 0);
this._userImpulses = new Vector3(0, 0, 0);
// private _userForces = new Vector3(0, 0, 0);
// private _velocity = new Vector3(0, 0, 0);
this._correctedMovement = new Vector3(0, 0, 0);
this.startPosition = new Vector3();
this.object = options.object;
this.PhysicsLib = options.PhysicsLib;
this.world = options.world;
this.body = options.body;
this.collider = options.collider;
this.startPosition.copy(this.object.position);
if (options.type == PhysicsPlayerType.CHARACTER_CONTROLLER) {
this.characterController = createCharacterController(this.world, this.object);
this.onGround = this.onGroundWithCharacterController;
this.update = this.updateWithCharacterController;
} else {
this.onGround = this.onGroundWithTorque;
this.update = this.updateWithTorque;
this.initWithTorque(options.worldObject, options.scene);
}
}
dispose() {
if (this.characterController) {
this.world.removeCharacterController(this.characterController);
}
}
// setComputeInputData(data: CorePlayerPhysicsComputeInputData) {
// this._computeInputData.speed = data.speed;
// this._computeInputData.runAllowed = data.runAllowed;
// this._computeInputData.runSpeedMult = data.runSpeedMult;
// this._computeInputData.jumpAllowed = data.jumpAllowed;
// this._computeInputData.jumpStrength = data.jumpStrength;
// }
_computeForwardDirAndUpdateCamera() {
if (!this.cameraAndControls) {
forwardDir.copy(DEFAULT_FORWARD_DIR);
return;
}
const { camera, controlsNode } = this.cameraAndControls;
forwardDir.set(0, 0, -1).unproject(camera).sub(camera.position);
forwardDir.y = 0;
forwardDir.normalize();
if (controlsNode.target && controlsNode.setTarget) {
controlsNode.target(currentTarget);
delta.copy(this.object.position).sub(currentTarget);
newCameraPosition.copy(camera.position).add(delta);
camera.position.lerp(newCameraPosition, LERP);
newTarget.copy(currentTarget).lerp(this.object.position, LERP);
controlsNode.setTarget(newTarget);
}
}
/**
*
* torque
*
*/
initWithTorque(worldObject, scene) {
const cameraPath = CorePhysicsAttribute.getCharacterControllerCameraPath(this.object);
if (cameraPath == null) {
return;
}
const camera = CorePath.findObjectByMaskInObject(`*/${cameraPath}`, worldObject);
if (!camera) {
return;
}
const controlsNode = CoreCameraControlsController.controlsNode({ camera, scene });
if (!controlsNode) {
return;
}
this.cameraAndControls = { camera, controlsNode };
}
onGroundWithTorque() {
return Math.abs(this.body.linvel().y) < 0.1;
}
// setInputDataWithTorque(inputData: CorePlayerPhysicsInputData) {
// this._computeForwardDirAndUpdateCamera();
// // this._inputData.left = inputData.left;
// // this._inputData.right = inputData.right;
// // this._inputData.backward = inputData.backward;
// // this._inputData.forward = inputData.forward;
// }
updateWithTorque(computeInputData, inputData, delta2) {
this._computeForwardDirAndUpdateCamera();
this._userTorques.set(0, 0, 0);
this._userImpulses.set(0, 0, 0);
const running = computeInputData.runAllowed && inputData.run;
if (computeInputData.jumpAllowed && inputData.jump && this.onGround()) {
this._userImpulses.y += computeInputData.jumpStrength * 100;
}
const speed = running ? computeInputData.speed * computeInputData.runSpeedMult : computeInputData.speed;
if (inputData.left && !inputData.right) {
torqueLR.copy(forwardDir).multiplyScalar(-speed);
this._userTorques.add(torqueLR);
} else {
if (inputData.right && !inputData.left) {
torqueLR.copy(forwardDir).multiplyScalar(speed);
this._userTorques.add(torqueLR);
}
}
if (inputData.forward && !inputData.backward) {
torqueFB.copy(forwardDir).cross(up).normalize().multiplyScalar(-speed);
this._userTorques.add(torqueFB);
} else {
if (inputData.backward && !inputData.forward) {
torqueFB.copy(forwardDir).cross(up).normalize().multiplyScalar(speed);
this._userTorques.add(torqueFB);
}
}
if (computeInputData.resetIfBelowThreshold) {
if (this.body.translation().y < computeInputData.resetThreshold) {
_physicsRBDResetAll(this.object, true);
this.body.setTranslation(this.startPosition, true);
}
}
this.body.applyTorqueImpulse(this._userTorques, true);
this.body.applyImpulse(this._userImpulses, true);
}
/**
*
* character controller
*
*/
onGroundWithCharacterController() {
return Math.abs(this._correctedMovement.y) < 0.01;
}
setInputDataWithCharacterController(inputData) {
}
updateWithCharacterController(computeData, inputData, delta2) {
}
}