UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

171 lines (170 loc) 6.29 kB
"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) { } }