UNPKG

@polygonjs/polygonjs

Version:

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

425 lines (424 loc) 14.5 kB
"use strict"; import { TypeAssert } from "./../../engine/poly/Assert"; import { PhysicsRBDColliderType, PhysicsRBDType, CorePhysicsAttribute } from "./PhysicsAttribute"; import { Vector3, Quaternion } from "three"; import { CorePhysicsLoaded } from "./CorePhysics"; import { createPhysicsSphere } from "./shapes/RBDSphere"; import { createPhysicsCuboid } from "./shapes/RBDCuboid"; import { createPhysicsCapsule } from "./shapes/RBDCapsule"; import { createPhysicsCone } from "./shapes/RBDCone"; import { createPhysicsCylinder } from "./shapes/RBDCylinder"; import { createPhysicsTriMesh } from "./shapes/RBDTrimesh"; import { createPhysicsConvexHull } from "./shapes/ConvexHull"; import { createPhysicsHeightField } from "./shapes/HeightField"; import { touchRBDProperties, touchRBDProperty } from "../reactivity/RBDPropertyReactivity"; import { OBJECT_TRANSFORM_PROPERTIES, touchObjectProperties } from "../reactivity/ObjectPropertyReactivity"; import { removeFromParent } from "../../engine/poly/PolyOnObjectsAddRemoveHooksController"; import { getRBDFromId, object3DFromRBD } from "./PhysicsWorld"; export var RBDProperty = /* @__PURE__ */ ((RBDProperty2) => { RBDProperty2["ANGULAR_VELOCITY"] = "angVel"; RBDProperty2["LINEAR_VELOCITY"] = "linVel"; RBDProperty2["POSITION"] = "position"; RBDProperty2["ROTATION"] = "rotation"; RBDProperty2["LINEAR_DAMPING"] = "linearDamping"; RBDProperty2["ANGULAR_DAMPING"] = "angularDamping"; RBDProperty2["IS_SLEEPING"] = "isSleeping"; RBDProperty2["IS_MOVING"] = "isMoving"; return RBDProperty2; })(RBDProperty || {}); const tmpV3 = new Vector3(); const currentPos = new Vector3(); const currentLinearVelocity = new Vector3(); const currentAngularVelocity = new Vector3(); const newPos = new Vector3(); const newLinearVelocity = new Vector3(); const newAngularVelocity = new Vector3(); const currentQuaternion = new Quaternion(); const newQuaternion = new Quaternion(); const linearVelocity = new Vector3(); const angularVelocity = new Vector3(); const physicsRBDByRBDHandle = /* @__PURE__ */ new Map(); const worldByRBD = /* @__PURE__ */ new WeakMap(); function _createRBDFromDescAndId(world, rigidBodyDesc, rbdId) { const rigidBody = world.createRigidBody(rigidBodyDesc); const handle = rigidBody.handle; worldByRBD.set(rigidBody, world); physicsRBDByRBDHandle.set(handle, rigidBody); return rigidBody; } function _createRBDFromDescAndObject(world, rigidBodyDesc, object) { const rbdId = CorePhysicsAttribute.getRBDId(object); const rigidBody = _createRBDFromDescAndId(world, rigidBodyDesc, rbdId); CorePhysicsAttribute.setRBDHandle(object, rigidBody.handle); return rigidBody; } function _createRBDFromAttributes(options) { const { PhysicsLib: PhysicsLib2, world, object, rigidBodyById, objectsByRBD, newRBDIds } = options; const type = CorePhysicsAttribute.getRBDType(object); if (type == null) { return; } const rbdType = PhysicsRBDTypeToRigidBodyType(type); if (rbdType == null) { return; } const linearDamping = CorePhysicsAttribute.getLinearDamping(object); const angularDamping = CorePhysicsAttribute.getAngularDamping(object); linearVelocity.set(0, 0, 0); angularVelocity.set(0, 0, 0); CorePhysicsAttribute.getLinearVelocity(object, linearVelocity); CorePhysicsAttribute.getAngularVelocity(object, angularVelocity); const gravityScale = CorePhysicsAttribute.getGravityScale(object); const canSleep = CorePhysicsAttribute.getCanSleep(object); const rigidBodyDesc = new PhysicsLib2.RigidBodyDesc(rbdType); rigidBodyDesc.setTranslation(object.position.x, object.position.y, object.position.z); rigidBodyDesc.setRotation(object.quaternion); rigidBodyDesc.setLinvel(linearVelocity.x, linearVelocity.y, linearVelocity.z); rigidBodyDesc.setAngvel(angularVelocity); if (linearDamping != null) { rigidBodyDesc.setLinearDamping(linearDamping); } if (angularDamping != null) { rigidBodyDesc.setAngularDamping(angularDamping); } if (gravityScale != null) { rigidBodyDesc.setGravityScale(gravityScale); } if (canSleep != null) { rigidBodyDesc.setCanSleep(canSleep); } const rigidBody = _createRBDFromDescAndObject(world, rigidBodyDesc, object); objectsByRBD.set(rigidBody, object); const rbdId = CorePhysicsAttribute.getRBDId(object); if (rbdId) { rigidBodyById.set(rbdId, rigidBody); newRBDIds.add(rbdId); } return rigidBody; } function _createColliderDesc(PhysicsLib2, object) { const colliderType = CorePhysicsAttribute.getColliderType(object); if (!(colliderType != null)) { return; } const colliderDesc = PhysicsRBDCollider(PhysicsLib2, colliderType, object); if (!colliderDesc) { console.error("no collider", object); return; } const restitution = CorePhysicsAttribute.getRestitution(object); const friction = CorePhysicsAttribute.getFriction(object); const density = CorePhysicsAttribute.getDensity(object); if (restitution != null) { colliderDesc.setRestitution(restitution); } if (friction != null) { colliderDesc.setFriction(friction); } if (density != null) { colliderDesc.setDensity(density); } return colliderDesc; } export function _getRBDFromId(rbdId) { const rigidBody = getRBDFromId(rbdId); if (!rigidBody) { return; } return object3DFromRBD(rigidBody); } export function _getRBDFromObject(object) { const handle = CorePhysicsAttribute.getRBDHandle(object); if (handle == null) { return; } return physicsRBDByRBDHandle.get(handle); } export function _getPhysicsWorldFromRBD(object) { const rbd = _getRBDFromObject(object); if (!rbd) { return; } return worldByRBD.get(rbd); } export function _physicsRBDDelete(scene, object) { const handle = CorePhysicsAttribute.getRBDHandle(object); if (handle == null) { return; } const body = physicsRBDByRBDHandle.get(handle); if (!body) { return; } const world = worldByRBD.get(body); if (!world) { return; } world.removeRigidBody(body); worldByRBD.delete(body); physicsRBDByRBDHandle.delete(handle); CorePhysicsAttribute.deleteRBDHandle(object); removeFromParent(scene, object); } export function _physicsCreateRBD(options) { const { PhysicsLib: PhysicsLib2, world, object, rigidBodyById, objectsByRBD, newRBDIds } = options; const rigidBody = _createRBDFromAttributes({ PhysicsLib: PhysicsLib2, world, object, rigidBodyById, objectsByRBD, newRBDIds }); if (!rigidBody) { for (const child of object.children) { _physicsCreateRBD({ PhysicsLib: PhysicsLib2, world, rigidBodyById, objectsByRBD, object: child, newRBDIds }); } return; } let childrenColliderDesc; if (object.children.length > 0) { object.traverse((child) => { if (child != object) { const childColliderDesc = _createColliderDesc(PhysicsLib2, child); if (childColliderDesc) { childrenColliderDesc = childrenColliderDesc || []; childrenColliderDesc.push({ object: child, colliderDesc: childColliderDesc }); } } }); } const colliderDesc = _createColliderDesc(PhysicsLib2, object); if (!(colliderDesc || childrenColliderDesc)) { return; } if (colliderDesc) { world.createCollider(colliderDesc, rigidBody); } if (childrenColliderDesc) { for (const childCollider of childrenColliderDesc) { const collider = world.createCollider(childCollider.colliderDesc, rigidBody); tmpV3.copy(childCollider.object.position); childCollider.object.localToWorld(tmpV3); object.worldToLocal(tmpV3); collider.setTranslationWrtParent(tmpV3); collider.setRotationWrtParent(childCollider.object.quaternion); } } } export function physicsUpdateRBD(object, rigidBody) { const position = rigidBody.translation(); const rotation = rigidBody.rotation(); object.position.set(position.x, position.y, position.z); object.quaternion.set(rotation.x, rotation.y, rotation.z, rotation.w); object.updateMatrix(); updateRBDRefs(object); } const SIM_PROPERTIES = [ "angVel" /* ANGULAR_VELOCITY */, "linVel" /* LINEAR_VELOCITY */, "position" /* POSITION */, "rotation" /* ROTATION */, "isSleeping" /* IS_SLEEPING */, "isMoving" /* IS_MOVING */ ]; function updateRBDRefs(object) { touchRBDProperties(object, SIM_PROPERTIES); touchObjectProperties(object, OBJECT_TRANSFORM_PROPERTIES); } export function _physicsRBDApplyImpulse(object, impulse) { const body = _getRBDFromObject(object); if (!body) { console.warn("no rbd found"); return; } body.applyImpulse(impulse, true); } export function _physicsRBDApplyImpulseAtPoint(object, impulse, point) { const body = _getRBDFromObject(object); if (!body) { console.warn("no rbd found"); return; } body.applyImpulseAtPoint(impulse, point, true); } export function _physicsRBDApplyTorqueImpulse(object, impulse) { const body = _getRBDFromObject(object); if (!body) { console.warn("no rbd found"); return; } body.applyTorqueImpulse(impulse, true); } export function _physicsRBDAddForce(object, force) { const body = _getRBDFromObject(object); if (!body) { console.warn("no rbd found"); return; } body.addForce(force, true); } export function _physicsRBDAddForceAtPoint(object, force, point) { const body = _getRBDFromObject(object); if (!body) { console.warn("no rbd found"); return; } body.addForceAtPoint(force, point, true); } export function _physicsRBDAddTorque(object, torque) { const body = _getRBDFromObject(object); if (!body) { console.warn("no rbd found"); return; } body.addTorque(torque, true); } export function _physicsRBDResetAll(object, wakeup) { const body = _getRBDFromObject(object); if (!body) { console.warn("no rbd found"); return; } body.resetForces(wakeup); body.resetTorques(wakeup); body.setLinvel({ x: 0, y: 0, z: 0 }, wakeup); body.setAngvel({ x: 0, y: 0, z: 0 }, wakeup); } export function _physicsRBDResetForces(object, wakeup) { const body = _getRBDFromObject(object); if (!body) { console.warn("no rbd found"); return; } body.resetForces(wakeup); } export function _physicsRBDResetTorques(object, wakeup) { const body = _getRBDFromObject(object); if (!body) { console.warn("no rbd found"); return; } body.resetTorques(wakeup); } export function _setPhysicsRBDPosition(object, targetPosition, lerp) { const body = _getRBDFromObject(object); if (!body) { console.warn("no rbd found"); return; } const translateFunc = body.isKinematic() ? body.setNextKinematicTranslation.bind(body) : body.setTranslation.bind(body); if (lerp < 1) { const rbdPosition = body.translation(); currentPos.set(rbdPosition.x, rbdPosition.y, rbdPosition.z); newPos.copy(targetPosition); currentPos.lerp(newPos, lerp); translateFunc(currentPos, true); } else { translateFunc(targetPosition, true); } touchRBDProperty(object, "position" /* POSITION */); } export function _setPhysicsRBDRotation(object, targetQuaternion, lerp) { const body = _getRBDFromObject(object); if (!body) { console.warn("no rbd found"); return; } const rotateFunc = body.isKinematic() ? body.setNextKinematicRotation.bind(body) : body.setRotation.bind(body); if (lerp < 1) { const rbdRotation = body.rotation(); currentQuaternion.set(rbdRotation.x, rbdRotation.y, rbdRotation.z, rbdRotation.w); newQuaternion.copy(currentQuaternion); currentQuaternion.slerp(newQuaternion, lerp); rotateFunc(currentQuaternion, true); } else { rotateFunc(targetQuaternion, true); } touchRBDProperty(object, "rotation" /* ROTATION */); } export function _setPhysicsRBDLinearVelocity(object, targetVelocity, lerp) { const body = _getRBDFromObject(object); if (!body) { console.warn("no rbd found"); return; } if (lerp < 1) { const rbdLinearVelocity = body.linvel(); currentLinearVelocity.set(rbdLinearVelocity.x, rbdLinearVelocity.y, rbdLinearVelocity.z); newLinearVelocity.copy(targetVelocity); currentLinearVelocity.lerp(newPos, lerp); body.setLinvel(currentLinearVelocity, true); } else { body.setLinvel(targetVelocity, true); } touchRBDProperty(object, "linVel" /* LINEAR_VELOCITY */); } export function _setPhysicsRBDAngularVelocity(object, targetVelocity, lerp) { const body = _getRBDFromObject(object); if (!body) { console.warn("no rbd found"); return; } if (lerp < 1) { const rbdAngularVelocity = body.angvel(); currentAngularVelocity.set(rbdAngularVelocity.x, rbdAngularVelocity.y, rbdAngularVelocity.z); newAngularVelocity.copy(targetVelocity); currentAngularVelocity.lerp(newPos, lerp); body.setAngvel(currentAngularVelocity, true); } else { body.setAngvel(targetVelocity, true); } touchRBDProperty(object, "angVel" /* ANGULAR_VELOCITY */); } function PhysicsRBDTypeToRigidBodyType(type) { var _a; const RigidBodyType2 = (_a = CorePhysicsLoaded()) == null ? void 0 : _a.RigidBodyType; if (!RigidBodyType2) { return; } switch (type) { case PhysicsRBDType.FIXED: { return RigidBodyType2.Fixed; } case PhysicsRBDType.DYNAMIC: { return RigidBodyType2.Dynamic; } case PhysicsRBDType.KINEMATIC_POS: { return RigidBodyType2.KinematicPositionBased; } case PhysicsRBDType.KINEMATIC_VEL: { return RigidBodyType2.KinematicVelocityBased; } } TypeAssert.unreachable(type); } function PhysicsRBDCollider(PhysicsLib2, colliderType, object) { switch (colliderType) { case PhysicsRBDColliderType.CAPSULE: { return createPhysicsCapsule(PhysicsLib2, object); } case PhysicsRBDColliderType.CUBOID: { return createPhysicsCuboid(PhysicsLib2, object); } case PhysicsRBDColliderType.CONE: { return createPhysicsCone(PhysicsLib2, object); } case PhysicsRBDColliderType.CONVEX_HULL: { return createPhysicsConvexHull(PhysicsLib2, object); } case PhysicsRBDColliderType.TRIMESH: { return createPhysicsTriMesh(PhysicsLib2, object); } case PhysicsRBDColliderType.CYLINDER: { return createPhysicsCylinder(PhysicsLib2, object); } case PhysicsRBDColliderType.SPHERE: { return createPhysicsSphere(PhysicsLib2, object); } case PhysicsRBDColliderType.HEIGHT_FIELD: { return createPhysicsHeightField(PhysicsLib2, object); } } TypeAssert.unreachable(colliderType); }