UNPKG

@polygonjs/polygonjs

Version:

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

334 lines (333 loc) 11.4 kB
"use strict"; import { Vector4, Vector3, Vector2, BoxGeometry, Mesh, MeshBasicMaterial } from "three"; import { CorePhysicsLoaded } from "./CorePhysics"; import { getRBDFromId, physicsCreateRBDFromWorld, physicsWorldNodeIdFromObject } from "./PhysicsWorld"; import { TypeAssert } from "./../../engine/poly/Assert"; import { getObjectVector2, setObjectVector2, getObjectVector3, setObjectVector3, getObjectVector4, setObjectVector4, getObjectString, setObjectString } from "../geometry/AttributeUtils"; import { CorePhysicsAttribute } from "./PhysicsAttribute"; import { _getPhysicsWorldFromRBD, _getRBDFromObject, _physicsRBDDelete } from "./PhysicsRBD"; import { removeFromParent } from "../../engine/poly/PolyOnObjectsAddRemoveHooksController"; import { PhysicsRBDType } from "./PhysicsAttribute"; import { PhysicsRBDColliderType } from "./PhysicsAttribute"; import { setFirstValue } from "../SetUtils"; export var PhysicsJointType = /* @__PURE__ */ ((PhysicsJointType2) => { PhysicsJointType2["FIXED"] = "fixed"; PhysicsJointType2["SPHERICAL"] = "spherical"; PhysicsJointType2["REVOLUT"] = "revolute"; PhysicsJointType2["PRISMATIC"] = "prismatic"; return PhysicsJointType2; })(PhysicsJointType || {}); export const PHYSICS_JOINT_TYPES = [ "fixed" /* FIXED */, "spherical" /* SPHERICAL */, "revolute" /* REVOLUT */, "prismatic" /* PRISMATIC */ ]; const ALLOWED_JOIN_TYPES = ["fixed" /* FIXED */, "spherical" /* SPHERICAL */]; export const PHYSICS_JOINT_TYPE_MENU_ENTRIES = ALLOWED_JOIN_TYPES.map((name, value) => ({ name, value })); export var PhysicsJointAttribute = /* @__PURE__ */ ((PhysicsJointAttribute2) => { PhysicsJointAttribute2["JOIN_TYPE"] = "jointType"; PhysicsJointAttribute2["RBD_ID1"] = "rbdId1"; PhysicsJointAttribute2["RBD_ID2"] = "rbdId2"; PhysicsJointAttribute2["ANCHOR1"] = "anchor1"; PhysicsJointAttribute2["ANCHOR2"] = "anchor2"; PhysicsJointAttribute2["LIMIT"] = "limit"; PhysicsJointAttribute2["AXIS"] = "axis"; PhysicsJointAttribute2["FRAME1"] = "frame1"; PhysicsJointAttribute2["FRAME2"] = "frame2"; return PhysicsJointAttribute2; })(PhysicsJointAttribute || {}); export class CorePhysicsJoinAttribute { // common static setJoinType(object, value) { setObjectString(object, "jointType" /* JOIN_TYPE */, value); } static getJoinType(object) { return getObjectString(object, "jointType" /* JOIN_TYPE */); } static setRBDId1(object, value) { setObjectString(object, "rbdId1" /* RBD_ID1 */, value); } static getRBDId1(object) { return getObjectString(object, "rbdId1" /* RBD_ID1 */); } static setRBDId2(object, value) { setObjectString(object, "rbdId2" /* RBD_ID2 */, value); } static getRBDId2(object) { return getObjectString(object, "rbdId2" /* RBD_ID2 */); } static setAnchor1(object, value) { setObjectVector3(object, "anchor1" /* ANCHOR1 */, value); } static getAnchor1(object, value) { return getObjectVector3(object, "anchor1" /* ANCHOR1 */, value); } static setAnchor2(object, value) { setObjectVector3(object, "anchor2" /* ANCHOR2 */, value); } static getAnchor2(object, value) { return getObjectVector3(object, "anchor2" /* ANCHOR2 */, value); } static setLimit(object, value) { setObjectVector2(object, "limit" /* LIMIT */, value); } static getLimit(object, value) { return getObjectVector2(object, "limit" /* LIMIT */, value); } static setAxis(object, value) { setObjectVector3(object, "axis" /* AXIS */, value); } static getAxis(object, value) { return getObjectVector3(object, "axis" /* AXIS */, value); } static setFrame1(object, value) { setObjectVector4(object, "frame1" /* FRAME1 */, value); } static getFrame1(object, value) { return getObjectVector4(object, "frame1" /* FRAME1 */, value); } static setFrame2(object, value) { setObjectVector4(object, "frame2" /* FRAME2 */, value); } static getFrame2(object, value) { return getObjectVector4(object, "frame2" /* FRAME2 */, value); } } const jointDataListByWorldObject = /* @__PURE__ */ new Map(); export function setJointDataListForWorldObject(scene, worldObject) { const nodeId = physicsWorldNodeIdFromObject(worldObject); if (nodeId == null) { return; } const array = []; jointDataListByWorldObject.set(nodeId, array); const childrenToRemove = []; worldObject.traverse((child) => { const jointData = createJointDataFromJoinObject(child); if (jointData) { childrenToRemove.push(child); array.push(jointData); } }); for (const child of childrenToRemove) { removeFromParent(scene, child); } } function createJointDataFromJoinObject(object) { const jointType = CorePhysicsJoinAttribute.getJoinType(object); if (!jointType) { return; } const rbdId1 = CorePhysicsJoinAttribute.getRBDId1(object); const rbdId2 = CorePhysicsJoinAttribute.getRBDId2(object); if (rbdId1 == null || rbdId2 == null) { return; } const anchor12 = new Vector3(); const anchor22 = new Vector3(); CorePhysicsJoinAttribute.getAnchor1(object, anchor12); CorePhysicsJoinAttribute.getAnchor2(object, anchor22); const jointData = { jointType, rbdId1, rbdId2, anchor1: anchor12, anchor2: anchor22, data: {} }; switch (jointType) { case "fixed" /* FIXED */: { const frame1 = new Vector4(); const frame2 = new Vector4(); CorePhysicsJoinAttribute.getFrame1(object, frame1); CorePhysicsJoinAttribute.getFrame1(object, frame1); jointData.data.fixed = { frame1, frame2 }; return jointData; } case "prismatic" /* PRISMATIC */: { const axis = new Vector3(); const limit = new Vector2(); CorePhysicsJoinAttribute.getAxis(object, axis); CorePhysicsJoinAttribute.getLimit(object, limit); jointData.data.prismatic = { axis, limit }; return jointData; } case "revolute" /* REVOLUT */: { const axis = new Vector3(); const limit = new Vector2(); CorePhysicsJoinAttribute.getAxis(object, axis); CorePhysicsJoinAttribute.getLimit(object, limit); jointData.data.revolut = { axis, limit }; return jointData; } case "spherical" /* SPHERICAL */: { return jointData; } } TypeAssert.unreachable(jointType); } const wakeUp = true; export function physicsCreateJoints(PhysicsLib2, world, worldObject) { const nodeId = physicsWorldNodeIdFromObject(worldObject); if (nodeId == null) { return; } const jointDataList = jointDataListByWorldObject.get(nodeId); if (!jointDataList) { return; } for (const jointData of jointDataList) { physicsCreateJointFromJointData(PhysicsLib2, world, jointData); } } export function physicsCreateJointFromJointData(PhysicsLib2, world, jointData) { const { rbdId1, rbdId2 } = jointData; const rbd1 = getRBDFromId(rbdId1); const rbd2 = getRBDFromId(rbdId2); if (!(rbd1 && rbd2)) { return; } const joint = _createJoint(world, PhysicsLib2, jointData, rbd1, rbd2); return joint; } function _createJoint(world, PhysicsLib2, jointData, rbd1, rbd2) { const { jointType, anchor1: anchor12, anchor2: anchor22 } = jointData; switch (jointType) { case "fixed" /* FIXED */: { const fixedData = jointData.data.fixed; if (!fixedData) { return; } const { frame1, frame2 } = fixedData; const params = PhysicsLib2.JointData.fixed(anchor12, frame1, anchor22, frame2); const joint = world.createImpulseJoint(params, rbd1, rbd2, wakeUp); return joint; } case "prismatic" /* PRISMATIC */: { const prismaticfixedData = jointData.data.prismatic; if (!prismaticfixedData) { return; } const { axis, limit } = prismaticfixedData; const params = PhysicsLib2.JointData.prismatic(anchor12, anchor22, axis); params.limitsEnabled = true; params.limits = [limit.x, limit.y]; const joint = world.createImpulseJoint(params, rbd1, rbd2, wakeUp); joint.setLimits(limit.x, limit.y); return joint; } case "revolute" /* REVOLUT */: { const revolutfixedData = jointData.data.revolut; if (!revolutfixedData) { return; } const { axis, limit } = revolutfixedData; const params = PhysicsLib2.JointData.revolute(anchor12, anchor22, axis); params.limitsEnabled = true; params.limits = [limit.x, limit.y]; const joint = world.createImpulseJoint(params, rbd1, rbd2, wakeUp); joint.setLimits(limit.x, limit.y); return joint; } case "spherical" /* SPHERICAL */: { const params = PhysicsLib2.JointData.spherical(anchor12, anchor22); const joint = world.createImpulseJoint(params, rbd1, rbd2, wakeUp); return joint; } } TypeAssert.unreachable(jointType); } const anchor1 = new Vector3(0, 0, 0); const anchor2 = new Vector3(0, 0, 0); const _createRBDForKinematicConstraint = (options) => { const { world, rbdId, anchor } = options; const size = 0.01; const geometry = new BoxGeometry(size, size, size); const object = new Mesh(geometry, new MeshBasicMaterial()); object.castShadow = false; object.receiveShadow = false; object.visible = false; object.position.copy(anchor); object.updateMatrix(); object.matrixAutoUpdate = false; object.worldToLocal(anchor1.copy(anchor)); const RBD_ID = `kinematicConstraint-${rbdId}-${performance.now()}`; CorePhysicsAttribute.setDensity(object, 0); CorePhysicsAttribute.setRBDType(object, PhysicsRBDType.KINEMATIC_POS); CorePhysicsAttribute.setColliderType(object, PhysicsRBDColliderType.SPHERE); CorePhysicsAttribute.setRBDId(object, RBD_ID); CorePhysicsAttribute.setRadius(object, size / 2); const newRBDIds = physicsCreateRBDFromWorld(world, object); return { newRBDIds, object, anchor1 }; }; export function _createPhysicsRBDKinematicConstraint(rbdObject, anchor) { const PhysicsLib2 = CorePhysicsLoaded(); if (!PhysicsLib2) { return; } const rbdId1 = CorePhysicsAttribute.getRBDId(rbdObject); if (rbdId1 == null) { return; } const rbd1 = _getRBDFromObject(rbdObject); if (!rbd1) { return; } const world = _getPhysicsWorldFromRBD(rbdObject); if (!world) { return; } const result = _createRBDForKinematicConstraint({ world, rbdId: rbdId1, anchor }); const rbdId2 = result.newRBDIds ? setFirstValue(result.newRBDIds) : void 0; if (!rbdId2) { return; } const jointData = { jointType: "spherical" /* SPHERICAL */, anchor1: result.anchor1, anchor2, rbdId1, rbdId2, data: {} }; physicsCreateJointFromJointData(PhysicsLib2, world, jointData); return rbdId2; } export function _deletePhysicsRBDKinematicConstraint(scene, object) { _physicsRBDDelete(scene, object); } export function _physicsRBDDeleteConstraints(rbdObject) { const handle = CorePhysicsAttribute.getRBDHandle(rbdObject); if (handle == null) { return; } const body = _getRBDFromObject(rbdObject); if (!body) { return; } const world = _getPhysicsWorldFromRBD(rbdObject); if (!world) { return; } const wakeUp2 = true; const handles = []; world.impulseJoints.forEachJointHandleAttachedToRigidBody(handle, (jointHandle) => { handles.push(jointHandle); }); for (const jointHandle of handles) { const joint = world.getImpulseJoint(jointHandle); if (joint) { world.removeImpulseJoint(joint, wakeUp2); } } }