@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
137 lines (136 loc) • 4.59 kB
JavaScript
;
import { CorePhysics, CorePhysicsLoaded } from "./CorePhysics";
import { Vector3 } from "three";
import { _physicsCreateRBD, physicsUpdateRBD } from "./PhysicsRBD";
import { physicsCreateJoints } from "./PhysicsJoint";
import { PhysicsIdAttribute } from "./PhysicsAttribute";
import { clearPhysicsPlayers, createOrFindPhysicsPlayer } from "./player/PhysicsPlayer";
import { coreObjectClassFactory } from "../geometry/CoreObjectFactory";
export const PHYSICS_GRAVITY_DEFAULT = new Vector3(0, -9.81, 0);
const physicsworldByGraphNodeId = /* @__PURE__ */ new Map();
const objectsByRBD = /* @__PURE__ */ new WeakMap();
const rigidBodyById = /* @__PURE__ */ new Map();
export async function createOrFindPhysicsWorld(node, worldObject, gravity) {
const nodeId = node.graphNodeId();
const PhysicsLib2 = await CorePhysics();
let world = physicsworldByGraphNodeId.get(nodeId);
if (!world) {
world = new PhysicsLib2.World(gravity);
physicsworldByGraphNodeId.set(nodeId, world);
}
return { world, PhysicsLib: PhysicsLib2 };
}
export function physicsWorldNodeIdFromObject(worldObject) {
const nodeId = coreObjectClassFactory(worldObject).attribValue(worldObject, PhysicsIdAttribute.WORLD);
return nodeId;
}
export function physicsWorldFromObject(worldObject) {
const nodeId = coreObjectClassFactory(worldObject).attribValue(worldObject, PhysicsIdAttribute.WORLD);
if (nodeId == null) {
return;
}
return physicsworldByGraphNodeId.get(nodeId);
}
export function physicsWorldFromNodeId(nodeId) {
return physicsworldByGraphNodeId.get(nodeId);
}
export function initCorePhysicsWorld(PhysicsLib2, worldObject, scene) {
const world = physicsWorldFromObject(worldObject);
if (!world) {
console.warn("no physicsWorld found with this object", worldObject);
return;
}
_clearWorld(world);
const children = [...worldObject.children];
const newRBDIds = /* @__PURE__ */ new Set();
for (const child of children) {
_physicsCreateRBD({ PhysicsLib: PhysicsLib2, world, rigidBodyById, objectsByRBD, object: child, newRBDIds });
}
physicsCreateJoints(PhysicsLib2, world, worldObject);
for (const child of children) {
createOrFindPhysicsPlayer({ scene, object: child, PhysicsLib: PhysicsLib2, world, worldObject });
}
}
export function object3DFromRBD(rbd) {
return objectsByRBD.get(rbd);
}
export function physicsCreateRBDFromWorldObject(worldObject, object) {
const world = physicsWorldFromObject(worldObject);
if (!world) {
console.warn("no physicsWorld found with this object", worldObject);
return;
}
return physicsCreateRBDFromWorld(world, object);
}
export function physicsCreateRBDFromWorld(world, object) {
const PhysicsLib2 = CorePhysicsLoaded();
if (!PhysicsLib2) {
return;
}
const newRBDIds = /* @__PURE__ */ new Set();
_physicsCreateRBD({ PhysicsLib: PhysicsLib2, world, rigidBodyById, objectsByRBD, object, newRBDIds });
return newRBDIds;
}
export function getRBDFromId(rbdId) {
return rigidBodyById.get(rbdId);
}
function _clearWorld(world) {
const bodies = [];
const colliders = [];
const joints = [];
const multiBodyJoints = [];
world.bodies.forEach((body) => {
bodies.push(body);
});
world.colliders.forEach((collider) => {
colliders.push(collider);
});
world.impulseJoints.forEach((joint) => {
joints.push(joint);
});
world.multibodyJoints.forEach((multiBodyJoint) => {
multiBodyJoints.push(multiBodyJoint);
});
for (const body of bodies) {
world.removeRigidBody(body);
}
for (const collider of colliders) {
world.removeCollider(collider, false);
}
for (const joint of joints) {
world.removeImpulseJoint(joint, false);
}
for (const joint of multiBodyJoints) {
world.removeMultibodyJoint(joint, false);
}
clearPhysicsPlayers();
}
export function stepWorld(worldObject) {
const world = physicsWorldFromObject(worldObject);
if (!world) {
return;
}
world.step();
world.bodies.forEach((body) => {
const object = objectsByRBD.get(body);
if (object) {
physicsUpdateRBD(object, body);
}
});
}
const currentGravity = new Vector3();
const newGravity = new Vector3();
export function setWorldGravity(worldObject, gravity, lerp) {
const world = physicsWorldFromObject(worldObject);
if (!world) {
return;
}
if (lerp < 1) {
currentGravity.set(world.gravity.x, world.gravity.y, world.gravity.z);
newGravity.copy(gravity);
currentGravity.lerp(newGravity, lerp);
}
world.gravity.x = gravity.x;
world.gravity.y = gravity.y;
world.gravity.z = gravity.z;
}