@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
334 lines (333 loc) • 11.4 kB
JavaScript
"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);
}
}
}