babylon-box3d 0.5.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -1
- package/dist/box3dPlugin.js +1 -1
- package/lib/esm/box3d.d.ts +39 -1
- package/lib/esm/box3d.js +2 -2
- package/lib/esm/box3d.wasm +0 -0
- package/lib/esm-threads/box3d.d.ts +39 -1
- package/lib/esm-threads/box3d.js +2 -2
- package/lib/esm-threads/box3d.wasm +0 -0
- package/lib/node/box3d.d.ts +39 -1
- package/lib/node/box3d.mjs +2 -2
- package/lib/node/box3d.wasm +0 -0
- package/lib/node-threads/box3d.d.ts +39 -1
- package/lib/node-threads/box3d.mjs +2 -2
- package/lib/node-threads/box3d.wasm +0 -0
- package/lib/umd/box3d.umd.js +2 -2
- package/lib/umd/box3d.umd.wasm +0 -0
- package/package.json +1 -1
- package/umd/babylon.box3d.js +2 -2
- package/umd/babylon.box3d.js.map +1 -1
- package/umd/babylon.box3d.min.js +2 -2
- package/umd/babylon.box3d.min.js.map +1 -1
- package/wasm/box3d_shim.c +588 -10
package/umd/babylon.box3d.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["babylon-global:@babylonjs/core/Maths/math.vector.js", "babylon-global:@babylonjs/core/Physics/v2/IPhysicsEnginePlugin.js", "babylon-global:@babylonjs/core/Physics/physicsRaycastResult.js", "babylon-global:@babylonjs/core/Misc/logger.js", "babylon-global:@babylonjs/core/Culling/boundingBox.js", "babylon-global:@babylonjs/core/Meshes/mesh.js", "babylon-global:@babylonjs/core/Meshes/instancedMesh.js", "babylon-global:@babylonjs/core/Buffers/buffer.js", "babylon-global:@babylonjs/core/Misc/observable.js", "box3d-global:babylon-box3d/wasm", "box3d-threads-stub:babylon-box3d/wasm/threads", "../src/index.ts", "../src/box3dPlugin.ts", "../src/loadBox3D.ts"],
|
|
4
|
-
"sourcesContent": ["if (typeof BABYLON === \"undefined\") { throw new Error(\"babylon.box3d.js needs babylon.js loaded first\"); } module.exports = BABYLON;", "if (typeof BABYLON === \"undefined\") { throw new Error(\"babylon.box3d.js needs babylon.js loaded first\"); } module.exports = BABYLON;", "if (typeof BABYLON === \"undefined\") { throw new Error(\"babylon.box3d.js needs babylon.js loaded first\"); } module.exports = BABYLON;", "if (typeof BABYLON === \"undefined\") { throw new Error(\"babylon.box3d.js needs babylon.js loaded first\"); } module.exports = BABYLON;", "if (typeof BABYLON === \"undefined\") { throw new Error(\"babylon.box3d.js needs babylon.js loaded first\"); } module.exports = BABYLON;", "if (typeof BABYLON === \"undefined\") { throw new Error(\"babylon.box3d.js needs babylon.js loaded first\"); } module.exports = BABYLON;", "if (typeof BABYLON === \"undefined\") { throw new Error(\"babylon.box3d.js needs babylon.js loaded first\"); } module.exports = BABYLON;", "if (typeof BABYLON === \"undefined\") { throw new Error(\"babylon.box3d.js needs babylon.js loaded first\"); } module.exports = BABYLON;", "if (typeof BABYLON === \"undefined\") { throw new Error(\"babylon.box3d.js needs babylon.js loaded first\"); } module.exports = BABYLON;", "if (typeof Box3D === \"undefined\") { throw new Error(\"babylon.box3d.js needs lib/umd/box3d.umd.js loaded first\"); } export default Box3D;", "export default function () { throw new Error(\"babylon.box3d.js is the script tag build and has no threaded module. Install the package and import it, or use LoadBox3D({ threads: \\\"auto\\\" }).\"); }", "// babylon-box3d: Box3D physics for Babylon.js.\n//\n// import { Box3D, Box3DPlugin } from \"babylon-box3d\";\n// const box3d = await Box3D();\n// scene.enablePhysics(new Vector3(0, -9.81, 0), new Box3DPlugin(true, box3d));\n\n// the .js extension keeps the emitted dist/index.js importable by plain node ESM, not just by bundlers\nexport { BOX3D_HEIGHT_FIELD_HOLE, Box3DPlugin, Box3DWheelJoint, type IBox3DPluginOptions, type IBox3DWheelJointOptions } from \"./box3dPlugin.js\";\nexport { default as Box3D } from \"babylon-box3d/wasm\";\nexport type { Box3DModule, Box3DModuleOptions, Box3DExports, Box3DHeap } from \"babylon-box3d/wasm\";\nexport { CanUseBox3DThreads, LoadBox3D, type ILoadBox3DOptions } from \"./loadBox3D.js\";\n", "import { Matrix, Quaternion, TmpVectors, Vector3 } from \"@babylonjs/core/Maths/math.vector.js\";\nimport {\n type IPhysicsEnginePluginV2,\n type PhysicsMassProperties,\n type PhysicsShapeParameters,\n type ConstrainedBodyPair,\n type IPhysicsCollisionEvent,\n type IBasePhysicsCollisionEvent,\n PhysicsShapeType,\n PhysicsConstraintType,\n PhysicsMotionType,\n PhysicsConstraintAxis,\n PhysicsConstraintAxisLimitMode,\n PhysicsConstraintMotorType,\n PhysicsEventType,\n PhysicsPrestepType,\n PhysicsActivationControl,\n} from \"@babylonjs/core/Physics/v2/IPhysicsEnginePlugin.js\";\nimport { PhysicsRaycastResult } from \"@babylonjs/core/Physics/physicsRaycastResult.js\";\nimport { type IRaycastQuery } from \"@babylonjs/core/Physics/physicsRaycastResult.js\";\nimport { Logger } from \"@babylonjs/core/Misc/logger.js\";\nimport { type PhysicsBody } from \"@babylonjs/core/Physics/v2/physicsBody.js\";\nimport { type PhysicsConstraint, type Physics6DoFConstraint, type Physics6DoFLimit } from \"@babylonjs/core/Physics/v2/physicsConstraint.js\";\nimport { type PhysicsMaterial } from \"@babylonjs/core/Physics/v2/physicsMaterial.js\";\nimport { type PhysicsShape } from \"@babylonjs/core/Physics/v2/physicsShape.js\";\nimport { BoundingBox } from \"@babylonjs/core/Culling/boundingBox.js\";\nimport { type TransformNode } from \"@babylonjs/core/Meshes/transformNode.js\";\nimport { Mesh } from \"@babylonjs/core/Meshes/mesh.js\";\nimport { InstancedMesh } from \"@babylonjs/core/Meshes/instancedMesh.js\";\nimport { VertexBuffer } from \"@babylonjs/core/Buffers/buffer.js\";\nimport { Observable } from \"@babylonjs/core/Misc/observable.js\";\nimport { type Nullable, type FloatArray } from \"@babylonjs/core/types.js\";\n\n/** The cell material that cuts a hole in a height field: nothing collides with the cell and rays pass through it. */\nexport const BOX3D_HEIGHT_FIELD_HOLE = 255;\n\ndeclare module \"@babylonjs/core/Physics/v2/IPhysicsEnginePlugin.js\" {\n interface PhysicsShapeParameters {\n /**\n * Box3D height fields only: a material index for every cell, `(numHeightFieldSamplesX - 1) *\n * (numHeightFieldSamplesZ - 1)` of them, rows in the same order as `heightFieldData`. A cell of\n * `BOX3D_HEIGHT_FIELD_HOLE` (255) is a hole. The index is also what `userMaterialId` would carry in Box3D, so\n * keep it below 255 for solid ground.\n */\n heightFieldMaterials?: ArrayLike<number>;\n /**\n * `CONVEX_HULL` and `MESH` without a `mesh`: the points as x, y, z triplets in the body's space, for code that\n * builds shapes with no meshes to read them from, like a headless simulation.\n */\n positions?: ArrayLike<number>;\n /**\n * `MESH` with `positions`: three indices into the points per triangle, wound so the plain cross product of\n * (b - a) and (c - a) points out of the surface. That is Box3D's own winding, and it is used as given: no\n * flip for a left handed scene, which only applies to winding read from a Babylon mesh.\n */\n positionIndices?: ArrayLike<number>;\n }\n}\n\n/**\n * Per body plugin data. One instance per Box3D body (thin instances get one each).\n */\nclass Box3DBodyData {\n public constructor(\n /** slot handle inside the WASM shim */\n public slot: number\n ) {}\n public userMassProps: PhysicsMassProperties = {};\n /** Box3D angular motion locks currently set on the body, bits x, y, z */\n public angularLocks = 0;\n /** Havok's EventType bits: 1 collision started, 2 collision continued, 4 collision finished */\n public eventMask = 0;\n public motionType = PhysicsMotionType.STATIC;\n /** Babylon activation control; ALWAYS_INACTIVE parks the body as a static Box3D body, see setActivationControl */\n public activation = PhysicsActivationControl.SIMULATION_CONTROLLED;\n}\n\n/**\n * Per shape plugin data. A Babylon shape is a description that gets instantiated on each body it is set on.\n */\nclass Box3DShapeData {\n public constructor(\n public slot: number,\n public type: PhysicsShapeType\n ) {}\n public material: PhysicsMaterial = {};\n /** bodies currently instantiating this shape, refreshed when the description changes */\n public users = new Set<Box3DBodyData>();\n /** for containers: child shapes, so changes propagate to users */\n public children: Box3DShapeData[] = [];\n public parents = new Set<Box3DShapeData>();\n}\n\n/** Axis state kept on the JS side because box3d has no generic axis API. */\ninterface IAxisState {\n mode: PhysicsConstraintAxisLimitMode;\n min: number;\n max: number;\n motor: PhysicsConstraintMotorType;\n target: number;\n maxForce: number;\n friction: number;\n /** Physics6DoFLimit.stiffness: spring constant of a soft limit (N/m, or N*m/rad for angular axes) */\n stiffness: number;\n /** Physics6DoFLimit.damping */\n damping: number;\n}\n\n/**\n * How a SIX_DOF constraint is realised with Box3D's fixed joint types. Recomputed from the axis table whenever an axis\n * changes, and reused as is when a disabled constraint is enabled again.\n */\ninterface ISixDofPlan {\n jointType: Box3DJointType;\n /** Box3D frame x, y, z as indices into the constraint basis [axis, perpAxis, axis x perpAxis], null for identity frames */\n basis: Nullable<[number, number, number]>;\n /** the Babylon axis that follows the single degree of freedom of a revolute, prismatic or distance joint */\n primaryAxis: Nullable<PhysicsConstraintAxis>;\n /** spherical cone angle, negative when the swing is free */\n coneAngle: number;\n /** spherical twist limits (about axis), null when free */\n twist: Nullable<[number, number]>;\n /** revolute angle, prismatic translation or distance length limits, null when free */\n limit: Nullable<[number, number]>;\n /** distance joints: a real spring at rest length limit[0] instead of a rope between the limits */\n spring: boolean;\n /** stiffest soft limit, mapped to Box3D spring or constraint softness per body pair */\n stiffness: number;\n damping: number;\n angularStiffness: boolean;\n}\n\nclass Box3DConstraintData {\n public joints: number[] = [];\n public pairs: Array<{ parent: PhysicsBody; parentIndex: number; child: PhysicsBody; childIndex: number; parentData: Box3DBodyData; childData: Box3DBodyData }> = [];\n public type: PhysicsConstraintType = PhysicsConstraintType.LOCK;\n public jointType = 0;\n public enabled = true;\n public collisions = false;\n public frames = new Float32Array(14);\n public length = 0;\n public axes = new Map<PhysicsConstraintAxis, IAxisState>();\n /** SIX_DOF only */\n public plan: Nullable<ISixDofPlan> = null;\n}\n\n// shim joint types\nconst enum Box3DJointType {\n WELD = 0,\n SPHERICAL = 1,\n REVOLUTE = 2,\n PRISMATIC = 3,\n DISTANCE = 4,\n FILTER = 5,\n WHEEL = 6,\n PARALLEL = 7,\n}\n\n/**\n * Options for a Box3D wheel joint (Box3D specific, no Babylon equivalent).\n * The suspension travels along axisA (chassis space), the wheel spins about spinAxisB (wheel space)\n * and steers about the suspension axis.\n */\nexport interface IBox3DWheelJointOptions {\n /** anchor on the chassis, chassis local space */\n pivotA: Vector3;\n /** suspension axis in chassis local space (usually up) */\n axisA?: Vector3;\n /** axle direction in chassis local space, the wheel spins about it (default +z) */\n axleA?: Vector3;\n /** anchor on the wheel, wheel local space */\n pivotB?: Vector3;\n /** suspension spring stiffness in hertz */\n suspensionHertz?: number;\n /** suspension spring damping ratio */\n suspensionDampingRatio?: number;\n /** suspension travel limits along axisA */\n suspensionLimits?: [number, number];\n /** whether the wheel is driven */\n enableSpinMotor?: boolean;\n /** maximum drive torque */\n maxSpinTorque?: number;\n /** whether the wheel steers */\n enableSteering?: boolean;\n /** steering spring stiffness in hertz */\n steeringHertz?: number;\n /** steering spring damping ratio */\n steeringDampingRatio?: number;\n /** maximum steering torque */\n maxSteeringTorque?: number;\n /** steering angle limits in radians */\n steeringLimits?: [number, number];\n}\n\n/**\n * Handle to a Box3D wheel joint created with Box3DPlugin.createWheelJoint.\n */\nexport class Box3DWheelJoint {\n /**\n * @internal\n */\n public constructor(\n private _plugin: Box3DPlugin,\n /** @internal */\n public _slot: number\n ) {}\n\n /**\n * Sets the target angular speed of the spin motor.\n * @param speed radians per second\n */\n public setSpinSpeed(speed: number): void {\n this._plugin._wheelCall(\"_bx_WheelJoint_SetSpinMotorSpeed\", this._slot, speed);\n }\n\n /**\n * Sets the maximum torque the spin motor can apply.\n * @param torque newton meters\n */\n public setMaxSpinTorque(torque: number): void {\n this._plugin._wheelCall(\"_bx_WheelJoint_SetMaxSpinTorque\", this._slot, torque);\n }\n\n /**\n * Enables or disables the spin motor (disabled wheels roll freely).\n * @param enabled true to enable\n */\n public enableSpinMotor(enabled: boolean): void {\n this._plugin._wheelCall(\"_bx_WheelJoint_EnableSpinMotor\", this._slot, enabled ? 1 : 0);\n }\n\n /**\n * Sets the target steering angle.\n * @param radians steering angle\n */\n public setSteeringAngle(radians: number): void {\n this._plugin._wheelCall(\"_bx_WheelJoint_SetTargetSteeringAngle\", this._slot, radians);\n }\n\n /**\n * Tunes the suspension spring.\n * @param hertz stiffness\n * @param dampingRatio damping ratio\n */\n public setSuspension(hertz: number, dampingRatio: number): void {\n this._plugin._wheelCall(\"_bx_WheelJoint_SetSuspension\", this._slot, hertz, dampingRatio);\n }\n\n /**\n * Removes the joint.\n */\n public dispose(): void {\n this._plugin._destroyExtraJoint(this._slot);\n this._slot = 0;\n }\n}\n\n/**\n * Body event mask bits, the same values Havok's plugin uses so masks can be copied over from Havok code.\n * Box3D reports begin and end touch events together (they are one shape flag) and hit events separately.\n */\nconst enum Box3DEventBits {\n COLLISION_STARTED = 1,\n COLLISION_CONTINUED = 2,\n COLLISION_FINISHED = 4,\n ALL = 7,\n}\n\n/**\n * How much heavier a locked rotation axis is made than the heaviest free one. Babylon locks an axis with a zero inertia\n * component, Box3D needs an invertible tensor; 1e5 leaves a body a hundred thousand times harder to turn about that axis\n * while the tensor stays well conditioned in float32.\n */\nconst LockedInertiaRatio = 1e5;\n\n/**\n * Diagonalizes a symmetric inertia tensor [ixx, iyy, izz, ixy, ixz, iyz] into its principal moments and the rotation\n * that turns principal axes into body axes (Babylon's inertiaOrientation). Jacobi rotations, a few sweeps are plenty for\n * a 3x3, and the common diagonal case exits immediately.\n */\nfunction DiagonalizeInertia(tensor: ArrayLike<number>, moments: Vector3, orientation: Quaternion): void {\n const a = [\n [tensor[0], tensor[3], tensor[4]],\n [tensor[3], tensor[1], tensor[5]],\n [tensor[4], tensor[5], tensor[2]],\n ];\n orientation.set(0, 0, 0, 1);\n moments.set(tensor[0], tensor[1], tensor[2]);\n const q = [0, 0, 0, 1];\n for (let sweep = 0; sweep < 24; sweep++) {\n // rotation matrix of q, columns are the current principal axes\n const [x, y, z, w] = q;\n const r = [\n [1 - 2 * (y * y + z * z), 2 * (x * y - z * w), 2 * (x * z + y * w)],\n [2 * (x * y + z * w), 1 - 2 * (x * x + z * z), 2 * (y * z - x * w)],\n [2 * (x * z - y * w), 2 * (y * z + x * w), 1 - 2 * (x * x + y * y)],\n ];\n // d = transpose(r) * a * r\n const d = [0, 1, 2].map((i) => [0, 1, 2].map((j) => [0, 1, 2].reduce((sum, k) => sum + r[k][i] * [0, 1, 2].reduce((s2, l) => s2 + a[k][l] * r[l][j], 0), 0)));\n moments.set(d[0][0], d[1][1], d[2][2]);\n orientation.set(q[0], q[1], q[2], q[3]);\n const offDiagonal = [Math.abs(d[1][2]), Math.abs(d[0][2]), Math.abs(d[0][1])];\n const k = offDiagonal.indexOf(Math.max(...offDiagonal));\n const k1 = (k + 1) % 3;\n const k2 = (k + 2) % 3;\n const off = d[k1][k2];\n const scale = Math.abs(d[0][0]) + Math.abs(d[1][1]) + Math.abs(d[2][2]) + 1e-30;\n if (Math.abs(off) <= 1e-9 * scale) {\n return;\n }\n let theta = (d[k2][k2] - d[k1][k1]) / (2 * off);\n const sign = theta > 0 ? 1 : -1;\n theta *= sign;\n const t = sign / (theta + (theta < 1e6 ? Math.sqrt(theta * theta + 1) : theta));\n const c = 1 / Math.sqrt(t * t + 1);\n if (c === 1) {\n return;\n }\n const jacobi = [0, 0, 0, 0];\n // d is transpose(r) * a * r and the step right multiplies q, so d becomes transpose(jacobi) * d * jacobi: the\n // quaternion has to turn by -theta where the matrix form of the Jacobi rotation turns by +theta. With the other\n // sign every sweep puts the off diagonal term straight back and the loop never converges.\n jacobi[k] = -sign * Math.sqrt((1 - c) / 2);\n jacobi[3] = Math.sqrt(1 - jacobi[k] * jacobi[k]);\n // q = q * jacobi\n const [qx, qy, qz, qw] = q;\n const [jx, jy, jz, jw] = jacobi;\n q[0] = qw * jx + qx * jw + qy * jz - qz * jy;\n q[1] = qw * jy - qx * jz + qy * jw + qz * jx;\n q[2] = qw * jz + qx * jy - qy * jx + qz * jw;\n q[3] = qw * jw - qx * jx - qy * jy - qz * jz;\n const length = Math.hypot(q[0], q[1], q[2], q[3]) || 1;\n for (let i = 0; i < 4; i++) {\n q[i] /= length;\n }\n }\n}\n\n/** Builds the symmetric tensor [ixx, iyy, izz, ixy, ixz, iyz] of principal moments rotated into body space. */\nfunction ComposeInertia(moments: ArrayLike<number>, orientation: Quaternion): number[] {\n const { x, y, z, w } = orientation;\n const r = [\n [1 - 2 * (y * y + z * z), 2 * (x * y - z * w), 2 * (x * z + y * w)],\n [2 * (x * y + z * w), 1 - 2 * (x * x + z * z), 2 * (y * z - x * w)],\n [2 * (x * z - y * w), 2 * (y * z + x * w), 1 - 2 * (x * x + y * y)],\n ];\n const at = (i: number, j: number) => r[i][0] * moments[0] * r[j][0] + r[i][1] * moments[1] * r[j][1] + r[i][2] * moments[2] * r[j][2];\n return [at(0, 0), at(1, 1), at(2, 2), at(0, 1), at(0, 2), at(1, 2)];\n}\n\n/** Shape description properties that Box3D can change on live shapes, see bx_Body_SyncShapeDesc. */\nconst enum Box3DShapeSync {\n FILTER = 1,\n MATERIAL = 2,\n DENSITY = 4,\n}\n\nconst MOVE_STRIDE = 9;\nconst CONTACT_STRIDE = 12;\nconst SENSOR_STRIDE = 5;\nconst RAY_STRIDE = 11;\n\n/**\n * Collects mesh geometry in the physics body's local space (scaling baked in).\n */\nclass MeshGeometryAccumulator {\n private _vertices: number[] = [];\n private _indices: number[] = [];\n\n public constructor(\n private _collectIndices: boolean,\n private _flipWinding: boolean\n ) {}\n\n public addNodeMeshes(mesh: TransformNode, includeChildren: boolean): void {\n mesh.computeWorldMatrix(true);\n const rootScaled = TmpVectors.Matrix[0];\n Matrix.ScalingToRef(mesh.absoluteScaling.x, mesh.absoluteScaling.y, mesh.absoluteScaling.z, rootScaled);\n if (mesh instanceof Mesh) {\n this._addMesh(mesh, rootScaled);\n } else if (mesh instanceof InstancedMesh) {\n this._addMesh(mesh.sourceMesh, rootScaled);\n }\n if (includeChildren) {\n const worldToRoot = TmpVectors.Matrix[1];\n mesh.computeWorldMatrix().invertToRef(worldToRoot);\n const worldToRootScaled = TmpVectors.Matrix[2];\n worldToRoot.multiplyToRef(rootScaled, worldToRootScaled);\n const children = mesh.getChildMeshes(false).filter((m: any) => !m.physicsBody);\n for (const m of children) {\n const childToWorld = m.computeWorldMatrix();\n const childToRootScaled = TmpVectors.Matrix[3];\n childToWorld.multiplyToRef(worldToRootScaled, childToRootScaled);\n if (m instanceof Mesh) {\n this._addMesh(m, childToRootScaled);\n } else if (m instanceof InstancedMesh) {\n this._addMesh(m.sourceMesh, childToRootScaled);\n }\n }\n }\n }\n\n private _addMesh(mesh: Mesh, meshToRoot: Matrix): void {\n const vertexData = mesh.getVerticesData(VertexBuffer.PositionKind) || [];\n const numVerts = vertexData.length / 3;\n const indexOffset = this._vertices.length / 3;\n const p = TmpVectors.Vector3[0];\n for (let v = 0; v < numVerts; v++) {\n p.set(vertexData[v * 3 + 0], vertexData[v * 3 + 1], vertexData[v * 3 + 2]);\n Vector3.TransformCoordinatesToRef(p, meshToRoot, p);\n this._vertices.push(p.x, p.y, p.z);\n }\n if (this._collectIndices) {\n const meshIndices = mesh.getIndices();\n if (meshIndices) {\n for (let i = 0; i < meshIndices.length; i += 3) {\n if (this._flipWinding) {\n this._indices.push(meshIndices[i + 2] + indexOffset, meshIndices[i + 1] + indexOffset, meshIndices[i + 0] + indexOffset);\n } else {\n this._indices.push(meshIndices[i + 0] + indexOffset, meshIndices[i + 1] + indexOffset, meshIndices[i + 2] + indexOffset);\n }\n }\n }\n }\n }\n\n public get vertexCount(): number {\n return this._vertices.length / 3;\n }\n\n public get triangleCount(): number {\n return this._indices.length / 3;\n }\n\n public get vertices(): number[] {\n return this._vertices;\n }\n\n public get indices(): number[] {\n return this._indices;\n }\n}\n\n/**\n * Every native entry point the plugin calls. The constructor checks that the module has all of them, because the two ways this goes wrong\n * in practice - a box3d.js loader left behind by an older install, or a box3d.wasm served from a stale copy - otherwise turn into a physics\n * world where nothing ever happens. A test keeps the list in step with the code.\n */\nconst RequiredNativeExports = [\n \"_bx_Body_AllowFastRotation\", \"_bx_Body_ApplyAngularImpulse\", \"_bx_Body_ApplyForce\", \"_bx_Body_ApplyLinearImpulse\",\n \"_bx_Body_ApplyMassFromShapes\", \"_bx_Body_ApplyTorque\", \"_bx_Body_ComputeShapeMassData\", \"_bx_Body_EnableSleep\", \"_bx_Body_GetAABB\",\n \"_bx_Body_GetAngularDamping\", \"_bx_Body_GetAngularVelocity\", \"_bx_Body_GetGravityScale\", \"_bx_Body_GetLinearDamping\",\n \"_bx_Body_GetLinearVelocity\", \"_bx_Body_GetMassData\", \"_bx_Body_GetTransform\", \"_bx_Body_SetAngularDamping\", \"_bx_Body_SetAngularVelocity\",\n \"_bx_Body_SetAwake\", \"_bx_Body_SetEventFlags\", \"_bx_Body_SetGravityScale\", \"_bx_Body_SetLinearDamping\", \"_bx_Body_SetLinearVelocity\",\n \"_bx_Body_SetMassDataFull\", \"_bx_Body_SetMotionLocks\", \"_bx_Body_SetShape\", \"_bx_Body_SetTargetTransform\", \"_bx_Body_SetTransform\",\n \"_bx_Body_SetType\", \"_bx_Body_SyncShapeDesc\", \"_bx_ComputeAlignedFrameB\", \"_bx_ContactEventsPtr\", \"_bx_CreateBody\", \"_bx_CreateJoint\",\n \"_bx_CreateWorld\", \"_bx_DebugIndexCount\", \"_bx_DebugIndicesPtr\", \"_bx_DebugPositionsPtr\", \"_bx_DestroyBody\", \"_bx_DestroyJoint\",\n \"_bx_DestroyWorld\", \"_bx_GetMaxWorkers\", \"_bx_GetRejectedSlotCount\", \"_bx_Joint_EnableLimit\", \"_bx_Joint_EnableMotor\",\n \"_bx_Joint_EnableSpring\", \"_bx_Joint_IsValid\",\n \"_bx_Joint_SetCollideConnected\", \"_bx_Joint_SetConstraintTuning\", \"_bx_Joint_SetLimits\", \"_bx_Joint_SetMaxMotorForce\",\n \"_bx_Joint_SetMotorSpeed\", \"_bx_Joint_SetSphericalMotor\", \"_bx_Joint_SetSphericalTarget\", \"_bx_Joint_SetSpring\", \"_bx_Joint_SetTarget\",\n \"_bx_Joint_SetTwistLimits\", \"_bx_Joint_UpdateMotorFrame\", \"_bx_Joint_WakeBodies\", \"_bx_MoveEventsPtr\", \"_bx_RayHitsPtr\", \"_bx_Scratch\",\n \"_bx_SensorEventsPtr\", \"_bx_ShapeDesc_AddChild\", \"_bx_ShapeDesc_BuildDebugGeometry\", \"_bx_ShapeDesc_CreateBox\", \"_bx_ShapeDesc_CreateCapsule\",\n \"_bx_ShapeDesc_CreateContainer\", \"_bx_ShapeDesc_CreateCylinder\", \"_bx_ShapeDesc_CreateHeightField\", \"_bx_ShapeDesc_CreateHull\",\n \"_bx_ShapeDesc_CreateMesh\", \"_bx_ShapeDesc_CreateSphere\", \"_bx_ShapeDesc_Destroy\", \"_bx_ShapeDesc_GetAABB\", \"_bx_ShapeDesc_GetCategoryBits\",\n \"_bx_ShapeDesc_GetChildCount\", \"_bx_ShapeDesc_GetDensity\", \"_bx_ShapeDesc_GetFriction\", \"_bx_ShapeDesc_GetMaskBits\",\n \"_bx_ShapeDesc_GetRestitution\", \"_bx_ShapeDesc_RemoveChild\", \"_bx_ShapeDesc_SetDensity\", \"_bx_ShapeDesc_SetFilter\", \"_bx_ShapeDesc_SetGroup\",\n \"_bx_ShapeDesc_SetMaterial\", \"_bx_ShapeDesc_SetRollingResistance\", \"_bx_ShapeDesc_SetSensor\", \"_bx_World_CastRay\", \"_bx_World_EnableContinuous\",\n \"_bx_World_EnableSleeping\", \"_bx_World_Explode\", \"_bx_World_GetContactEvents\", \"_bx_World_GetMaximumLinearSpeed\", \"_bx_World_GetMoveEvents\",\n \"_bx_World_GetSensorEvents\", \"_bx_World_GetStats\", \"_bx_World_GetWorkerCount\", \"_bx_World_SetGravity\", \"_bx_World_SetMaximumLinearSpeed\",\n \"_bx_World_Step\"\n];\n\n/**\n * Options for the Box3D plugin, passed to the constructor after the module.\n */\nexport interface IBox3DPluginOptions {\n /**\n * Workers box3d may put on a world step, counting the thread the step is called on. 1 (the default) keeps\n * everything on the calling thread. Anything above 1 needs the threaded build of the module\n * (`LoadBox3D({ threads: true })` or `babylon-box3d/wasm/threads`), which in turn needs a cross origin isolated\n * page; on the single threaded module the request is clamped to 1 and a warning explains why.\n * \"auto\" asks for half of `navigator.hardwareConcurrency`, capped at what the build supports: box3d gains little\n * from the second thread of a core, and leaving room for rendering matters more than the last worker.\n * The world is created in the constructor and box3d builds its threads with it, so this cannot change later.\n */\n workerCount?: number | \"auto\";\n /**\n * Solver sub steps per world step. Box3D's default of 4 is what keeps tall stacks standing; 2 roughly halves\n * solver time and is worth trying for scenes that are mostly loose bodies, 8 buys stiffness in exchange for time.\n */\n subStepCount?: number;\n}\n\n/**\n * Box3D physics plugin for Babylon.js physics v2.\n * Box3D is Erin Catto's 3D rigid body engine (https://github.com/erincatto/box3d). This plugin drives the\n * WebAssembly build that ships in this package (a flat, handle based C shim over box3d).\n * Usage mirrors the Havok plugin:\n * ```ts\n * import { Box3D, Box3DPlugin } from \"babylon-box3d\";\n * const box3d = await Box3D();\n * scene.enablePhysics(new Vector3(0, -9.81, 0), new Box3DPlugin(true, box3d));\n * ```\n * On a cross origin isolated page the threaded module can spread a step over several workers:\n * ```ts\n * import { LoadBox3D, Box3DPlugin } from \"babylon-box3d\";\n * const box3d = await LoadBox3D({ threads: \"auto\" });\n * scene.enablePhysics(new Vector3(0, -9.81, 0), new Box3DPlugin(true, box3d, { workerCount: \"auto\" }));\n * ```\n */\nexport class Box3DPlugin implements IPhysicsEnginePluginV2 {\n /** Reference to the WASM module (the value resolved by the module factory). */\n public world: any;\n /** Name of the plugin */\n public name = \"Box3DPlugin\";\n /** Number of solver sub steps per world step. Box3D recommends 4. */\n public subStepCount = 4;\n /** Workers box3d puts on a world step, counting the calling thread. 1 unless the threaded module asked for more. */\n public readonly workerCount: number = 1;\n /** Wall clock time of the last world step in milliseconds (JavaScript side, includes the event sync). */\n public lastStepTimeMs = 0;\n\n private _b3: any;\n private _worldSlot = 0;\n private _fixedTimeStep = 1 / 60;\n private _timeStep = 1 / 60;\n private _maxAngularVelocity = 4 * Math.PI * 10;\n private _bodies: Array<{ body: PhysicsBody; index: number; data: Box3DBodyData } | undefined> = [];\n private _shapes: Array<Box3DShapeData | undefined> = [];\n private _bodyCollisionObservable = new Map<number, Observable<IPhysicsCollisionEvent>>();\n private _bodyCollisionEndedObservable = new Map<number, Observable<IBasePhysicsCollisionEvent>>();\n private _touchedInstanceMeshes = new Set<Mesh>();\n /** spherical joints whose velocity motor target has to be re-expressed in world space every step */\n private _motorJoints = new Set<number>();\n private _tmpVec3 = [new Vector3(), new Vector3(), new Vector3(), new Vector3()];\n private _tmpQuat = [new Quaternion(), new Quaternion(), new Quaternion()];\n private _warned = new Set<string>();\n /** the shim's rejected slot counter as of the last step, see executeStep */\n private _rejectedSlots = 0;\n\n /** Observable for collision started and continued events */\n public onCollisionObservable = new Observable<IPhysicsCollisionEvent>();\n /** Observable for collision ended events */\n public onCollisionEndedObservable = new Observable<IBasePhysicsCollisionEvent>();\n /** Observable for trigger entered and exited events */\n public onTriggerCollisionObservable = new Observable<IBasePhysicsCollisionEvent>();\n\n /**\n * Creates a Box3D plugin.\n * @param _useDeltaForWorldStep step the world with the frame delta (true) or a fixed time step (false)\n * @param box3dModule the resolved Box3D WASM module (await Box3DModule())\n * @param options worker count and sub steps, see IBox3DPluginOptions\n */\n public constructor(\n private _useDeltaForWorldStep = true,\n box3dModule: any,\n options?: IBox3DPluginOptions\n ) {\n if (!box3dModule) {\n throw new Error(\"Box3D module is required: pass the awaited result of the Box3D module factory.\");\n }\n const missing = RequiredNativeExports.filter((name) => typeof box3dModule[name] !== \"function\");\n if (missing.length > 0) {\n throw new Error(\n `Box3DPlugin: the Box3D module is missing ${missing.length} entry point${missing.length === 1 ? \"\" : \"s\"} this build needs` +\n ` (${missing.slice(0, 3).join(\", \")}${missing.length > 3 ? \", ...\" : \"\"}). box3d.js and box3d.wasm have to come from the` +\n \" same build of this package: check what locateFile points at and clear any copied or cached box3d.wasm.\"\n );\n }\n this._b3 = box3dModule;\n this.world = box3dModule;\n if (options?.subStepCount !== undefined) {\n this.subStepCount = Math.max(1, Math.round(options.subStepCount));\n }\n this._worldSlot = this._b3._bx_CreateWorld(0, -9.81, 0, this._resolveWorkerCount(options?.workerCount));\n if (!this._worldSlot) {\n throw new Error(\"Box3D: could not create a world (max worlds reached?)\");\n }\n // what box3d settled on, which is the request clamped to what this build of the module can run\n this.workerCount = Math.max(1, this._b3._bx_World_GetWorkerCount(this._worldSlot));\n }\n\n /**\n * Turns the requested worker count into one this module can honour. Only the threaded build reports more than one,\n * and asking a single threaded build for workers is quiet enough to look like it worked, so say so once.\n * @param requested the constructor option\n * @returns the count to create the world with\n */\n private _resolveWorkerCount(requested: number | \"auto\" | undefined): number {\n const supported = Math.max(1, this._b3._bx_GetMaxWorkers());\n if (requested === undefined) {\n return 1;\n }\n let wanted: number;\n if (requested === \"auto\") {\n const cores = (typeof navigator !== \"undefined\" && navigator.hardwareConcurrency) || 4;\n // half the reported cores: the other half is usually the second thread of each core, and box3d gains\n // little from those, while the renderer still needs somewhere to run\n wanted = Math.max(1, Math.floor(cores / 2));\n } else {\n wanted = Math.max(1, Math.round(requested));\n }\n if (wanted > 1 && supported === 1) {\n this._warnOnce(\n \"single-threaded-module\",\n `${wanted} workers were requested, but this Box3D module was built without threads, so the step stays on the calling ` +\n \"thread. Load the threaded build (LoadBox3D({ threads: true }), or babylon-box3d/wasm/threads) from a cross origin \" +\n \"isolated page: it needs SharedArrayBuffer, which browsers only allow with the COOP and COEP headers set.\"\n );\n }\n return Math.min(wanted, supported);\n }\n\n // ----------------------------------------------------------------------------------------\n // helpers\n // ----------------------------------------------------------------------------------------\n\n private _scratch(): Float32Array {\n return new Float32Array(this._b3.HEAPF32.buffer, this._b3._bx_Scratch(), 64);\n }\n\n private _warnOnce(key: string, message: string): void {\n if (!this._warned.has(key)) {\n this._warned.add(key);\n Logger.Warn(`Box3DPlugin: ${message}`);\n }\n }\n\n private _getPluginReference(body: PhysicsBody, instanceIndex?: number): Box3DBodyData {\n return body._pluginDataInstances?.length ? body._pluginDataInstances[instanceIndex ?? 0] : body._pluginData;\n }\n\n private _applyToBodyOrInstances(body: PhysicsBody, fn: (data: Box3DBodyData) => void, instanceIndex?: number): void {\n if (body._pluginDataInstances?.length > 0 && instanceIndex === undefined) {\n for (const data of body._pluginDataInstances) {\n fn(data);\n }\n } else {\n fn(this._getPluginReference(body, instanceIndex));\n }\n }\n\n private _motionTypeToNative(motionType: PhysicsMotionType): number {\n switch (motionType) {\n case PhysicsMotionType.STATIC:\n return 0;\n case PhysicsMotionType.ANIMATED:\n return 1;\n default:\n return 2;\n }\n }\n\n private _nodeTransformToRef(node: TransformNode, position: Vector3, orientation: Quaternion): void {\n if (node.parent) {\n node.computeWorldMatrix(true);\n position.copyFrom(node.absolutePosition);\n orientation.copyFrom(node.absoluteRotationQuaternion);\n return;\n }\n position.copyFrom(node.position);\n if (node.rotationQuaternion) {\n orientation.copyFrom(node.rotationQuaternion);\n } else {\n Quaternion.FromEulerAnglesToRef(node.rotation.x, node.rotation.y, node.rotation.z, orientation);\n }\n }\n\n // ----------------------------------------------------------------------------------------\n // world\n // ----------------------------------------------------------------------------------------\n\n public setGravity(gravity: Vector3): void {\n this._b3._bx_World_SetGravity(this._worldSlot, gravity.x, gravity.y, gravity.z);\n }\n\n public setTimeStep(timeStep: number): void {\n this._fixedTimeStep = timeStep;\n }\n\n public getTimeStep(): number {\n return this._fixedTimeStep;\n }\n\n public executeStep(delta: number, physicsBodies: Array<PhysicsBody>): void {\n for (const physicsBody of physicsBodies) {\n if (physicsBody.disablePreStep) {\n continue;\n }\n this.setPhysicsBodyTransformation(physicsBody, physicsBody.transformNode);\n }\n\n for (const joint of this._motorJoints) {\n // a joint whose bodies were destroyed is gone with them, drop it instead of holding the slot forever\n if (this._b3._bx_Joint_IsValid(joint)) {\n this._b3._bx_Joint_UpdateMotorFrame(joint);\n } else {\n this._motorJoints.delete(joint);\n }\n }\n\n const deltaTime = this._useDeltaForWorldStep ? delta : this._fixedTimeStep;\n this._timeStep = deltaTime;\n const start = performance.now();\n this._b3._bx_World_Step(this._worldSlot, deltaTime, this.subStepCount);\n\n // Only bodies that moved report an event, so sync those instead of iterating every body.\n const moveCount = this._b3._bx_World_GetMoveEvents(this._worldSlot);\n if (moveCount > 0) {\n const movePointer = this._b3._bx_MoveEventsPtr();\n let buffer = new Float32Array(this._b3.HEAPF32.buffer, movePointer, moveCount * MOVE_STRIDE);\n for (let i = 0; i < moveCount; i++) {\n if (buffer.buffer !== this._b3.HEAPF32.buffer) {\n // a world matrix observer grew the wasm memory; the records are still in place\n buffer = new Float32Array(this._b3.HEAPF32.buffer, movePointer, moveCount * MOVE_STRIDE);\n }\n const offset = i * MOVE_STRIDE;\n const ref = this._bodies[buffer[offset]];\n if (!ref || ref.body.disableSync) {\n continue;\n }\n this._syncBodyFromBuffer(ref.body, ref.index, buffer, offset + 1);\n }\n for (const mesh of this._touchedInstanceMeshes) {\n mesh.thinInstanceBufferUpdated(\"matrix\");\n }\n this._touchedInstanceMeshes.clear();\n }\n\n this._notifyCollisions();\n this._notifyTriggers();\n this.lastStepTimeMs = performance.now() - start;\n\n // Every native entry point returns quietly when it does not recognize a handle. That is what teardown needs and\n // it hides everything else, so say it once instead of simulating a world where half the calls do nothing.\n const rejected = this._b3._bx_GetRejectedSlotCount();\n if (rejected > this._rejectedSlots) {\n this._rejectedSlots = rejected;\n this._warnOnce(\n \"rejected-slots\",\n `the native module did not recognize ${rejected} of the handles it was given, and those calls did nothing. Something is using a ` +\n \"body, shape or joint after it was destroyed, or box3d.js and box3d.wasm are from different builds.\"\n );\n }\n }\n\n public getPluginVersion(): number {\n return 2;\n }\n\n public setVelocityLimits(maxLinearVelocity: number, maxAngularVelocity: number): void {\n this._b3._bx_World_SetMaximumLinearSpeed(this._worldSlot, maxLinearVelocity);\n this._maxAngularVelocity = maxAngularVelocity;\n }\n\n public getMaxLinearVelocity(): number {\n return this._b3._bx_World_GetMaximumLinearSpeed(this._worldSlot);\n }\n\n public getMaxAngularVelocity(): number {\n return this._maxAngularVelocity;\n }\n\n /**\n * Box3D counters and timings for the current world.\n * @returns body, shape, contact, joint and island counts plus the last step time in milliseconds\n */\n public getStats(): { bodies: number; shapes: number; contacts: number; joints: number; islands: number; stepMs: number; collideMs: number; solveMs: number } {\n this._b3._bx_World_GetStats(this._worldSlot);\n const s = this._scratch();\n return { bodies: s[0], shapes: s[1], contacts: s[2], joints: s[3], islands: s[4], stepMs: s[5], collideMs: s[6], solveMs: s[7] };\n }\n\n /**\n * Enables or disables island sleeping.\n * @param enabled true to let resting bodies sleep\n */\n public setSleepingEnabled(enabled: boolean): void {\n this._b3._bx_World_EnableSleeping(this._worldSlot, enabled ? 1 : 0);\n }\n\n /**\n * Enables or disables continuous collision against static geometry.\n * @param enabled true to enable continuous collision\n */\n public setContinuousEnabled(enabled: boolean): void {\n this._b3._bx_World_EnableContinuous(this._worldSlot, enabled ? 1 : 0);\n }\n\n // ----------------------------------------------------------------------------------------\n // bodies\n // ----------------------------------------------------------------------------------------\n\n private _createNativeBody(motionType: PhysicsMotionType, position: Vector3, orientation: Quaternion, startAsleep: boolean): Box3DBodyData {\n const slot = this._b3._bx_CreateBody(\n this._worldSlot,\n this._motionTypeToNative(motionType),\n position.x,\n position.y,\n position.z,\n orientation.x,\n orientation.y,\n orientation.z,\n orientation.w,\n startAsleep ? 0 : 1\n );\n const data = new Box3DBodyData(slot);\n data.motionType = motionType;\n return data;\n }\n\n public initBody(body: PhysicsBody, motionType: PhysicsMotionType, position: Vector3, orientation: Quaternion): void {\n const data = this._createNativeBody(motionType, position, orientation, body.startAsleep);\n body._pluginData = data;\n this._bodies[data.slot] = { body, index: 0, data };\n }\n\n public initBodyInstances(body: PhysicsBody, motionType: PhysicsMotionType, mesh: Mesh): void {\n const instancesCount = mesh._thinInstanceDataStorage?.instancesCount ?? 0;\n const matrixData = mesh._thinInstanceDataStorage?.matrixData;\n if (!matrixData) {\n return;\n }\n const shape = body.shape?._pluginData as Box3DShapeData | undefined;\n if (instancesCount > 8 && shape && this._bakesMeshCopies(shape)) {\n this._warnOnce(\n \"instanced-mesh-child\",\n \"a mesh inside a container has no local transform in Box3D, so every instance gets its own baked copy of the mesh data; \" +\n \"put the mesh on the body directly, or bake the offset into the mesh, to share it.\"\n );\n }\n this._createOrUpdateBodyInstances(body, motionType, matrixData, 0, instancesCount, false);\n }\n\n private _createOrUpdateBodyInstances(body: PhysicsBody, motionType: PhysicsMotionType, matrixData: Float32Array, startIndex: number, endIndex: number, update: boolean): void {\n const rotation = TmpVectors.Quaternion[0];\n const rotationMatrix = TmpVectors.Matrix[0];\n const position = TmpVectors.Vector3[0];\n for (let i = startIndex; i < endIndex; i++) {\n position.set(matrixData[i * 16 + 12], matrixData[i * 16 + 13], matrixData[i * 16 + 14]);\n Matrix.FromArrayToRef(matrixData, i * 16, rotationMatrix);\n rotationMatrix.decompose(undefined, rotation, undefined);\n if (update) {\n const data = body._pluginDataInstances[i];\n this._b3._bx_Body_SetTransform(data.slot, position.x, position.y, position.z, rotation.x, rotation.y, rotation.z, rotation.w);\n } else {\n const data = this._createNativeBody(motionType, position, rotation, body.startAsleep);\n const sibling = body._pluginDataInstances[0] as Box3DBodyData | undefined;\n if (sibling) {\n // a new instance behaves like the ones already there: same mass properties, events and activation\n data.userMassProps = sibling.userMassProps;\n data.eventMask = sibling.eventMask;\n this._applyEventFlags(data);\n if (sibling.activation !== PhysicsActivationControl.SIMULATION_CONTROLLED) {\n data.activation = sibling.activation;\n this._applyNativeMotionType(data);\n this._b3._bx_Body_EnableSleep(data.slot, sibling.activation === PhysicsActivationControl.ALWAYS_ACTIVE ? 0 : 1);\n }\n }\n body._pluginDataInstances.push(data);\n this._bodies[data.slot] = { body, index: i, data };\n }\n }\n }\n\n public updateBodyInstances(body: PhysicsBody, mesh: Mesh): void {\n const instancesCount = mesh._thinInstanceDataStorage?.instancesCount ?? 0;\n const matrixData = mesh._thinInstanceDataStorage?.matrixData;\n if (!matrixData) {\n return;\n }\n const pluginInstancesCount = body._pluginDataInstances.length;\n const motionType = this.getMotionType(body);\n if (instancesCount > pluginInstancesCount) {\n this._createOrUpdateBodyInstances(body, motionType, matrixData, pluginInstancesCount, instancesCount, false);\n const shape = body.shape;\n if (shape && shape._pluginData) {\n for (let i = pluginInstancesCount; i < instancesCount; i++) {\n this._setBodyShape(body._pluginDataInstances[i], shape._pluginData as Box3DShapeData);\n }\n }\n } else if (instancesCount < pluginInstancesCount) {\n const instancesToRemove = pluginInstancesCount - instancesCount;\n for (let i = 0; i < instancesToRemove; i++) {\n const data = body._pluginDataInstances.pop() as Box3DBodyData;\n this._destroyBodyData(data);\n }\n this._createOrUpdateBodyInstances(body, motionType, matrixData, 0, instancesCount, true);\n }\n }\n\n private _destroyBodyData(data: Box3DBodyData): void {\n if (!data) {\n return;\n }\n for (const shape of this._shapes) {\n shape?.users.delete(data);\n }\n this._bodyCollisionObservable.delete(data.slot);\n this._bodyCollisionEndedObservable.delete(data.slot);\n this._bodies[data.slot] = undefined;\n this._b3._bx_DestroyBody(data.slot);\n data.slot = 0;\n }\n\n public removeBody(body: PhysicsBody): void {\n // Box3D has no add/remove without destroying. The body is destroyed and re-created by initBody if needed.\n if (body._pluginDataInstances?.length) {\n for (const data of body._pluginDataInstances) {\n this._destroyBodyData(data);\n }\n }\n if (body._pluginData) {\n this._destroyBodyData(body._pluginData);\n }\n }\n\n public sync(body: PhysicsBody): void {\n this.syncTransform(body, body.transformNode);\n }\n\n private _syncBodyFromBuffer(body: PhysicsBody, index: number, buffer: Float32Array, offset: number): void {\n const node = body.transformNode;\n if (body._pluginDataInstances.length) {\n const m = node as Mesh;\n const matrixData = m._thinInstanceDataStorage?.matrixData;\n if (!matrixData) {\n return;\n }\n const scale = this._tmpVec3[0];\n const base = index * 16;\n scale.set(\n Math.hypot(matrixData[base], matrixData[base + 1], matrixData[base + 2]),\n Math.hypot(matrixData[base + 4], matrixData[base + 5], matrixData[base + 6]),\n Math.hypot(matrixData[base + 8], matrixData[base + 9], matrixData[base + 10])\n );\n const quat = this._tmpQuat[0];\n quat.set(buffer[offset + 3], buffer[offset + 4], buffer[offset + 5], buffer[offset + 6]);\n const position = this._tmpVec3[1];\n position.set(buffer[offset], buffer[offset + 1], buffer[offset + 2]);\n const matrix = TmpVectors.Matrix[0];\n Matrix.ComposeToRef(scale, quat, position, matrix);\n matrix.copyToArray(matrixData, base);\n this._touchedInstanceMeshes.add(m);\n return;\n }\n this._applyTransformToNode(node, buffer[offset], buffer[offset + 1], buffer[offset + 2], buffer[offset + 3], buffer[offset + 4], buffer[offset + 5], buffer[offset + 6]);\n }\n\n private _applyTransformToNode(node: TransformNode, px: number, py: number, pz: number, qx: number, qy: number, qz: number, qw: number): void {\n const quat = this._tmpQuat[0];\n quat.set(qx, qy, qz, qw);\n const parent = node.parent as TransformNode;\n if (parent && !parent.getWorldMatrix().isIdentity()) {\n parent.computeWorldMatrix(true);\n const savedScaling = this._tmpVec3[2];\n savedScaling.copyFrom(node.scaling);\n const finalTransform = TmpVectors.Matrix[0];\n const finalTranslation = this._tmpVec3[3];\n finalTranslation.set(px, py, pz);\n Matrix.ComposeToRef(node.absoluteScaling, quat, finalTranslation, finalTransform);\n const parentInverse = TmpVectors.Matrix[1];\n parent.getWorldMatrix().invertToRef(parentInverse);\n const localTransform = TmpVectors.Matrix[2];\n finalTransform.multiplyToRef(parentInverse, localTransform);\n localTransform.decomposeToTransformNode(node);\n node.rotationQuaternion?.normalize();\n node.scaling.copyFrom(savedScaling);\n } else {\n node.position.set(px, py, pz);\n if (node.rotationQuaternion) {\n node.rotationQuaternion.copyFrom(quat);\n } else {\n quat.toEulerAnglesToRef(node.rotation);\n }\n }\n }\n\n public syncTransform(body: PhysicsBody, transformNode: TransformNode): void {\n if (body._pluginDataInstances.length) {\n const m = transformNode as Mesh;\n const matrixData = m._thinInstanceDataStorage?.matrixData;\n if (!matrixData) {\n return;\n }\n for (let i = 0; i < body._pluginDataInstances.length; i++) {\n const data = body._pluginDataInstances[i] as Box3DBodyData;\n this._b3._bx_Body_GetTransform(data.slot);\n this._syncBodyFromBuffer(body, i, this._scratch(), 0);\n }\n m.thinInstanceBufferUpdated(\"matrix\");\n this._touchedInstanceMeshes.delete(m);\n return;\n }\n const data = body._pluginData as Box3DBodyData;\n if (!data || !data.slot) {\n return;\n }\n this._b3._bx_Body_GetTransform(data.slot);\n const s = this._scratch();\n this._applyTransformToNode(transformNode, s[0], s[1], s[2], s[3], s[4], s[5], s[6]);\n }\n\n /**\n * Pushes the transform node's pose into the physics body (called during the pre step).\n * @param body the physics body\n * @param node the transform node to read from\n */\n public setPhysicsBodyTransformation(body: PhysicsBody, node: TransformNode): void {\n const prestep = body.getPrestepType();\n if (prestep == PhysicsPrestepType.TELEPORT) {\n if (body._pluginDataInstances.length > 0) {\n const m = node as Mesh;\n const matrixData = m._thinInstanceDataStorage?.matrixData;\n if (!matrixData) {\n return;\n }\n this._createOrUpdateBodyInstances(body, body.getMotionType(), matrixData, 0, body._pluginDataInstances.length, true);\n return;\n }\n const data = body._pluginData as Box3DBodyData;\n const position = this._tmpVec3[0];\n const orientation = this._tmpQuat[0];\n this._nodeTransformToRef(node, position, orientation);\n this._b3._bx_Body_SetTransform(data.slot, position.x, position.y, position.z, orientation.x, orientation.y, orientation.z, orientation.w);\n } else if (prestep == PhysicsPrestepType.ACTION) {\n this.setTargetTransform(body, node.absolutePosition, node.absoluteRotationQuaternion);\n } else if (prestep == PhysicsPrestepType.DISABLED) {\n Logger.Warn(\"Prestep type is set to DISABLED. Unable to set physics body transformation.\");\n }\n }\n\n public setTargetTransform(body: PhysicsBody, position: Vector3, rotation: Quaternion, instanceIndex?: number): void {\n this._applyToBodyOrInstances(\n body,\n (data) => {\n this._b3._bx_Body_SetTargetTransform(data.slot, position.x, position.y, position.z, rotation.x, rotation.y, rotation.z, rotation.w, this._timeStep);\n },\n instanceIndex\n );\n }\n\n /** True when the shape puts a mesh inside a container, which Box3D can only do by baking a copy per body. */\n private _bakesMeshCopies(data: Box3DShapeData, visited = new Set<Box3DShapeData>()): boolean {\n if (visited.has(data)) {\n return false;\n }\n visited.add(data);\n return data.children.some((child) => child.type === PhysicsShapeType.MESH || this._bakesMeshCopies(child, visited));\n }\n\n private _setBodyShape(data: Box3DBodyData, shape: Nullable<Box3DShapeData>): void {\n for (const existing of this._shapes) {\n existing?.users.delete(data);\n }\n this._b3._bx_Body_SetShape(data.slot, shape ? shape.slot : 0);\n if (shape) {\n shape.users.add(data);\n }\n this._applyEventFlags(data);\n this._internalUpdateMassProperties(data);\n }\n\n public setShape(body: PhysicsBody, shape: Nullable<PhysicsShape>): void {\n const shapeData = shape && shape._pluginData ? (shape._pluginData as Box3DShapeData) : null;\n this._applyToBodyOrInstances(body, (data) => this._setBodyShape(data, shapeData));\n }\n\n public getShape(body: PhysicsBody): Nullable<PhysicsShape> {\n return body.shape ?? null;\n }\n\n public getShapeType(shape: PhysicsShape): PhysicsShapeType {\n return shape.type ?? (shape._pluginData as Box3DShapeData)?.type ?? PhysicsShapeType.CONTAINER;\n }\n\n /** Turns the body's event mask into Box3D's two shape flags, so a body only pays for the events it asked for. */\n private _applyEventFlags(data: Box3DBodyData): void {\n const touch = data.eventMask & (Box3DEventBits.COLLISION_STARTED | Box3DEventBits.COLLISION_FINISHED) ? 1 : 0;\n const hit = data.eventMask & Box3DEventBits.COLLISION_CONTINUED ? 1 : 0;\n this._b3._bx_Body_SetEventFlags(data.slot, touch, hit);\n }\n\n public setEventMask(body: PhysicsBody, eventMask: number, instanceIndex?: number): void {\n this._applyToBodyOrInstances(\n body,\n (data) => {\n data.eventMask = eventMask;\n this._applyEventFlags(data);\n },\n instanceIndex\n );\n }\n\n public getEventMask(body: PhysicsBody, instanceIndex?: number): number {\n return this._getPluginReference(body, instanceIndex).eventMask;\n }\n\n public setMotionType(body: PhysicsBody, motionType: PhysicsMotionType, instanceIndex?: number): void {\n this._applyToBodyOrInstances(\n body,\n (data) => {\n data.motionType = motionType;\n this._applyNativeMotionType(data);\n this._internalUpdateMassProperties(data);\n },\n instanceIndex\n );\n }\n\n /** The Box3D body type: the Babylon motion type, unless the body is parked by ALWAYS_INACTIVE. */\n private _applyNativeMotionType(data: Box3DBodyData): void {\n const native = data.activation === PhysicsActivationControl.ALWAYS_INACTIVE ? 0 : this._motionTypeToNative(data.motionType);\n this._b3._bx_Body_SetType(data.slot, native);\n }\n\n /**\n * Babylon's activation control, matched to Havok's behaviour with Box3D sleeping.\n * ALWAYS_ACTIVE turns sleeping off for the body, SIMULATION_CONTROLLED turns it back on. ALWAYS_INACTIVE parks the\n * body: in Havok such a body ignores impulses and velocity changes, is not woken by anything that touches it and\n * still blocks other bodies, which Box3D sleeping alone cannot do, so it becomes a static Box3D body until the\n * control changes. Coming back it is left asleep, like Havok, until something wakes it.\n * @param body the physics body\n * @param controlMode how the body may be activated and deactivated\n * @param instanceIndex optional thin instance index\n */\n public setActivationControl(body: PhysicsBody, controlMode: PhysicsActivationControl, instanceIndex?: number): void {\n this._applyToBodyOrInstances(\n body,\n (data) => {\n if (data.activation === controlMode) {\n return;\n }\n const wasInactive = data.activation === PhysicsActivationControl.ALWAYS_INACTIVE;\n data.activation = controlMode;\n if (controlMode === PhysicsActivationControl.ALWAYS_INACTIVE) {\n this._b3._bx_Body_SetLinearVelocity(data.slot, 0, 0, 0);\n this._b3._bx_Body_SetAngularVelocity(data.slot, 0, 0, 0);\n this._applyNativeMotionType(data);\n return;\n }\n this._applyNativeMotionType(data);\n this._internalUpdateMassProperties(data);\n this._b3._bx_Body_EnableSleep(data.slot, controlMode === PhysicsActivationControl.ALWAYS_ACTIVE ? 0 : 1);\n if (wasInactive && controlMode === PhysicsActivationControl.SIMULATION_CONTROLLED) {\n this._b3._bx_Body_SetAwake(data.slot, 0);\n }\n },\n instanceIndex\n );\n }\n\n public getMotionType(body: PhysicsBody, instanceIndex?: number): PhysicsMotionType {\n return this._getPluginReference(body, instanceIndex).motionType;\n }\n\n /**\n * Reads Box3D's mass data and converts it to Babylon's form: the inertia is the principal moments of the tensor\n * divided by the mass (Babylon's inertia is per unit mass) and the orientation rotates the principal axes into\n * body space.\n */\n private _readMassData(data: Box3DBodyData): PhysicsMassProperties {\n // Box3D keeps mass 0 on static and kinematic bodies; Havok reports what the shapes weigh whatever the type\n if (data.motionType === PhysicsMotionType.DYNAMIC && data.activation !== PhysicsActivationControl.ALWAYS_INACTIVE) {\n this._b3._bx_Body_GetMassData(data.slot);\n } else {\n this._b3._bx_Body_ComputeShapeMassData(data.slot);\n }\n const s = this._scratch();\n const mass = s[0];\n const principal = new Vector3();\n const orientation = new Quaternion();\n DiagonalizeInertia([s[4], s[5], s[6], s[7], s[8], s[9]], principal, orientation);\n if (mass > 0) {\n principal.scaleInPlace(1 / mass);\n }\n return {\n mass,\n centerOfMass: new Vector3(s[1], s[2], s[3]),\n inertia: principal,\n inertiaOrientation: orientation,\n };\n }\n\n /** The mass properties of the body: what the user asked for, filled in from the shapes where they said nothing. */\n private _resolveMassProperties(data: Box3DBodyData): Required<PhysicsMassProperties> {\n const computed = this._readMassData(data);\n const user = data.userMassProps ?? {};\n // no invented mass here: a body with no shapes really does weigh nothing, only the tensor written to Box3D\n // needs a positive mass (see _internalUpdateMassProperties)\n const mass = user.mass !== undefined && user.mass > 0 ? user.mass : computed.mass!;\n return {\n mass,\n centerOfMass: user.centerOfMass ?? computed.centerOfMass!,\n inertia: user.inertia ?? computed.inertia!,\n inertiaOrientation: user.inertiaOrientation ?? (user.inertia ? Quaternion.Identity() : computed.inertiaOrientation!),\n };\n }\n\n private _internalUpdateMassProperties(data: Box3DBodyData): void {\n if (data.motionType !== PhysicsMotionType.DYNAMIC || data.activation === PhysicsActivationControl.ALWAYS_INACTIVE) {\n // motion locks are world space velocity locks, they would fight a kinematic body's target transform\n this._applyMotionLocks(data, false, false, false);\n return;\n }\n this._b3._bx_Body_ApplyMassFromShapes(data.slot);\n const user = data.userMassProps;\n const hasUser = !!user && (user.mass !== undefined || !!user.centerOfMass || !!user.inertia || !!user.inertiaOrientation);\n if (!hasUser) {\n this._applyMotionLocks(data, false, false, false);\n return;\n }\n const props = this._resolveMassProperties(data);\n // a dynamic body with no mass at all would ignore gravity and every impulse\n const mass = props.mass > 0 ? props.mass : 1;\n const inertia = props.inertia;\n const orientation = props.inertiaOrientation;\n // Babylon's inertia is per unit mass and a zero component means infinite inertia about that principal axis.\n // Box3D needs an invertible tensor, so a locked axis gets a very large moment; where the free axes stay aligned\n // with the world, Box3D's motion locks are added on top and make it exact.\n const locked = [inertia.x <= 0, inertia.y <= 0, inertia.z <= 0];\n const largest = Math.max(inertia.x, inertia.y, inertia.z, 1e-4) * LockedInertiaRatio;\n const moments = [locked[0] ? largest : inertia.x, locked[1] ? largest : inertia.y, locked[2] ? largest : inertia.z].map((value) => value * mass);\n const tensor = ComposeInertia(moments, orientation);\n this._b3._bx_Body_SetMassDataFull(\n data.slot,\n mass,\n props.centerOfMass.x,\n props.centerOfMass.y,\n props.centerOfMass.z,\n tensor[0],\n tensor[1],\n tensor[2],\n tensor[3],\n tensor[4],\n tensor[5]\n );\n this._applyLockedAxes(data, locked, orientation);\n }\n\n /**\n * Box3D locks are world space, Babylon's zero inertia components are body local. Locking two of them leaves a single\n * free axis, and if that axis is world aligned the body can only ever spin about it, so the world locks are exact\n * and stay exact. Everything else relies on the large moment above.\n */\n private _applyLockedAxes(data: Box3DBodyData, locked: boolean[], orientation: Quaternion): void {\n const count = locked.filter(Boolean).length;\n if (count === 3) {\n this._applyMotionLocks(data, true, true, true);\n return;\n }\n if (count !== 2) {\n this._applyMotionLocks(data, false, false, false);\n return;\n }\n this._b3._bx_Body_GetTransform(data.slot);\n const s = this._scratch();\n const bodyRotation = this._tmpQuat[0].set(s[3], s[4], s[5], s[6]);\n const free = locked.indexOf(false);\n const axis = this._tmpVec3[0].set(free === 0 ? 1 : 0, free === 1 ? 1 : 0, free === 2 ? 1 : 0);\n axis.applyRotationQuaternionInPlace(orientation).applyRotationQuaternionInPlace(bodyRotation);\n const components = [Math.abs(axis.x), Math.abs(axis.y), Math.abs(axis.z)];\n const dominant = components.indexOf(Math.max(...components));\n if (components[dominant] > 0.9999) {\n this._applyMotionLocks(data, dominant !== 0, dominant !== 1, dominant !== 2);\n } else {\n this._applyMotionLocks(data, false, false, false);\n }\n }\n\n private _applyMotionLocks(data: Box3DBodyData, x: boolean, y: boolean, z: boolean): void {\n const locks = (x ? 1 : 0) | (y ? 2 : 0) | (z ? 4 : 0);\n if (locks === data.angularLocks) {\n return;\n }\n data.angularLocks = locks;\n this._b3._bx_Body_SetMotionLocks(data.slot, 0, 0, 0, x ? 1 : 0, y ? 1 : 0, z ? 1 : 0);\n }\n\n public computeMassProperties(body: PhysicsBody, instanceIndex?: number): PhysicsMassProperties {\n const data = this._getPluginReference(body, instanceIndex);\n this._b3._bx_Body_ApplyMassFromShapes(data.slot);\n const computed = this._readMassData(data);\n this._internalUpdateMassProperties(data);\n return computed;\n }\n\n public setMassProperties(body: PhysicsBody, massProps: PhysicsMassProperties, instanceIndex?: number): void {\n this._applyToBodyOrInstances(\n body,\n (data) => {\n data.userMassProps = massProps;\n this._internalUpdateMassProperties(data);\n },\n instanceIndex\n );\n }\n\n public getMassProperties(body: PhysicsBody, instanceIndex?: number): PhysicsMassProperties {\n return this._resolveMassProperties(this._getPluginReference(body, instanceIndex));\n }\n\n public setLinearDamping(body: PhysicsBody, damping: number, instanceIndex?: number): void {\n this._applyToBodyOrInstances(body, (data) => this._b3._bx_Body_SetLinearDamping(data.slot, damping), instanceIndex);\n }\n\n public getLinearDamping(body: PhysicsBody, instanceIndex?: number): number {\n return this._b3._bx_Body_GetLinearDamping(this._getPluginReference(body, instanceIndex).slot);\n }\n\n public setAngularDamping(body: PhysicsBody, damping: number, instanceIndex?: number): void {\n this._applyToBodyOrInstances(body, (data) => this._b3._bx_Body_SetAngularDamping(data.slot, damping), instanceIndex);\n }\n\n public getAngularDamping(body: PhysicsBody, instanceIndex?: number): number {\n return this._b3._bx_Body_GetAngularDamping(this._getPluginReference(body, instanceIndex).slot);\n }\n\n public setLinearVelocity(body: PhysicsBody, linVel: Vector3, instanceIndex?: number): void {\n this._applyToBodyOrInstances(body, (data) => this._b3._bx_Body_SetLinearVelocity(data.slot, linVel.x, linVel.y, linVel.z), instanceIndex);\n }\n\n public getLinearVelocityToRef(body: PhysicsBody, linVel: Vector3, instanceIndex?: number): void {\n this._b3._bx_Body_GetLinearVelocity(this._getPluginReference(body, instanceIndex).slot);\n const s = this._scratch();\n linVel.set(s[0], s[1], s[2]);\n }\n\n public applyImpulse(body: PhysicsBody, impulse: Vector3, location: Vector3, instanceIndex?: number): void {\n this._applyToBodyOrInstances(\n body,\n (data) => this._b3._bx_Body_ApplyLinearImpulse(data.slot, impulse.x, impulse.y, impulse.z, location.x, location.y, location.z),\n instanceIndex\n );\n }\n\n public applyAngularImpulse(body: PhysicsBody, angularImpulse: Vector3, instanceIndex?: number): void {\n this._applyToBodyOrInstances(body, (data) => this._b3._bx_Body_ApplyAngularImpulse(data.slot, angularImpulse.x, angularImpulse.y, angularImpulse.z), instanceIndex);\n }\n\n public applyForce(body: PhysicsBody, force: Vector3, location: Vector3, instanceIndex?: number): void {\n this._applyToBodyOrInstances(body, (data) => this._b3._bx_Body_ApplyForce(data.slot, force.x, force.y, force.z, location.x, location.y, location.z), instanceIndex);\n }\n\n public applyTorque(body: PhysicsBody, torque: Vector3, instanceIndex?: number): void {\n this._applyToBodyOrInstances(body, (data) => this._b3._bx_Body_ApplyTorque(data.slot, torque.x, torque.y, torque.z), instanceIndex);\n }\n\n public setAngularVelocity(body: PhysicsBody, angVel: Vector3, instanceIndex?: number): void {\n this._applyToBodyOrInstances(body, (data) => this._b3._bx_Body_SetAngularVelocity(data.slot, angVel.x, angVel.y, angVel.z), instanceIndex);\n }\n\n public getAngularVelocityToRef(body: PhysicsBody, angVel: Vector3, instanceIndex?: number): void {\n this._b3._bx_Body_GetAngularVelocity(this._getPluginReference(body, instanceIndex).slot);\n const s = this._scratch();\n angVel.set(s[0], s[1], s[2]);\n }\n\n public getBodyGeometry(body: PhysicsBody): { positions: Float32Array | number[]; indices: Uint32Array | number[] } {\n const shape = body.shape?._pluginData as Box3DShapeData | undefined;\n if (!shape) {\n return { positions: [], indices: [] };\n }\n const vertexCount = this._b3._bx_ShapeDesc_BuildDebugGeometry(shape.slot);\n const indexCount = this._b3._bx_DebugIndexCount();\n if (!vertexCount || !indexCount) {\n return { positions: [], indices: [] };\n }\n const positions = new Float32Array(this._b3.HEAPF32.buffer, this._b3._bx_DebugPositionsPtr(), vertexCount * 3).slice();\n const indices = new Uint32Array(this._b3.HEAPU32.buffer, this._b3._bx_DebugIndicesPtr(), indexCount).slice();\n return { positions, indices };\n }\n\n public disposeBody(body: PhysicsBody): void {\n this.removeBody(body);\n body._pluginData = undefined;\n body._pluginDataInstances.length = 0;\n }\n\n public setCollisionCallbackEnabled(body: PhysicsBody, enabled: boolean, instanceIndex?: number): void {\n // Havok replaces the mask with all three collision events, or clears it\n this.setEventMask(body, enabled ? Box3DEventBits.ALL : 0, instanceIndex);\n }\n\n public setCollisionEndedCallbackEnabled(body: PhysicsBody, enabled: boolean, instanceIndex?: number): void {\n this._applyToBodyOrInstances(\n body,\n (data) => {\n data.eventMask = enabled ? data.eventMask | Box3DEventBits.COLLISION_FINISHED : data.eventMask & ~Box3DEventBits.COLLISION_FINISHED;\n this._applyEventFlags(data);\n },\n instanceIndex\n );\n }\n\n public getCollisionObservable(body: PhysicsBody, instanceIndex?: number): Observable<IPhysicsCollisionEvent> {\n const slot = this._getPluginReference(body, instanceIndex).slot;\n let observable = this._bodyCollisionObservable.get(slot);\n if (!observable) {\n observable = new Observable<IPhysicsCollisionEvent>();\n this._bodyCollisionObservable.set(slot, observable);\n }\n return observable;\n }\n\n public getCollisionEndedObservable(body: PhysicsBody, instanceIndex?: number): Observable<IBasePhysicsCollisionEvent> {\n const slot = this._getPluginReference(body, instanceIndex).slot;\n let observable = this._bodyCollisionEndedObservable.get(slot);\n if (!observable) {\n observable = new Observable<IBasePhysicsCollisionEvent>();\n this._bodyCollisionEndedObservable.set(slot, observable);\n }\n return observable;\n }\n\n public setGravityFactor(body: PhysicsBody, factor: number, instanceIndex?: number): void {\n this._applyToBodyOrInstances(body, (data) => this._b3._bx_Body_SetGravityScale(data.slot, factor), instanceIndex);\n }\n\n public getGravityFactor(body: PhysicsBody, instanceIndex?: number): number {\n return this._b3._bx_Body_GetGravityScale(this._getPluginReference(body, instanceIndex).slot);\n }\n\n // ----------------------------------------------------------------------------------------\n // shapes\n // ----------------------------------------------------------------------------------------\n\n private _registerShape(shape: PhysicsShape, slot: number, type: PhysicsShapeType): Box3DShapeData {\n if (!slot) {\n throw new Error(\"Box3DPlugin: shape creation failed (degenerate geometry?)\");\n }\n const data = new Box3DShapeData(slot, type);\n shape._pluginData = data;\n this._shapes[slot] = data;\n return data;\n }\n\n private _withFloatBuffer<T>(values: ArrayLike<number>, fn: (ptr: number) => T): T {\n const ptr = this._b3._malloc(values.length * 4);\n new Float32Array(this._b3.HEAPF32.buffer, ptr, values.length).set(values);\n try {\n return fn(ptr);\n } finally {\n this._b3._free(ptr);\n }\n }\n\n /** Copies bytes into the module for the length of `fn`; with no bytes, `fn` gets a null pointer. */\n private _withByteBuffer<T>(values: Nullable<Uint8Array>, fn: (ptr: number) => T): T {\n if (!values || values.length === 0) {\n return fn(0);\n }\n const ptr = this._b3._malloc(values.length);\n new Uint8Array(this._b3.HEAPU8.buffer, ptr, values.length).set(values);\n try {\n return fn(ptr);\n } finally {\n this._b3._free(ptr);\n }\n }\n\n private _withIntBuffer<T>(values: ArrayLike<number>, fn: (ptr: number) => T): T {\n const ptr = this._b3._malloc(values.length * 4);\n new Int32Array(this._b3.HEAP32.buffer, ptr, values.length).set(values);\n try {\n return fn(ptr);\n } finally {\n this._b3._free(ptr);\n }\n }\n\n private _createOptionsFromGroundMesh(options: PhysicsShapeParameters): void {\n const mesh = options.groundMesh;\n if (!mesh) {\n return;\n }\n const pos = mesh.getVerticesData(VertexBuffer.PositionKind) as FloatArray;\n const transform = mesh.computeWorldMatrix(true);\n const transformed: number[] = [];\n const p = TmpVectors.Vector3[0];\n for (let i = 0; i < pos.length; i += 3) {\n Vector3.FromArrayToRef(pos, i, p);\n Vector3.TransformCoordinatesToRef(p, transform, p);\n p.toArray(transformed, i);\n }\n const arraySize = ~~(Math.sqrt(transformed.length / 3) - 1);\n const boundingInfo = mesh.getBoundingInfo();\n const dim = Math.min(boundingInfo.boundingBox.extendSizeWorld.x, boundingInfo.boundingBox.extendSizeWorld.z);\n const minX = boundingInfo.boundingBox.minimumWorld.x;\n const minY = boundingInfo.boundingBox.minimumWorld.y;\n const minZ = boundingInfo.boundingBox.minimumWorld.z;\n const matrix = new Float32Array((arraySize + 1) * (arraySize + 1));\n const elementSize = (dim * 2) / arraySize;\n matrix.fill(minY);\n for (let i = 0; i < transformed.length; i += 3) {\n const x = Math.round((transformed[i + 0] - minX) / elementSize);\n const z = arraySize - Math.round((transformed[i + 2] - minZ) / elementSize);\n matrix[z * (arraySize + 1) + x] = transformed[i + 1] - minY;\n }\n options.numHeightFieldSamplesX = arraySize + 1;\n options.numHeightFieldSamplesZ = arraySize + 1;\n options.heightFieldSizeX = boundingInfo.boundingBox.extendSizeWorld.x * 2;\n options.heightFieldSizeZ = boundingInfo.boundingBox.extendSizeWorld.z * 2;\n options.heightFieldData = matrix;\n }\n\n public initShape(shape: PhysicsShape, type: PhysicsShapeType, options: PhysicsShapeParameters): void {\n const b3 = this._b3;\n const center = options.center ?? Vector3.ZeroReadOnly;\n const rotation = options.rotation ?? Quaternion.Identity();\n switch (type) {\n case PhysicsShapeType.SPHERE: {\n const radius = options.radius ?? 1;\n this._registerShape(shape, b3._bx_ShapeDesc_CreateSphere(center.x, center.y, center.z, radius), type);\n break;\n }\n case PhysicsShapeType.CAPSULE: {\n const a = options.pointA ?? Vector3.ZeroReadOnly;\n const b = options.pointB ?? Vector3.UpReadOnly;\n this._registerShape(shape, b3._bx_ShapeDesc_CreateCapsule(a.x, a.y, a.z, b.x, b.y, b.z, options.radius ?? 0), type);\n break;\n }\n case PhysicsShapeType.BOX: {\n const extents = options.extents ?? Vector3.OneReadOnly;\n this._registerShape(\n shape,\n b3._bx_ShapeDesc_CreateBox(extents.x * 0.5, extents.y * 0.5, extents.z * 0.5, center.x, center.y, center.z, rotation.x, rotation.y, rotation.z, rotation.w),\n type\n );\n break;\n }\n case PhysicsShapeType.CYLINDER: {\n const a = options.pointA ?? Vector3.ZeroReadOnly;\n const b = options.pointB ?? Vector3.UpReadOnly;\n const axis = b.subtract(a);\n const height = axis.length();\n const q = this._tmpQuat[0];\n if (height > 1e-6) {\n axis.scaleInPlace(1 / height);\n Quaternion.FromUnitVectorsToRef(Vector3.UpReadOnly, axis, q);\n } else {\n q.set(0, 0, 0, 1);\n }\n // Box3D's cylinder runs from 0 to height along its local Y, so it goes at pointA, not at the middle.\n this._registerShape(shape, b3._bx_ShapeDesc_CreateCylinder(height, options.radius ?? 0, 16, a.x, a.y, a.z, q.x, q.y, q.z, q.w), type);\n break;\n }\n case PhysicsShapeType.CONVEX_HULL:\n case PhysicsShapeType.MESH: {\n if (!options.mesh && options.positions) {\n this._initShapeFromPositions(shape, type, options.positions, options.positionIndices);\n break;\n }\n const mesh = options.mesh;\n if (!mesh) {\n throw new Error(\"No mesh provided to create physics shape.\");\n }\n const needIndices = type === PhysicsShapeType.MESH;\n const flipWinding = !mesh.getScene().useRightHandedSystem;\n const accum = new MeshGeometryAccumulator(needIndices, flipWinding);\n accum.addNodeMeshes(mesh, !!options.includeChildMeshes);\n if (type === PhysicsShapeType.CONVEX_HULL) {\n const slot = this._withFloatBuffer(accum.vertices, (ptr) => b3._bx_ShapeDesc_CreateHull(ptr, accum.vertexCount));\n this._registerShape(shape, slot, type);\n } else {\n const slot = this._withFloatBuffer(accum.vertices, (vptr) =>\n this._withIntBuffer(accum.indices, (iptr) => b3._bx_ShapeDesc_CreateMesh(vptr, accum.vertexCount, iptr, accum.triangleCount, 1, 1, 1, 0, 0))\n );\n this._registerShape(shape, slot, type);\n }\n break;\n }\n case PhysicsShapeType.HEIGHTFIELD: {\n if (options.groundMesh) {\n this._createOptionsFromGroundMesh(options);\n }\n const nx = options.numHeightFieldSamplesX;\n const nz = options.numHeightFieldSamplesZ;\n if (!nx || !nz || !options.heightFieldSizeX || !options.heightFieldSizeZ || !options.heightFieldData) {\n throw new Error(\"Missing required heightfield parameters\");\n }\n const heights = new Float32Array(nx * nz);\n for (let x = 0; x < nx; x++) {\n for (let z = 0; z < nz; z++) {\n // box3d rows run along z (index z * countX + x); Babylon data rows are flipped along z\n heights[z * nx + x] = options.heightFieldData[(nz - 1 - z) * nx + x];\n }\n }\n const scaleX = options.heightFieldSizeX / (nx - 1);\n const scaleZ = options.heightFieldSizeZ / (nz - 1);\n const cellsX = nx - 1;\n const cellsZ = nz - 1;\n const source = options.heightFieldMaterials;\n if (source && source.length !== cellsX * cellsZ) {\n throw new Error(`heightFieldMaterials needs ${cellsX * cellsZ} cells (${cellsX} \u00D7 ${cellsZ}), got ${source.length}`);\n }\n // Cells flip along z the same way the heights do.\n const materials = source ? new Uint8Array(cellsX * cellsZ) : null;\n if (source && materials) {\n for (let x = 0; x < cellsX; x++) {\n for (let z = 0; z < cellsZ; z++) {\n materials[z * cellsX + x] = source[(cellsZ - 1 - z) * cellsX + x];\n }\n }\n }\n const slot = this._withFloatBuffer(heights, (heightsPtr) =>\n this._withByteBuffer(materials, (materialsPtr) =>\n b3._bx_ShapeDesc_CreateHeightField(\n heightsPtr,\n materialsPtr,\n nx,\n nz,\n scaleX,\n 1,\n scaleZ,\n 0,\n -options.heightFieldSizeX! * 0.5,\n 0,\n -options.heightFieldSizeZ! * 0.5\n )\n )\n );\n this._registerShape(shape, slot, type);\n break;\n }\n case PhysicsShapeType.CONTAINER: {\n this._registerShape(shape, b3._bx_ShapeDesc_CreateContainer(), type);\n break;\n }\n default:\n throw new Error(\"Unsupported Shape Type.\");\n }\n }\n\n private _initShapeFromPositions(shape: PhysicsShape, type: PhysicsShapeType, positions: ArrayLike<number>, indices: ArrayLike<number> | undefined): void {\n const b3 = this._b3;\n if (positions.length % 3 !== 0) {\n throw new Error(`positions needs x, y, z triplets, got ${positions.length} numbers`);\n }\n const vertexCount = positions.length / 3;\n if (type === PhysicsShapeType.CONVEX_HULL) {\n this._registerShape(\n shape,\n this._withFloatBuffer(positions, (ptr) => b3._bx_ShapeDesc_CreateHull(ptr, vertexCount)),\n type\n );\n return;\n }\n if (!indices || indices.length % 3 !== 0) {\n throw new Error(\"a MESH shape from positions needs positionIndices, three per triangle\");\n }\n for (let i = 0; i < indices.length; i++) {\n if (indices[i] < 0 || indices[i] >= vertexCount || !Number.isInteger(indices[i])) {\n throw new Error(`positionIndices[${i}] is ${indices[i]}, but there are ${vertexCount} points`);\n }\n }\n this._registerShape(\n shape,\n this._withFloatBuffer(positions, (vptr) =>\n this._withIntBuffer(indices, (iptr) => b3._bx_ShapeDesc_CreateMesh(vptr, vertexCount, iptr, indices.length / 3, 1, 1, 1, 0, 0))\n ),\n type\n );\n }\n\n // Re-instantiates the shape on every body that uses it (or uses a container holding it). Only needed for geometry\n // and child changes; filters, materials and density are applied in place, see _syncShapeUsers.\n private _refreshShapeUsers(data: Box3DShapeData, visited = new Set<Box3DShapeData>()): void {\n if (visited.has(data)) {\n return;\n }\n visited.add(data);\n for (const body of data.users) {\n this._b3._bx_Body_SetShape(body.slot, data.slot);\n this._applyEventFlags(body);\n this._internalUpdateMassProperties(body);\n }\n for (const parent of data.parents) {\n this._refreshShapeUsers(parent, visited);\n }\n }\n\n /**\n * Pushes changed description properties into the Box3D shapes that are already on the bodies using this shape,\n * directly or through a container. Rebuilding them instead would drop their contacts and re-apply the body mass.\n */\n private _syncShapeUsers(data: Box3DShapeData, what: Box3DShapeSync, visited = new Set<Box3DShapeData>(), changed = data): void {\n if (visited.has(data)) {\n return;\n }\n visited.add(data);\n for (const body of data.users) {\n this._b3._bx_Body_SyncShapeDesc(body.slot, changed.slot, what);\n if (what & Box3DShapeSync.DENSITY) {\n this._internalUpdateMassProperties(body);\n }\n }\n for (const parent of data.parents) {\n this._syncShapeUsers(parent, what, visited, changed);\n }\n }\n\n public setShapeFilterMembershipMask(shape: PhysicsShape, membershipMask: number): void {\n const data = shape._pluginData as Box3DShapeData;\n const collide = this._b3._bx_ShapeDesc_GetMaskBits(data.slot);\n this._b3._bx_ShapeDesc_SetFilter(data.slot, membershipMask >>> 0, collide >>> 0);\n this._syncShapeUsers(data, Box3DShapeSync.FILTER);\n }\n\n public getShapeFilterMembershipMask(shape: PhysicsShape): number {\n return this._b3._bx_ShapeDesc_GetCategoryBits((shape._pluginData as Box3DShapeData).slot);\n }\n\n public setShapeFilterCollideMask(shape: PhysicsShape, collideMask: number): void {\n const data = shape._pluginData as Box3DShapeData;\n const membership = this._b3._bx_ShapeDesc_GetCategoryBits(data.slot);\n this._b3._bx_ShapeDesc_SetFilter(data.slot, membership >>> 0, collideMask >>> 0);\n this._syncShapeUsers(data, Box3DShapeSync.FILTER);\n }\n\n public getShapeFilterCollideMask(shape: PhysicsShape): number {\n return this._b3._bx_ShapeDesc_GetMaskBits((shape._pluginData as Box3DShapeData).slot);\n }\n\n public setMaterial(shape: PhysicsShape, material: PhysicsMaterial): void {\n const data = shape._pluginData as Box3DShapeData;\n data.material = material;\n this._b3._bx_ShapeDesc_SetMaterial(data.slot, material.friction ?? 0.5, material.restitution ?? 0);\n this._syncShapeUsers(data, Box3DShapeSync.MATERIAL);\n }\n\n public getMaterial(shape: PhysicsShape): PhysicsMaterial {\n const data = shape._pluginData as Box3DShapeData;\n return {\n friction: this._b3._bx_ShapeDesc_GetFriction(data.slot),\n staticFriction: data.material.staticFriction,\n restitution: this._b3._bx_ShapeDesc_GetRestitution(data.slot),\n frictionCombine: data.material.frictionCombine,\n restitutionCombine: data.material.restitutionCombine,\n };\n }\n\n public setDensity(shape: PhysicsShape, density: number): void {\n const data = shape._pluginData as Box3DShapeData;\n this._b3._bx_ShapeDesc_SetDensity(data.slot, density);\n this._syncShapeUsers(data, Box3DShapeSync.DENSITY);\n }\n\n public getDensity(shape: PhysicsShape): number {\n return this._b3._bx_ShapeDesc_GetDensity((shape._pluginData as Box3DShapeData).slot);\n }\n\n public addChild(shape: PhysicsShape, newChild: PhysicsShape, translation?: Vector3, rotation?: Quaternion, scale?: Vector3): void {\n const parent = shape._pluginData as Box3DShapeData;\n const child = newChild._pluginData as Box3DShapeData;\n const t = translation ?? Vector3.ZeroReadOnly;\n const r = rotation ?? Quaternion.Identity();\n const s = scale ?? Vector3.OneReadOnly;\n this._b3._bx_ShapeDesc_AddChild(parent.slot, child.slot, t.x, t.y, t.z, r.x, r.y, r.z, r.w, s.x, s.y, s.z);\n parent.children.push(child);\n child.parents.add(parent);\n this._refreshShapeUsers(parent);\n }\n\n public removeChild(shape: PhysicsShape, childIndex: number): void {\n const parent = shape._pluginData as Box3DShapeData;\n this._b3._bx_ShapeDesc_RemoveChild(parent.slot, childIndex);\n const [child] = parent.children.splice(childIndex, 1);\n if (child && !parent.children.includes(child)) {\n child.parents.delete(parent);\n }\n this._refreshShapeUsers(parent);\n }\n\n public getNumChildren(shape: PhysicsShape): number {\n return this._b3._bx_ShapeDesc_GetChildCount((shape._pluginData as Box3DShapeData).slot);\n }\n\n public getBoundingBox(shape: PhysicsShape): BoundingBox {\n this._b3._bx_ShapeDesc_GetAABB((shape._pluginData as Box3DShapeData).slot);\n const s = this._scratch();\n TmpVectors.Vector3[0].set(s[0], s[1], s[2]);\n TmpVectors.Vector3[1].set(s[3], s[4], s[5]);\n return new BoundingBox(TmpVectors.Vector3[0], TmpVectors.Vector3[1], Matrix.IdentityReadOnly);\n }\n\n public getBodyBoundingBox(body: PhysicsBody): BoundingBox {\n const data = this._getPluginReference(body);\n this._b3._bx_Body_GetAABB(data.slot);\n const s = this._scratch();\n TmpVectors.Vector3[0].set(s[0], s[1], s[2]);\n TmpVectors.Vector3[1].set(s[3], s[4], s[5]);\n return new BoundingBox(TmpVectors.Vector3[0], TmpVectors.Vector3[1], Matrix.IdentityReadOnly);\n }\n\n public disposeShape(shape: PhysicsShape): void {\n const data = shape._pluginData as Box3DShapeData;\n if (!data) {\n return;\n }\n for (const parent of data.parents) {\n const index = parent.children.indexOf(data);\n if (index >= 0) {\n parent.children.splice(index, 1);\n this._b3._bx_ShapeDesc_RemoveChild(parent.slot, index);\n }\n }\n for (const child of data.children) {\n child.parents.delete(data);\n }\n this._shapes[data.slot] = undefined;\n this._b3._bx_ShapeDesc_Destroy(data.slot);\n shape._pluginData = undefined;\n }\n\n public setTrigger(shape: PhysicsShape, isTrigger: boolean): void {\n const data = shape._pluginData as Box3DShapeData;\n this._b3._bx_ShapeDesc_SetSensor(data.slot, isTrigger ? 1 : 0);\n // Box3D decides at creation whether a shape is a sensor, so this one does need a rebuild\n this._refreshShapeUsers(data);\n }\n\n // ----------------------------------------------------------------------------------------\n // constraints\n // ----------------------------------------------------------------------------------------\n\n private _frameToBuffer(buffer: Float32Array, offset: number, pivot: Vector3, xAxis: Vector3, yAxis: Vector3, zAxis: Vector3): void {\n const m = TmpVectors.Matrix[0];\n Matrix.FromValuesToRef(xAxis.x, xAxis.y, xAxis.z, 0, yAxis.x, yAxis.y, yAxis.z, 0, zAxis.x, zAxis.y, zAxis.z, 0, 0, 0, 0, 1, m);\n const q = this._tmpQuat[2];\n Quaternion.FromRotationMatrixToRef(m, q);\n q.normalize();\n buffer[offset] = pivot.x;\n buffer[offset + 1] = pivot.y;\n buffer[offset + 2] = pivot.z;\n buffer[offset + 3] = q.x;\n buffer[offset + 4] = q.y;\n buffer[offset + 5] = q.z;\n buffer[offset + 6] = q.w;\n }\n\n private _buildFrames(cdata: Box3DConstraintData, constraint: PhysicsConstraint, bodyA: Box3DBodyData, bodyB: Box3DBodyData): void {\n const options = constraint.options;\n const pivotA = options.pivotA ?? Vector3.ZeroReadOnly;\n const pivotB = options.pivotB ?? Vector3.ZeroReadOnly;\n const axisA = (options.axisA ?? Vector3.RightReadOnly).normalizeToNew();\n const axisB = (options.axisB ?? Vector3.RightReadOnly).normalizeToNew();\n const perpA = options.perpAxisA ? options.perpAxisA.normalizeToNew() : axisA.getNormalToRef(new Vector3());\n const perpB = options.perpAxisB ? options.perpAxisB.normalizeToNew() : axisB.getNormalToRef(new Vector3());\n // Gram-Schmidt in case the user's perp axis is not exactly perpendicular\n perpA.subtractInPlace(axisA.scale(Vector3.Dot(axisA, perpA))).normalize();\n perpB.subtractInPlace(axisB.scale(Vector3.Dot(axisB, perpB))).normalize();\n const thirdA = Vector3.Cross(axisA, perpA);\n const thirdB = Vector3.Cross(axisB, perpB);\n\n if (!constraint._initOptions) {\n constraint._initOptions = {\n axisA: axisA.clone(),\n axisB: axisB.clone(),\n perpAxisA: perpA.clone(),\n perpAxisB: perpB.clone(),\n pivotA: pivotA.clone(),\n pivotB: pivotB.clone(),\n };\n }\n\n const frames = cdata.frames;\n if (cdata.plan) {\n // SIX_DOF: the constraint basis is Havok's [axis, perpAxis, axis x perpAxis]; the plan picks which of them\n // becomes Box3D's frame x, y and z (cyclic permutations, so the frames stay right handed)\n const basis = cdata.plan.basis;\n if (basis) {\n const basisA = [axisA, perpA, thirdA];\n const basisB = [axisB, perpB, thirdB];\n this._frameToBuffer(frames, 0, pivotA, basisA[basis[0]], basisA[basis[1]], basisA[basis[2]]);\n this._frameToBuffer(frames, 7, pivotB, basisB[basis[0]], basisB[basis[1]], basisB[basis[2]]);\n } else {\n frames.set([pivotA.x, pivotA.y, pivotA.z, 0, 0, 0, 1, pivotB.x, pivotB.y, pivotB.z, 0, 0, 0, 1]);\n }\n return;\n }\n switch (cdata.type) {\n case PhysicsConstraintType.HINGE:\n case PhysicsConstraintType.BALL_AND_SOCKET:\n // box3d: revolute rotates about the frame z axis, spherical cone is centered on frame A z\n this._frameToBuffer(frames, 0, pivotA, perpA, Vector3.Cross(axisA, perpA), axisA);\n this._frameToBuffer(frames, 7, pivotB, perpB, Vector3.Cross(axisB, perpB), axisB);\n break;\n case PhysicsConstraintType.PRISMATIC:\n case PhysicsConstraintType.SLIDER:\n // box3d: prismatic slides along the frame A x axis\n this._frameToBuffer(frames, 0, pivotA, axisA, perpA, thirdA);\n this._frameToBuffer(frames, 7, pivotB, axisB, perpB, thirdB);\n break;\n case PhysicsConstraintType.LOCK: {\n // weld the bodies in their current relative pose\n this._b3._bx_Body_GetTransform(bodyA.slot);\n let s = this._scratch();\n const qA = this._tmpQuat[0];\n qA.set(s[3], s[4], s[5], s[6]);\n this._b3._bx_Body_GetTransform(bodyB.slot);\n s = this._scratch();\n const qB = this._tmpQuat[1];\n qB.set(s[3], s[4], s[5], s[6]);\n // frameB rotation = inv(qB) * qA so both frames coincide in world space now\n const rel = qB.invert().multiply(qA).normalize();\n frames.set([pivotA.x, pivotA.y, pivotA.z, 0, 0, 0, 1, pivotB.x, pivotB.y, pivotB.z, rel.x, rel.y, rel.z, rel.w]);\n break;\n }\n default:\n frames.set([pivotA.x, pivotA.y, pivotA.z, 0, 0, 0, 1, pivotB.x, pivotB.y, pivotB.z, 0, 0, 0, 1]);\n break;\n }\n }\n\n private _createJoint(cdata: Box3DConstraintData, bodyA: Box3DBodyData, bodyB: Box3DBodyData): number {\n this._scratch().set(cdata.frames);\n const joint = this._b3._bx_CreateJoint(this._worldSlot, cdata.jointType, bodyA.slot, bodyB.slot, cdata.collisions ? 1 : 0, cdata.length);\n if (!joint) {\n Logger.Warn(\"Box3DPlugin: joint creation failed.\");\n return 0;\n }\n // A slider allows rotation about the axis in Havok. Box3D's prismatic locks it.\n this._applyAxisState(cdata, joint, bodyA, bodyB);\n return joint;\n }\n\n /** Reads Physics6DoFConstraint.limits into the axis table with Havok's rules. */\n private _readSixDofLimits(cdata: Box3DConstraintData, limits: ReadonlyArray<Physics6DoFLimit> | undefined): void {\n for (const limit of limits ?? []) {\n const state = this._axisState(cdata, limit.axis);\n if (limit.minLimit === 0 && limit.maxLimit === 0) {\n state.mode = PhysicsConstraintAxisLimitMode.LOCKED;\n state.min = 0;\n state.max = 0;\n } else if (limit.minLimit !== undefined || limit.maxLimit !== undefined) {\n // a missing side is unbounded\n state.mode = PhysicsConstraintAxisLimitMode.LIMITED;\n state.min = limit.minLimit ?? -Infinity;\n state.max = limit.maxLimit ?? Infinity;\n }\n state.stiffness = limit.stiffness ?? 0;\n state.damping = limit.damping ?? 0;\n }\n }\n\n /**\n * Maps the six axes of a SIX_DOF constraint onto one Box3D joint, following Havok's semantics: an axis that is not\n * listed is free, 0/0 is locked, anything else is limited. The constraint frame is [axis, perpAxis, axis x perpAxis];\n * ANGULAR_X rotates about axis, ANGULAR_Y about perpAxis and ANGULAR_Z about axis x perpAxis, all measured as the\n * rotation of the child frame relative to the parent frame (right handed, like Havok).\n * - all linear locked, all angular locked: weld\n * - all linear locked, one angular axis open: revolute about it, with its limits (one sided ranges work)\n * - all linear locked, two or three angular axes open: spherical, twist limits from ANGULAR_X and one symmetric\n * cone from ANGULAR_Y/Z (Box3D has no elliptical cone, the larger swing range is used)\n * - two linear locked, angular locked: prismatic along the open linear axis\n * - only LINEAR_DISTANCE constrained: distance joint (a spring when min == max and a stiffness is set)\n * - nothing constrained: filter joint (collision filtering only)\n * Anything else warns once and uses the closest of these.\n */\n private _planSixDof(cdata: Box3DConstraintData): ISixDofPlan {\n const Axis = PhysicsConstraintAxis;\n const Mode = PhysicsConstraintAxisLimitMode;\n const mode = (axis: PhysicsConstraintAxis) => cdata.axes.get(axis)?.mode ?? Mode.FREE;\n const range = (axis: PhysicsConstraintAxis): [number, number] => {\n const state = cdata.axes.get(axis)!;\n return state.mode === Mode.LOCKED ? [0, 0] : [Math.min(state.min, state.max), Math.max(state.min, state.max)];\n };\n const clamp = (value: number, limit: number) => Math.max(-limit, Math.min(limit, value));\n const maxAngle = 0.99 * Math.PI;\n // Box3D's B3_HUGE, keeps an unbounded side of a linear range out of the solver as a real number\n const maxLength = 100000;\n const plan: ISixDofPlan = {\n jointType: Box3DJointType.WELD,\n basis: [0, 1, 2],\n primaryAxis: null,\n coneAngle: -1,\n twist: null,\n limit: null,\n spring: false,\n stiffness: 0,\n damping: 0,\n angularStiffness: false,\n };\n for (const [axis, state] of cdata.axes) {\n if ((state.stiffness > 0 || state.damping > 0) && state.stiffness >= plan.stiffness) {\n plan.stiffness = state.stiffness;\n plan.damping = state.damping;\n plan.angularStiffness = axis === Axis.ANGULAR_X || axis === Axis.ANGULAR_Y || axis === Axis.ANGULAR_Z;\n }\n }\n const linear = [Axis.LINEAR_X, Axis.LINEAR_Y, Axis.LINEAR_Z];\n const angular = [Axis.ANGULAR_X, Axis.ANGULAR_Y, Axis.ANGULAR_Z];\n const linearLocked = linear.filter((a) => mode(a) === Mode.LOCKED).length;\n const linearFree = linear.filter((a) => mode(a) === Mode.FREE).length;\n const angularOpen = angular.filter((a) => mode(a) !== Mode.LOCKED);\n const angularFree = angular.filter((a) => mode(a) === Mode.FREE).length;\n const distanceMode = mode(Axis.LINEAR_DISTANCE);\n\n if (distanceMode !== Mode.FREE) {\n if (linearFree === 3 && angularFree === 3) {\n const [lower, upper] = range(Axis.LINEAR_DISTANCE);\n plan.jointType = Box3DJointType.DISTANCE;\n plan.basis = null;\n plan.primaryAxis = Axis.LINEAR_DISTANCE;\n plan.limit = [Math.min(Math.max(0, lower), maxLength), Math.min(Math.max(0, upper), maxLength)];\n plan.spring = plan.stiffness > 0 && Math.abs(upper - lower) < 1e-6 && isFinite(lower);\n return plan;\n }\n this._warnOnce(\"sixdof-distance\", \"SIX_DOF: LINEAR_DISTANCE combined with other constrained axes is not supported with Box3D, the distance limit is ignored.\");\n }\n\n // one open linear axis (free or limited) with the other two locked slides; see the prismatic case below\n let pointJoint = linearLocked === 3;\n if (!pointJoint && linearLocked !== 2 && linearFree === 0) {\n this._warnOnce(\"sixdof-linear-limited\", \"SIX_DOF: two or more limited linear axes are treated as locked with Box3D.\");\n pointJoint = true;\n }\n if (pointJoint) {\n if (angularOpen.length === 0) {\n return plan;\n }\n if (angularOpen.length === 1) {\n // Box3D revolutes rotate about frame z\n const axis = angularOpen[0];\n plan.jointType = Box3DJointType.REVOLUTE;\n plan.basis = [\n [1, 2, 0],\n [2, 0, 1],\n [0, 1, 2],\n ][angular.indexOf(axis)] as [number, number, number];\n plan.primaryAxis = axis;\n if (mode(axis) === Mode.LIMITED) {\n const [lower, upper] = range(axis);\n plan.limit = [clamp(lower, maxAngle), clamp(upper, maxAngle)];\n }\n return plan;\n }\n // spherical: cone centered on frame z (axis), twist about frame z\n plan.jointType = Box3DJointType.SPHERICAL;\n plan.basis = [1, 2, 0];\n if (mode(Axis.ANGULAR_X) !== Mode.FREE) {\n const [lower, upper] = range(Axis.ANGULAR_X);\n plan.twist = [clamp(lower, maxAngle), clamp(upper, maxAngle)];\n }\n const swingModes = [mode(Axis.ANGULAR_Y), mode(Axis.ANGULAR_Z)];\n if (swingModes.some((m) => m !== Mode.FREE)) {\n const extents: number[] = [];\n let asymmetric = false;\n for (const axis of [Axis.ANGULAR_Y, Axis.ANGULAR_Z]) {\n if (mode(axis) === Mode.FREE) {\n continue;\n }\n const [lower, upper] = range(axis);\n extents.push(Math.max(Math.abs(lower), Math.abs(upper)));\n asymmetric ||= Math.abs(lower + upper) > 1e-4;\n }\n const cone = Math.max(...extents);\n if (isFinite(cone)) {\n if (swingModes.includes(Mode.FREE) || Math.abs(extents[0] - extents[1]) > 1e-4 || asymmetric) {\n this._warnOnce(\n \"sixdof-cone\",\n \"SIX_DOF: Box3D has one symmetric swing cone, ANGULAR_Y and ANGULAR_Z use the larger of their ranges.\"\n );\n }\n if (cone > Math.PI / 2) {\n this._warnOnce(\"sixdof-cone-90\", \"SIX_DOF: Box3D cone limits are at most 90 degrees, larger swing ranges are clamped.\");\n }\n plan.coneAngle = Math.min(cone, Math.PI / 2);\n }\n }\n return plan;\n }\n\n if (linearLocked === 2) {\n // Box3D prismatics slide along frame x\n const slide = linear.find((a) => mode(a) !== Mode.LOCKED)!;\n plan.jointType = Box3DJointType.PRISMATIC;\n plan.basis = [\n [0, 1, 2],\n [1, 2, 0],\n [2, 0, 1],\n ][linear.indexOf(slide)] as [number, number, number];\n plan.primaryAxis = slide;\n if (mode(slide) === Mode.LIMITED) {\n const [lower, upper] = range(slide);\n plan.limit = [clamp(lower, maxLength), clamp(upper, maxLength)];\n }\n if (angularOpen.length) {\n this._warnOnce(\"sixdof-prismatic\", \"SIX_DOF: a sliding axis with rotation is not supported with Box3D, rotation is locked.\");\n }\n return plan;\n }\n\n plan.jointType = Box3DJointType.FILTER;\n plan.basis = null;\n if (linearFree !== 3 || angularFree !== 3) {\n this._warnOnce(\"sixdof-unsupported\", \"SIX_DOF: this combination of free and limited axes is not supported with Box3D, the bodies are left unconstrained.\");\n }\n return plan;\n }\n\n /** Box3D spring settings for a Havok spring constant and damping on a body pair. */\n private _springToHertz(stiffness: number, damping: number, angular: boolean, bodyA: Box3DBodyData, bodyB: Box3DBodyData): { hertz: number; dampingRatio: number } {\n // effective mass (or rotational inertia) of the pair, a static or animated body counts as infinitely heavy\n const inverse = (data: Box3DBodyData) => {\n if (data.motionType !== PhysicsMotionType.DYNAMIC) {\n return 0;\n }\n this._b3._bx_Body_GetMassData(data.slot);\n const s = this._scratch();\n const value = angular ? (s[4] + s[5] + s[6]) / 3 : s[0];\n return value > 0 ? 1 / value : 0;\n };\n const inverseSum = inverse(bodyA) + inverse(bodyB);\n const mass = inverseSum > 0 ? 1 / inverseSum : 1;\n const k = Math.max(stiffness, 0);\n return {\n hertz: Math.sqrt(k / mass) / (2 * Math.PI),\n dampingRatio: k > 0 ? damping / (2 * Math.sqrt(k * mass)) : 1,\n };\n }\n\n public initConstraint(constraint: PhysicsConstraint, body: PhysicsBody, childBody: PhysicsBody, instanceIndex?: number, childInstanceIndex?: number): void {\n const type = constraint.type;\n const options = constraint.options;\n if (!type || !options) {\n Logger.Warn(\"No constraint type or options. Constraint is invalid.\");\n return;\n }\n if ((body._pluginDataInstances.length > 0 && instanceIndex === undefined) || (childBody._pluginDataInstances.length > 0 && childInstanceIndex === undefined)) {\n Logger.Warn(\"Body is instanced but no instance index was specified. Constraint will not be applied.\");\n return;\n }\n const firstPair = !constraint._pluginData;\n const cdata: Box3DConstraintData = constraint._pluginData ?? new Box3DConstraintData();\n constraint._pluginData = cdata;\n cdata.type = type;\n if (firstPair) {\n cdata.collisions = !!options.collision;\n }\n switch (type) {\n case PhysicsConstraintType.BALL_AND_SOCKET:\n cdata.jointType = Box3DJointType.SPHERICAL;\n break;\n case PhysicsConstraintType.HINGE:\n cdata.jointType = Box3DJointType.REVOLUTE;\n break;\n case PhysicsConstraintType.PRISMATIC:\n case PhysicsConstraintType.SLIDER:\n cdata.jointType = Box3DJointType.PRISMATIC;\n break;\n case PhysicsConstraintType.LOCK:\n cdata.jointType = Box3DJointType.WELD;\n break;\n case PhysicsConstraintType.DISTANCE:\n cdata.jointType = Box3DJointType.DISTANCE;\n break;\n case PhysicsConstraintType.SIX_DOF:\n // later pairs of the same constraint share the axis table, including changes made since the first pair\n if (firstPair) {\n this._readSixDofLimits(cdata, (constraint as Physics6DoFConstraint).limits);\n }\n cdata.plan = this._planSixDof(cdata);\n cdata.jointType = cdata.plan.jointType;\n break;\n default:\n Logger.Warn(\"Box3DPlugin: unknown constraint type \" + type);\n return;\n }\n\n const bodyA = this._getPluginReference(body, instanceIndex);\n const bodyB = this._getPluginReference(childBody, childInstanceIndex);\n this._buildFrames(cdata, constraint, bodyA, bodyB);\n this._updateJointLength(cdata, options.maxDistance, bodyA, bodyB);\n // joints[i] belongs to pairs[i], 0 while the constraint is disabled or when creation failed\n const joint = cdata.enabled ? this._createJoint(cdata, bodyA, bodyB) : 0;\n cdata.joints.push(joint);\n cdata.pairs.push({ parent: body, parentIndex: instanceIndex ?? 0, child: childBody, childIndex: childInstanceIndex ?? 0, parentData: bodyA, childData: bodyB });\n }\n\n /** Length parameter passed to Box3D's distance joint at creation (the rest length of its spring). */\n private _updateJointLength(cdata: Box3DConstraintData, maxDistance: number | undefined, bodyA: Box3DBodyData, bodyB: Box3DBodyData): void {\n if (cdata.type === PhysicsConstraintType.DISTANCE) {\n cdata.length = maxDistance ?? 0;\n } else if (cdata.plan?.jointType === Box3DJointType.DISTANCE && cdata.plan.limit) {\n // a spring rests at its (single) limit; for a rope the rest length is unused, its limits do the work\n cdata.length = cdata.plan.limit[0];\n } else {\n return;\n }\n if (cdata.length <= 0) {\n // use the current distance between the world space pivots\n cdata.length = Math.max(0.01, this._currentPivotDistance(cdata, bodyA, bodyB));\n }\n }\n\n private _currentPivotDistance(cdata: Box3DConstraintData, bodyA: Box3DBodyData, bodyB: Box3DBodyData): number {\n const f = cdata.frames;\n const worldA = this._tmpVec3[0];\n const worldB = this._tmpVec3[1];\n this._b3._bx_Body_GetTransform(bodyA.slot);\n let s = this._scratch();\n this._tmpQuat[0].set(s[3], s[4], s[5], s[6]);\n worldA.set(f[0], f[1], f[2]).applyRotationQuaternionInPlace(this._tmpQuat[0]).addInPlaceFromFloats(s[0], s[1], s[2]);\n this._b3._bx_Body_GetTransform(bodyB.slot);\n s = this._scratch();\n this._tmpQuat[0].set(s[3], s[4], s[5], s[6]);\n worldB.set(f[7], f[8], f[9]).applyRotationQuaternionInPlace(this._tmpQuat[0]).addInPlaceFromFloats(s[0], s[1], s[2]);\n return Vector3.Distance(worldA, worldB);\n }\n\n public setEnabled(constraint: PhysicsConstraint, isEnabled: boolean): void {\n const cdata = constraint._pluginData as Box3DConstraintData;\n if (!cdata || cdata.enabled === isEnabled) {\n return;\n }\n cdata.enabled = isEnabled;\n // Box3D has no enable flag on joints: destroy them, or re-create them from the saved frames, plan and axis state.\n this._recreateJoints(cdata);\n }\n\n private _destroyJoint(joint: number): void {\n this._motorJoints.delete(joint);\n this._b3._bx_DestroyJoint(joint);\n }\n\n private _recreateJoints(cdata: Box3DConstraintData): void {\n for (let i = 0; i < cdata.pairs.length; i++) {\n if (cdata.joints[i]) {\n this._destroyJoint(cdata.joints[i]);\n }\n const pair = cdata.pairs[i];\n cdata.joints[i] = cdata.enabled && pair.parentData.slot && pair.childData.slot ? this._createJoint(cdata, pair.parentData, pair.childData) : 0;\n }\n }\n\n public getEnabled(constraint: PhysicsConstraint): boolean {\n return (constraint._pluginData as Box3DConstraintData)?.enabled ?? false;\n }\n\n public setCollisionsEnabled(constraint: PhysicsConstraint, isEnabled: boolean): void {\n const cdata = constraint._pluginData as Box3DConstraintData;\n cdata.collisions = isEnabled;\n for (const joint of cdata.joints) {\n if (joint) {\n this._b3._bx_Joint_SetCollideConnected(joint, isEnabled ? 1 : 0);\n }\n }\n }\n\n public getCollisionsEnabled(constraint: PhysicsConstraint): boolean {\n return (constraint._pluginData as Box3DConstraintData)?.collisions ?? false;\n }\n\n // The one axis box3d exposes for this constraint type.\n private _primaryAxis(cdata: Box3DConstraintData): Nullable<PhysicsConstraintAxis> {\n switch (cdata.type) {\n case PhysicsConstraintType.HINGE:\n return PhysicsConstraintAxis.ANGULAR_X;\n case PhysicsConstraintType.PRISMATIC:\n case PhysicsConstraintType.SLIDER:\n return PhysicsConstraintAxis.LINEAR_X;\n case PhysicsConstraintType.DISTANCE:\n return PhysicsConstraintAxis.LINEAR_DISTANCE;\n case PhysicsConstraintType.BALL_AND_SOCKET:\n return PhysicsConstraintAxis.ANGULAR_Y;\n case PhysicsConstraintType.SIX_DOF:\n return cdata.plan?.primaryAxis ?? null;\n default:\n return null;\n }\n }\n\n private _isAngularAxis(axis: PhysicsConstraintAxis): boolean {\n return axis === PhysicsConstraintAxis.ANGULAR_X || axis === PhysicsConstraintAxis.ANGULAR_Y || axis === PhysicsConstraintAxis.ANGULAR_Z;\n }\n\n private _isPrimaryAxis(cdata: Box3DConstraintData, axis: PhysicsConstraintAxis): boolean {\n if (cdata.type === PhysicsConstraintType.BALL_AND_SOCKET || cdata.plan?.jointType === Box3DJointType.SPHERICAL) {\n return this._isAngularAxis(axis);\n }\n return axis === this._primaryAxis(cdata);\n }\n\n private _axisState(cdata: Box3DConstraintData, axis: PhysicsConstraintAxis): IAxisState {\n let state = cdata.axes.get(axis);\n if (!state) {\n state = {\n mode: PhysicsConstraintAxisLimitMode.FREE,\n min: 0,\n max: 0,\n motor: PhysicsConstraintMotorType.NONE,\n target: 0,\n maxForce: 0,\n friction: 0,\n stiffness: 0,\n damping: 0,\n };\n cdata.axes.set(axis, state);\n }\n return state;\n }\n\n private _applyAxisState(cdata: Box3DConstraintData, joint: number, bodyA: Box3DBodyData, bodyB: Box3DBodyData): void {\n const b3 = this._b3;\n if (cdata.plan) {\n this._applySixDofPlan(cdata, joint, bodyA, bodyB);\n b3._bx_Joint_WakeBodies(joint);\n return;\n }\n const primary = this._primaryAxis(cdata);\n if (primary === null) {\n return;\n }\n for (const [axis, state] of cdata.axes) {\n if (!this._isPrimaryAxis(cdata, axis)) {\n continue;\n }\n if (cdata.type === PhysicsConstraintType.BALL_AND_SOCKET) {\n if (axis === PhysicsConstraintAxis.ANGULAR_X) {\n // twist about the primary axis (frame z in box3d)\n b3._bx_Joint_SetTwistLimits(joint, state.mode === PhysicsConstraintAxisLimitMode.FREE ? 0 : 1, state.min, state.max);\n continue;\n }\n }\n const limited = state.mode !== PhysicsConstraintAxisLimitMode.FREE;\n if (limited) {\n const min = state.mode === PhysicsConstraintAxisLimitMode.LOCKED ? 0 : state.min;\n const max = state.mode === PhysicsConstraintAxisLimitMode.LOCKED ? 0 : state.max;\n b3._bx_Joint_SetLimits(joint, min, max);\n }\n b3._bx_Joint_EnableLimit(joint, limited ? 1 : 0);\n if (cdata.type !== PhysicsConstraintType.BALL_AND_SOCKET) {\n this._applyMotor(joint, state);\n }\n }\n if (cdata.type === PhysicsConstraintType.BALL_AND_SOCKET) {\n this._applySphericalMotor(cdata, joint);\n }\n b3._bx_Joint_WakeBodies(joint);\n }\n\n /**\n * Box3D's spherical joint has one motor for the whole joint: a relative angular velocity, and one spring towards a\n * target rotation. Babylon has a motor per axis, so the three angular axes are combined into one target in the\n * joint frame (ANGULAR_X about frame z, ANGULAR_Y about frame x, ANGULAR_Z about frame y).\n */\n private _applySphericalMotor(cdata: Box3DConstraintData, joint: number): void {\n const b3 = this._b3;\n const twist = cdata.axes.get(PhysicsConstraintAxis.ANGULAR_X);\n const swing1 = cdata.axes.get(PhysicsConstraintAxis.ANGULAR_Y);\n const swing2 = cdata.axes.get(PhysicsConstraintAxis.ANGULAR_Z);\n const states = [twist, swing1, swing2];\n const velocity = (state?: IAxisState) => (state?.motor === PhysicsConstraintMotorType.VELOCITY ? state.target : 0);\n const hasVelocity = states.some((state) => state?.motor === PhysicsConstraintMotorType.VELOCITY);\n const hasPosition = states.some((state) => state?.motor === PhysicsConstraintMotorType.POSITION);\n const maxTorque = Math.max(...states.map((state) => (state?.motor === PhysicsConstraintMotorType.VELOCITY ? state.maxForce : 0)));\n b3._bx_Joint_SetSphericalMotor(joint, hasVelocity ? 1 : 0, velocity(swing1), velocity(swing2), velocity(twist), maxTorque);\n const target = velocity(swing1) !== 0 || velocity(swing2) !== 0 || velocity(twist) !== 0;\n if (hasVelocity && target) {\n // the world space target has to follow body A as it turns\n this._motorJoints.add(joint);\n } else {\n this._motorJoints.delete(joint);\n }\n b3._bx_Joint_EnableSpring(joint, hasPosition ? 1 : 0);\n if (hasPosition) {\n const position = (state?: IAxisState) => (state?.motor === PhysicsConstraintMotorType.POSITION ? state.target : 0);\n const rotation = this._tmpQuat[0];\n Quaternion.RotationYawPitchRollToRef(0, 0, position(twist), rotation);\n const swing = this._tmpQuat[1];\n Quaternion.RotationYawPitchRollToRef(position(swing2), position(swing1), 0, swing);\n rotation.multiplyInPlace(swing);\n b3._bx_Joint_SetSpring(joint, 5, 1);\n b3._bx_Joint_SetSphericalTarget(joint, rotation.x, rotation.y, rotation.z, rotation.w);\n }\n }\n\n private _applyMotor(joint: number, state: IAxisState): void {\n const b3 = this._b3;\n switch (state.motor) {\n case PhysicsConstraintMotorType.VELOCITY:\n b3._bx_Joint_EnableSpring(joint, 0);\n b3._bx_Joint_EnableMotor(joint, 1);\n b3._bx_Joint_SetMotorSpeed(joint, state.target);\n b3._bx_Joint_SetMaxMotorForce(joint, state.maxForce);\n break;\n case PhysicsConstraintMotorType.POSITION:\n b3._bx_Joint_EnableMotor(joint, 0);\n b3._bx_Joint_EnableSpring(joint, 1);\n b3._bx_Joint_SetSpring(joint, 5, 1);\n b3._bx_Joint_SetTarget(joint, state.target);\n break;\n default:\n b3._bx_Joint_EnableMotor(joint, 0);\n b3._bx_Joint_EnableSpring(joint, 0);\n break;\n }\n }\n\n /** Applies a SIX_DOF plan's limits, springs and motors to one of its Box3D joints. */\n private _applySixDofPlan(cdata: Box3DConstraintData, joint: number, bodyA: Box3DBodyData, bodyB: Box3DBodyData): void {\n const b3 = this._b3;\n const plan = cdata.plan!;\n switch (plan.jointType) {\n case Box3DJointType.SPHERICAL:\n if (plan.coneAngle >= 0) {\n b3._bx_Joint_SetLimits(joint, -plan.coneAngle, plan.coneAngle);\n }\n b3._bx_Joint_EnableLimit(joint, plan.coneAngle >= 0 ? 1 : 0);\n b3._bx_Joint_SetTwistLimits(joint, plan.twist ? 1 : 0, plan.twist ? plan.twist[0] : 0, plan.twist ? plan.twist[1] : 0);\n break;\n case Box3DJointType.REVOLUTE:\n case Box3DJointType.PRISMATIC:\n if (plan.limit) {\n b3._bx_Joint_SetLimits(joint, plan.limit[0], plan.limit[1]);\n }\n b3._bx_Joint_EnableLimit(joint, plan.limit ? 1 : 0);\n break;\n case Box3DJointType.DISTANCE:\n if (plan.spring) {\n const spring = this._springToHertz(plan.stiffness, plan.damping, false, bodyA, bodyB);\n b3._bx_Joint_EnableLimit(joint, 0);\n b3._bx_Joint_EnableSpring(joint, 1);\n b3._bx_Joint_SetSpring(joint, spring.hertz, spring.dampingRatio);\n b3._bx_Joint_SetTarget(joint, cdata.length);\n } else {\n // an enabled spring with 0 hertz leaves the length free between the limits (a rope); Box3D keeps\n // equal limits rigid\n b3._bx_Joint_SetLimits(joint, plan.limit![0], plan.limit![1]);\n b3._bx_Joint_EnableLimit(joint, 1);\n b3._bx_Joint_EnableSpring(joint, 1);\n b3._bx_Joint_SetSpring(joint, 0, 0);\n }\n break;\n default:\n break;\n }\n if (plan.stiffness > 0 && !plan.spring) {\n this._warnOnce(\n \"sixdof-softness\",\n \"SIX_DOF: limit stiffness and damping are approximated with Box3D's per joint constraint softness, which applies to every axis of the joint.\"\n );\n const soft = this._springToHertz(plan.stiffness, plan.damping, plan.angularStiffness, bodyA, bodyB);\n b3._bx_Joint_SetConstraintTuning(joint, soft.hertz, soft.dampingRatio);\n }\n if (plan.jointType === Box3DJointType.SPHERICAL) {\n this._applySphericalMotor(cdata, joint);\n } else if (plan.primaryAxis !== null && plan.jointType !== Box3DJointType.DISTANCE) {\n const state = cdata.axes.get(plan.primaryAxis);\n if (state) {\n this._applyMotor(joint, state);\n }\n }\n }\n\n private _setAxis(constraint: PhysicsConstraint, axis: PhysicsConstraintAxis, apply: (state: IAxisState) => void): void {\n const cdata = constraint._pluginData as Box3DConstraintData;\n if (!cdata) {\n return;\n }\n const state = this._axisState(cdata, axis);\n const previousMotor = { motor: state.motor, target: state.target, maxForce: state.maxForce };\n apply(state);\n if (cdata.plan) {\n // SIX_DOF: every axis shapes the plan. A different Box3D joint type or frame needs new joints.\n const plan = this._planSixDof(cdata);\n const rebuild = plan.jointType !== cdata.plan.jointType || String(plan.basis) !== String(cdata.plan.basis);\n cdata.plan = plan;\n cdata.jointType = plan.jointType;\n const motorChanged = previousMotor.motor !== state.motor || previousMotor.target !== state.target || previousMotor.maxForce !== state.maxForce;\n if (motorChanged && state.motor !== PhysicsConstraintMotorType.NONE && !this._isPrimaryAxis(cdata, axis)) {\n this._warnOnce(`axis-motor-${axis}`, `SIX_DOF: a motor on axis ${axis} has no effect with the Box3D joint this constraint maps to.`);\n }\n const first = cdata.pairs[0];\n if (first) {\n // the rest length of a distance joint follows its limits, whether or not the joint is rebuilt\n this._updateJointLength(cdata, constraint.options.maxDistance, first.parentData, first.childData);\n }\n if (rebuild) {\n if (first) {\n this._buildFrames(cdata, constraint, first.parentData, first.childData);\n }\n this._recreateJoints(cdata);\n return;\n }\n } else if (!this._isPrimaryAxis(cdata, axis)) {\n this._warnOnce(`axis-${cdata.type}-${axis}`, `axis ${axis} is not configurable on constraint type ${cdata.type} with Box3D; the value is stored but has no effect.`);\n return;\n }\n for (let i = 0; i < cdata.joints.length; i++) {\n if (cdata.joints[i]) {\n this._applyAxisState(cdata, cdata.joints[i], cdata.pairs[i].parentData, cdata.pairs[i].childData);\n }\n }\n }\n\n public setAxisFriction(constraint: PhysicsConstraint, axis: PhysicsConstraintAxis, friction: number): void {\n const cdata = constraint._pluginData as Box3DConstraintData;\n if (cdata) {\n this._axisState(cdata, axis).friction = friction;\n }\n }\n\n public getAxisFriction(constraint: PhysicsConstraint, axis: PhysicsConstraintAxis): Nullable<number> {\n return (constraint._pluginData as Box3DConstraintData)?.axes.get(axis)?.friction ?? null;\n }\n\n public setAxisMode(constraint: PhysicsConstraint, axis: PhysicsConstraintAxis, limitMode: PhysicsConstraintAxisLimitMode): void {\n this._setAxis(constraint, axis, (state) => (state.mode = limitMode));\n }\n\n public getAxisMode(constraint: PhysicsConstraint, axis: PhysicsConstraintAxis): Nullable<PhysicsConstraintAxisLimitMode> {\n return (constraint._pluginData as Box3DConstraintData)?.axes.get(axis)?.mode ?? null;\n }\n\n public setAxisMinLimit(constraint: PhysicsConstraint, axis: PhysicsConstraintAxis, minLimit: number): void {\n this._setAxis(constraint, axis, (state) => {\n state.min = minLimit;\n if (state.mode === PhysicsConstraintAxisLimitMode.FREE) {\n state.mode = PhysicsConstraintAxisLimitMode.LIMITED;\n }\n });\n }\n\n public getAxisMinLimit(constraint: PhysicsConstraint, axis: PhysicsConstraintAxis): Nullable<number> {\n return (constraint._pluginData as Box3DConstraintData)?.axes.get(axis)?.min ?? null;\n }\n\n public setAxisMaxLimit(constraint: PhysicsConstraint, axis: PhysicsConstraintAxis, limit: number): void {\n this._setAxis(constraint, axis, (state) => {\n state.max = limit;\n if (state.mode === PhysicsConstraintAxisLimitMode.FREE) {\n state.mode = PhysicsConstraintAxisLimitMode.LIMITED;\n }\n });\n }\n\n public getAxisMaxLimit(constraint: PhysicsConstraint, axis: PhysicsConstraintAxis): Nullable<number> {\n return (constraint._pluginData as Box3DConstraintData)?.axes.get(axis)?.max ?? null;\n }\n\n public setAxisMotorType(constraint: PhysicsConstraint, axis: PhysicsConstraintAxis, motorType: PhysicsConstraintMotorType): void {\n this._setAxis(constraint, axis, (state) => (state.motor = motorType));\n }\n\n public getAxisMotorType(constraint: PhysicsConstraint, axis: PhysicsConstraintAxis): Nullable<PhysicsConstraintMotorType> {\n return (constraint._pluginData as Box3DConstraintData)?.axes.get(axis)?.motor ?? null;\n }\n\n public setAxisMotorTarget(constraint: PhysicsConstraint, axis: PhysicsConstraintAxis, target: number): void {\n this._setAxis(constraint, axis, (state) => (state.target = target));\n }\n\n public getAxisMotorTarget(constraint: PhysicsConstraint, axis: PhysicsConstraintAxis): Nullable<number> {\n return (constraint._pluginData as Box3DConstraintData)?.axes.get(axis)?.target ?? null;\n }\n\n public setAxisMotorMaxForce(constraint: PhysicsConstraint, axis: PhysicsConstraintAxis, maxForce: number): void {\n this._setAxis(constraint, axis, (state) => (state.maxForce = maxForce));\n }\n\n public getAxisMotorMaxForce(constraint: PhysicsConstraint, axis: PhysicsConstraintAxis): Nullable<number> {\n return (constraint._pluginData as Box3DConstraintData)?.axes.get(axis)?.maxForce ?? null;\n }\n\n public disposeConstraint(constraint: PhysicsConstraint): void {\n const cdata = constraint._pluginData as Box3DConstraintData;\n if (!cdata) {\n return;\n }\n for (const joint of cdata.joints) {\n if (joint) {\n this._destroyJoint(joint);\n }\n }\n cdata.joints.length = 0;\n cdata.pairs.length = 0;\n }\n\n public getBodiesUsingConstraint(constraint: PhysicsConstraint): ConstrainedBodyPair[] {\n const cdata = constraint._pluginData as Box3DConstraintData;\n if (!cdata) {\n return [];\n }\n return cdata.pairs.map((p) => ({ parentBody: p.parent, parentBodyIndex: p.parentIndex, childBody: p.child, childBodyIndex: p.childIndex }));\n }\n\n public addConstraint(body: PhysicsBody, childBody: PhysicsBody, constraint: PhysicsConstraint, instanceIndex?: number, childInstanceIndex?: number): void {\n this.initConstraint(constraint, body, childBody, instanceIndex, childInstanceIndex);\n }\n\n // ----------------------------------------------------------------------------------------\n // Box3D specific extras\n // ----------------------------------------------------------------------------------------\n\n /**\n * Applies a radial impulse to every shape within the radius, like a grenade.\n * @param position world position of the explosion\n * @param radius radius of the explosion\n * @param impulsePerArea impulse per surface area of the affected shapes\n * @param falloff distance beyond the radius over which the impulse fades to zero\n */\n public explode(position: Vector3, radius: number, impulsePerArea: number, falloff = 0): void {\n this._b3._bx_World_Explode(this._worldSlot, position.x, position.y, position.z, radius, falloff, impulsePerArea);\n }\n\n /**\n * Box2D style collision group. Shapes sharing a negative group never collide with each other,\n * shapes sharing a positive group always collide. Zero means no group.\n * @param shape the shape\n * @param groupIndex the group index\n */\n public setShapeFilterGroup(shape: PhysicsShape, groupIndex: number): void {\n const data = shape._pluginData as Box3DShapeData;\n this._b3._bx_ShapeDesc_SetGroup(data.slot, groupIndex | 0);\n this._syncShapeUsers(data, Box3DShapeSync.FILTER);\n }\n\n /**\n * Rolling resistance for spheres and capsules (Babylon materials have no equivalent).\n * @param shape the shape\n * @param value resistance, typically in [0, 1]\n */\n public setShapeRollingResistance(shape: PhysicsShape, value: number): void {\n const data = shape._pluginData as Box3DShapeData;\n this._b3._bx_ShapeDesc_SetRollingResistance(data.slot, value);\n this._syncShapeUsers(data, Box3DShapeSync.MATERIAL);\n }\n\n /**\n * Lets a body spin faster than the default angular speed cap (wheels).\n * @param body the body\n * @param allow true to allow fast rotation\n * @param instanceIndex optional thin instance index\n */\n public setAllowFastRotation(body: PhysicsBody, allow: boolean, instanceIndex?: number): void {\n this._applyToBodyOrInstances(body, (data) => this._b3._bx_Body_AllowFastRotation(data.slot, allow ? 1 : 0), instanceIndex);\n }\n\n /**\n * Creates a Box3D wheel joint between a chassis and a wheel body.\n * @param chassis the chassis body\n * @param wheel the wheel body\n * @param options wheel joint options\n * @returns a handle used to drive and steer the wheel\n */\n public createWheelJoint(chassis: PhysicsBody, wheel: PhysicsBody, options: IBox3DWheelJointOptions): Box3DWheelJoint {\n const s = this._scratch();\n const axisA = (options.axisA ?? Vector3.UpReadOnly).normalizeToNew();\n const axleA = (options.axleA ?? Vector3.Forward()).normalizeToNew();\n // suspension travels along frame A x, the wheel spins about frame z\n axleA.subtractInPlace(axisA.scale(Vector3.Dot(axisA, axleA))).normalize();\n this._frameToBuffer(s, 0, options.pivotA, axisA, Vector3.Cross(axleA, axisA), axleA);\n // frame B must coincide with frame A in world space at creation, compute it from the current poses\n const pivotB = options.pivotB ?? Vector3.ZeroReadOnly;\n s[7] = pivotB.x;\n s[8] = pivotB.y;\n s[9] = pivotB.z;\n const chassisData = this._getPluginReference(chassis);\n const wheelData = this._getPluginReference(wheel);\n this._b3._bx_ComputeAlignedFrameB(chassisData.slot, wheelData.slot);\n const susp = options.suspensionLimits ?? [-0.2, 0.2];\n const steer = options.steeringLimits ?? [-Math.PI / 4, Math.PI / 4];\n s.set(\n [\n 1,\n options.suspensionHertz ?? 4,\n options.suspensionDampingRatio ?? 0.7,\n 1,\n susp[0],\n susp[1],\n options.enableSpinMotor ? 1 : 0,\n options.maxSpinTorque ?? 5,\n 0,\n options.enableSteering ? 1 : 0,\n options.steeringHertz ?? 10,\n options.steeringDampingRatio ?? 0.7,\n 0,\n options.maxSteeringTorque ?? 5,\n 1,\n steer[0],\n steer[1],\n ],\n 14\n );\n const slot = this._b3._bx_CreateJoint(this._worldSlot, Box3DJointType.WHEEL, chassisData.slot, wheelData.slot, 0, 0);\n if (!slot) {\n throw new Error(\"Box3DPlugin: wheel joint creation failed\");\n }\n return new Box3DWheelJoint(this, slot);\n }\n\n /**\n * Creates a Box3D parallel joint: a spring that keeps a local axis of bodyB parallel to an axis\n * of bodyA, for example to keep a vehicle upright without locking its motion.\n * @param bodyA first body (often a static body)\n * @param bodyB body to align\n * @param axisA axis in bodyA local space\n * @param axisB axis in bodyB local space\n * @param hertz spring stiffness\n * @param dampingRatio spring damping\n * @param maxTorque maximum spring torque\n * @returns a joint slot that can be passed to disposeExtraJoint\n */\n public createParallelJoint(bodyA: PhysicsBody, bodyB: PhysicsBody, axisA: Vector3, axisB: Vector3, hertz = 1, dampingRatio = 1, maxTorque = 3.4e38): number {\n const s = this._scratch();\n const a = axisA.normalizeToNew();\n const pa = a.getNormalToRef(new Vector3());\n this._frameToBuffer(s, 0, Vector3.ZeroReadOnly, pa, Vector3.Cross(a, pa), a);\n const b = axisB.normalizeToNew();\n const pb = b.getNormalToRef(new Vector3());\n this._frameToBuffer(s, 7, Vector3.ZeroReadOnly, pb, Vector3.Cross(b, pb), b);\n s.set([hertz, dampingRatio, maxTorque], 14);\n return this._b3._bx_CreateJoint(this._worldSlot, Box3DJointType.PARALLEL, this._getPluginReference(bodyA).slot, this._getPluginReference(bodyB).slot, 1, 0);\n }\n\n /**\n * Destroys a joint created by createParallelJoint.\n * @param slot the joint slot\n */\n public disposeExtraJoint(slot: number): void {\n this._destroyExtraJoint(slot);\n }\n\n /**\n * @internal\n */\n public _destroyExtraJoint(slot: number): void {\n if (slot) {\n this._destroyJoint(slot);\n }\n }\n\n /**\n * @internal\n */\n public _wheelCall(fn: string, slot: number, ...args: number[]): void {\n if (slot) {\n this._b3[fn](slot, ...args);\n }\n }\n\n // ----------------------------------------------------------------------------------------\n // queries\n // ----------------------------------------------------------------------------------------\n\n public raycast(from: Vector3, to: Vector3, result: PhysicsRaycastResult | Array<PhysicsRaycastResult>, query?: IRaycastQuery): void {\n const results = Array.isArray(result) ? result : [result];\n for (const r of results) {\n r.reset(from, to);\n }\n const membership = (query?.membership ?? ~0) >>> 0;\n const collideWith = (query?.collideWith ?? ~0) >>> 0;\n const ignore = query?.ignoreBody ? ((query.ignoreBody._pluginData as Box3DBodyData)?.slot ?? 0) : 0;\n const closestOnly = results.length === 1;\n const count = this._b3._bx_World_CastRay(\n this._worldSlot,\n from.x,\n from.y,\n from.z,\n to.x - from.x,\n to.y - from.y,\n to.z - from.z,\n membership,\n collideWith,\n ignore,\n query?.shouldHitTriggers ? 1 : 0,\n closestOnly ? 1 : 0\n );\n if (count <= 0) {\n return;\n }\n const buffer = new Float32Array(this._b3.HEAPF32.buffer, this._b3._bx_RayHitsPtr(), count * RAY_STRIDE);\n const hits: number[] = [];\n for (let i = 0; i < count; i++) {\n hits.push(i);\n }\n hits.sort((a, b) => buffer[a * RAY_STRIDE + 6] - buffer[b * RAY_STRIDE + 6]);\n if (!results.length) {\n for (let i = 0; i < count; i++) {\n const r = new PhysicsRaycastResult();\n r.reset(from, to);\n results.push(r);\n }\n }\n const n = Math.min(count, results.length);\n for (let i = 0; i < n; i++) {\n const o = hits[i] * RAY_STRIDE;\n const r = results[i];\n const bodyRef = this._bodies[buffer[o + 7]];\n r.body = bodyRef?.body;\n r.bodyIndex = bodyRef?.index;\n r.shape = bodyRef?.body.shape ?? undefined;\n r.setHitData({ x: buffer[o + 3], y: buffer[o + 4], z: buffer[o + 5] }, { x: buffer[o], y: buffer[o + 1], z: buffer[o + 2] }, buffer[o + 9]);\n r.calculateHitDistance();\n }\n }\n\n // ----------------------------------------------------------------------------------------\n // events\n // ----------------------------------------------------------------------------------------\n\n /**\n * Copies `count` event records out of wasm memory and resolves their two body slots (at `slotOffset`) to the plugin's\n * body references. Observers run user code that can grow the wasm memory, which detaches every HEAPF32 view (creating\n * bodies or shapes, casting rays), or dispose bodies and hand their slots to new ones, so nothing is read from wasm\n * memory or the slot table once the first observer has been called.\n */\n private _readEvents(pointer: number, count: number, stride: number, slotOffset: number) {\n const records = new Float32Array(this._b3.HEAPF32.buffer, pointer, count * stride).slice();\n const refs: Array<{ body: PhysicsBody; index: number; data: Box3DBodyData } | undefined> = new Array(count * 2);\n for (let i = 0; i < count; i++) {\n refs[i * 2] = this._bodies[records[i * stride + slotOffset]];\n refs[i * 2 + 1] = this._bodies[records[i * stride + slotOffset + 1]];\n }\n return { records, refs };\n }\n\n private _notifyCollisions(): void {\n const count = this._b3._bx_World_GetContactEvents(this._worldSlot);\n if (!count) {\n return;\n }\n const { records: buffer, refs } = this._readEvents(this._b3._bx_ContactEventsPtr(), count, CONTACT_STRIDE, 3);\n for (let i = 0; i < count; i++) {\n const o = i * CONTACT_STRIDE;\n const kind = buffer[o];\n const refA = refs[i * 2];\n const refB = refs[i * 2 + 1];\n // a body disposed by an earlier observer has slot 0, its remaining events are dropped\n if (!refA || !refB || !refA.data.slot || !refB.data.slot) {\n continue;\n }\n // like Havok, an event is reported when either body asked for that event type\n const bit = kind === 0 ? Box3DEventBits.COLLISION_STARTED : kind === 1 ? Box3DEventBits.COLLISION_FINISHED : Box3DEventBits.COLLISION_CONTINUED;\n if (((refA.data.eventMask | refB.data.eventMask) & bit) === 0) {\n continue;\n }\n if (kind === 1) {\n const ended: IBasePhysicsCollisionEvent = {\n collider: refA.body,\n colliderIndex: refA.index,\n collidedAgainst: refB.body,\n collidedAgainstIndex: refB.index,\n type: PhysicsEventType.COLLISION_FINISHED,\n };\n this.onCollisionEndedObservable.notifyObservers(ended);\n this._bodyCollisionEndedObservable.get(refA.data.slot)?.notifyObservers(ended);\n const endedB = this._bodyCollisionEndedObservable.get(refB.data.slot);\n if (endedB) {\n endedB.notifyObservers({ ...ended, collider: refB.body, colliderIndex: refB.index, collidedAgainst: refA.body, collidedAgainstIndex: refA.index });\n }\n continue;\n }\n // begin events carry the manifold point, normal and normal impulse, hit events the approach speed\n const type = kind === 0 ? PhysicsEventType.COLLISION_STARTED : PhysicsEventType.COLLISION_CONTINUED;\n const point = new Vector3(buffer[o + 5], buffer[o + 6], buffer[o + 7]);\n const normal = new Vector3(buffer[o + 8], buffer[o + 9], buffer[o + 10]);\n const info: IPhysicsCollisionEvent = {\n collider: refA.body,\n colliderIndex: refA.index,\n collidedAgainst: refB.body,\n collidedAgainstIndex: refB.index,\n type,\n point,\n normal,\n distance: 0,\n impulse: buffer[o + 11],\n };\n this.onCollisionObservable.notifyObservers(info);\n if (this._bodyCollisionObservable.size) {\n this._bodyCollisionObservable.get(refA.data.slot)?.notifyObservers(info);\n const obsB = this._bodyCollisionObservable.get(refB.data.slot);\n if (obsB) {\n obsB.notifyObservers({\n ...info,\n collider: refB.body,\n colliderIndex: refB.index,\n collidedAgainst: refA.body,\n collidedAgainstIndex: refA.index,\n normal: normal ? normal.negate() : null,\n });\n }\n }\n }\n }\n\n private _notifyTriggers(): void {\n const count = this._b3._bx_World_GetSensorEvents(this._worldSlot);\n if (!count || !this.onTriggerCollisionObservable.hasObservers()) {\n return;\n }\n const { records: buffer, refs } = this._readEvents(this._b3._bx_SensorEventsPtr(), count, SENSOR_STRIDE, 3);\n for (let i = 0; i < count; i++) {\n const o = i * SENSOR_STRIDE;\n const refA = refs[i * 2];\n const refB = refs[i * 2 + 1];\n if (!refA || !refB || !refA.data.slot || !refB.data.slot) {\n continue;\n }\n this.onTriggerCollisionObservable.notifyObservers({\n collider: refA.body,\n colliderIndex: refA.index,\n collidedAgainst: refB.body,\n collidedAgainstIndex: refB.index,\n type: buffer[o] === 0 ? PhysicsEventType.TRIGGER_ENTERED : PhysicsEventType.TRIGGER_EXITED,\n });\n }\n }\n\n public dispose(): void {\n this._motorJoints.clear();\n this.onCollisionObservable.clear();\n this.onCollisionEndedObservable.clear();\n this.onTriggerCollisionObservable.clear();\n this._bodyCollisionObservable.clear();\n this._bodyCollisionEndedObservable.clear();\n for (const shape of this._shapes) {\n if (shape) {\n this._b3._bx_ShapeDesc_Destroy(shape.slot);\n }\n }\n this._shapes.length = 0;\n this._bodies.length = 0;\n if (this._worldSlot) {\n this._b3._bx_DestroyWorld(this._worldSlot);\n this._worldSlot = 0;\n }\n }\n}\n", "// Picks a Box3D module: the plain one, or the threaded one when the page can run it.\n//\n// The package ships two builds of the same wasm. The default is single threaded and runs anywhere. The threaded build\n// lets box3d spread a world step over its own worker threads, which is several times faster on a heavy scene, but it\n// needs SharedArrayBuffer, and browsers only hand that out on a cross origin isolated page:\n//\n// Cross-Origin-Opener-Policy: same-origin\n// Cross-Origin-Embedder-Policy: require-corp\n//\n// The threaded module is imported dynamically, so a page that never asks for threads never downloads it.\n\nimport type { Box3DModule, Box3DModuleOptions } from \"babylon-box3d/wasm\";\n\n/** Options for LoadBox3D: the emscripten module options plus which build to load. */\nexport interface ILoadBox3DOptions extends Box3DModuleOptions {\n /**\n * Which build to load. false (the default) is the single threaded one. true is the threaded one, and fails\n * loudly if the page is not cross origin isolated. \"auto\" uses the threaded build where it can and falls back\n * to the single threaded one everywhere else.\n */\n threads?: boolean | \"auto\";\n}\n\n/**\n * Whether the threaded Box3D build can run here: the page has to be cross origin isolated, which is what gives it\n * SharedArrayBuffer. Node and bundler test environments have SharedArrayBuffer without the flag.\n * @returns true when LoadBox3D({ threads: true }) will work\n */\nexport function CanUseBox3DThreads(): boolean {\n if (typeof SharedArrayBuffer === \"undefined\") {\n return false;\n }\n const isolated = (globalThis as { crossOriginIsolated?: boolean }).crossOriginIsolated;\n return isolated === undefined || isolated;\n}\n\n/**\n * Loads the Box3D WebAssembly module, optionally the threaded build.\n * The result goes to the plugin as it always does; ask the plugin for workers to put them to use:\n * ```ts\n * const box3d = await LoadBox3D({ threads: \"auto\" });\n * scene.enablePhysics(gravity, new Box3DPlugin(true, box3d, { workerCount: \"auto\" }));\n * ```\n * @param options which build to load, plus the emscripten options (locateFile and friends)\n * @returns the resolved module\n */\nexport async function LoadBox3D(options: ILoadBox3DOptions = {}): Promise<Box3DModule> {\n const { threads = false, ...moduleOptions } = options;\n const wantsThreads = threads === \"auto\" ? CanUseBox3DThreads() : threads;\n if (wantsThreads) {\n if (threads === true && !CanUseBox3DThreads()) {\n throw new Error(\n \"babylon-box3d: the threaded build needs SharedArrayBuffer, which this page does not have. Serve it with the \" +\n \"Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Embedder-Policy: require-corp headers, or use \" +\n 'LoadBox3D({ threads: \"auto\" }) to fall back to the single threaded build.'\n );\n }\n const threaded = await import(\"babylon-box3d/wasm/threads\");\n return threaded.default(moduleOptions);\n }\n const plain = await import(\"babylon-box3d/wasm\");\n return plain.default(moduleOptions);\n}\n"],
|
|
4
|
+
"sourcesContent": ["if (typeof BABYLON === \"undefined\") { throw new Error(\"babylon.box3d.js needs babylon.js loaded first\"); } module.exports = BABYLON;", "if (typeof BABYLON === \"undefined\") { throw new Error(\"babylon.box3d.js needs babylon.js loaded first\"); } module.exports = BABYLON;", "if (typeof BABYLON === \"undefined\") { throw new Error(\"babylon.box3d.js needs babylon.js loaded first\"); } module.exports = BABYLON;", "if (typeof BABYLON === \"undefined\") { throw new Error(\"babylon.box3d.js needs babylon.js loaded first\"); } module.exports = BABYLON;", "if (typeof BABYLON === \"undefined\") { throw new Error(\"babylon.box3d.js needs babylon.js loaded first\"); } module.exports = BABYLON;", "if (typeof BABYLON === \"undefined\") { throw new Error(\"babylon.box3d.js needs babylon.js loaded first\"); } module.exports = BABYLON;", "if (typeof BABYLON === \"undefined\") { throw new Error(\"babylon.box3d.js needs babylon.js loaded first\"); } module.exports = BABYLON;", "if (typeof BABYLON === \"undefined\") { throw new Error(\"babylon.box3d.js needs babylon.js loaded first\"); } module.exports = BABYLON;", "if (typeof BABYLON === \"undefined\") { throw new Error(\"babylon.box3d.js needs babylon.js loaded first\"); } module.exports = BABYLON;", "if (typeof Box3D === \"undefined\") { throw new Error(\"babylon.box3d.js needs lib/umd/box3d.umd.js loaded first\"); } export default Box3D;", "export default function () { throw new Error(\"babylon.box3d.js is the script tag build and has no threaded module. Install the package and import it, or use LoadBox3D({ threads: \\\"auto\\\" }).\"); }", "// babylon-box3d: Box3D physics for Babylon.js.\n//\n// import { Box3D, Box3DPlugin } from \"babylon-box3d\";\n// const box3d = await Box3D();\n// scene.enablePhysics(new Vector3(0, -9.81, 0), new Box3DPlugin(true, box3d));\n\n// the .js extension keeps the emitted dist/index.js importable by plain node ESM, not just by bundlers\nexport { BOX3D_HEIGHT_FIELD_HOLE, Box3DPlugin, Box3DWheelJoint, type IBox3DPluginOptions, type IBox3DWheelJointOptions } from \"./box3dPlugin.js\";\nexport { default as Box3D } from \"babylon-box3d/wasm\";\nexport type { Box3DModule, Box3DModuleOptions, Box3DExports, Box3DHeap } from \"babylon-box3d/wasm\";\nexport { CanUseBox3DThreads, LoadBox3D, type ILoadBox3DOptions } from \"./loadBox3D.js\";\n", "import { Matrix, Quaternion, TmpVectors, Vector3 } from \"@babylonjs/core/Maths/math.vector.js\";\nimport {\n type IPhysicsEnginePluginV2,\n type PhysicsMassProperties,\n type PhysicsShapeParameters,\n type ConstrainedBodyPair,\n type IPhysicsCollisionEvent,\n type IBasePhysicsCollisionEvent,\n PhysicsShapeType,\n PhysicsConstraintType,\n PhysicsMotionType,\n PhysicsConstraintAxis,\n PhysicsConstraintAxisLimitMode,\n PhysicsConstraintMotorType,\n PhysicsEventType,\n PhysicsPrestepType,\n PhysicsActivationControl,\n} from \"@babylonjs/core/Physics/v2/IPhysicsEnginePlugin.js\";\nimport { PhysicsRaycastResult } from \"@babylonjs/core/Physics/physicsRaycastResult.js\";\nimport { type IRaycastQuery } from \"@babylonjs/core/Physics/physicsRaycastResult.js\";\nimport { Logger } from \"@babylonjs/core/Misc/logger.js\";\nimport { type PhysicsBody } from \"@babylonjs/core/Physics/v2/physicsBody.js\";\nimport { type PhysicsConstraint, type Physics6DoFConstraint, type Physics6DoFLimit } from \"@babylonjs/core/Physics/v2/physicsConstraint.js\";\nimport { type PhysicsMaterial } from \"@babylonjs/core/Physics/v2/physicsMaterial.js\";\nimport { type PhysicsShape } from \"@babylonjs/core/Physics/v2/physicsShape.js\";\nimport { BoundingBox } from \"@babylonjs/core/Culling/boundingBox.js\";\nimport { type TransformNode } from \"@babylonjs/core/Meshes/transformNode.js\";\nimport { Mesh } from \"@babylonjs/core/Meshes/mesh.js\";\nimport { InstancedMesh } from \"@babylonjs/core/Meshes/instancedMesh.js\";\nimport { VertexBuffer } from \"@babylonjs/core/Buffers/buffer.js\";\nimport { Observable } from \"@babylonjs/core/Misc/observable.js\";\nimport { type Nullable, type FloatArray } from \"@babylonjs/core/types.js\";\n\n/** The cell material that cuts a hole in a height field: nothing collides with the cell and rays pass through it. */\nexport const BOX3D_HEIGHT_FIELD_HOLE = 255;\n\ndeclare module \"@babylonjs/core/Physics/v2/IPhysicsEnginePlugin.js\" {\n interface PhysicsShapeParameters {\n /**\n * Box3D height fields only: a material index for every cell, `(numHeightFieldSamplesX - 1) *\n * (numHeightFieldSamplesZ - 1)` of them, rows in the same order as `heightFieldData`. A cell of\n * `BOX3D_HEIGHT_FIELD_HOLE` (255) is a hole. The index is also what `userMaterialId` would carry in Box3D, so\n * keep it below 255 for solid ground.\n */\n heightFieldMaterials?: ArrayLike<number>;\n /**\n * `CONVEX_HULL` and `MESH` without a `mesh`: the points as x, y, z triplets in the body's space, for code that\n * builds shapes with no meshes to read them from, like a headless simulation.\n */\n positions?: ArrayLike<number>;\n /**\n * `MESH` with `positions`: three indices into the points per triangle, wound so the plain cross product of\n * (b - a) and (c - a) points out of the surface. That is Box3D's own winding, and it is used as given: no\n * flip for a left handed scene, which only applies to winding read from a Babylon mesh.\n */\n positionIndices?: ArrayLike<number>;\n }\n}\n\n/**\n * Per body plugin data. One instance per Box3D body (thin instances get one each).\n */\nclass Box3DBodyData {\n public constructor(\n /** slot handle inside the WASM shim */\n public slot: number\n ) {}\n public userMassProps: PhysicsMassProperties = {};\n /** Box3D angular motion locks currently set on the body, bits x, y, z */\n public angularLocks = 0;\n /** Havok's EventType bits: 1 collision started, 2 collision continued, 4 collision finished */\n public eventMask = 0;\n public motionType = PhysicsMotionType.STATIC;\n /** Babylon activation control; ALWAYS_INACTIVE parks the body as a static Box3D body, see setActivationControl */\n public activation = PhysicsActivationControl.SIMULATION_CONTROLLED;\n}\n\n/**\n * Per shape plugin data. A Babylon shape is a description that gets instantiated on each body it is set on.\n */\nclass Box3DShapeData {\n public constructor(\n public slot: number,\n public type: PhysicsShapeType\n ) {}\n public material: PhysicsMaterial = {};\n /** bodies currently instantiating this shape, refreshed when the description changes */\n public users = new Set<Box3DBodyData>();\n /** for containers: child shapes, so changes propagate to users */\n public children: Box3DShapeData[] = [];\n public parents = new Set<Box3DShapeData>();\n}\n\n/** Axis state kept on the JS side because box3d has no generic axis API. */\ninterface IAxisState {\n mode: PhysicsConstraintAxisLimitMode;\n min: number;\n max: number;\n motor: PhysicsConstraintMotorType;\n target: number;\n maxForce: number;\n friction: number;\n /** Physics6DoFLimit.stiffness: spring constant of a soft limit (N/m, or N*m/rad for angular axes) */\n stiffness: number;\n /** Physics6DoFLimit.damping */\n damping: number;\n}\n\n/**\n * How a SIX_DOF constraint is realised with Box3D's fixed joint types. Recomputed from the axis table whenever an axis\n * changes, and reused as is when a disabled constraint is enabled again.\n */\ninterface ISixDofPlan {\n jointType: Box3DJointType;\n /** Box3D frame x, y, z as indices into the constraint basis [axis, perpAxis, axis x perpAxis], null for identity frames */\n basis: Nullable<[number, number, number]>;\n /** the Babylon axis that follows the single degree of freedom of a revolute, prismatic or distance joint */\n primaryAxis: Nullable<PhysicsConstraintAxis>;\n /** spherical cone angle, negative when the swing is free */\n coneAngle: number;\n /** spherical twist limits (about axis), null when free */\n twist: Nullable<[number, number]>;\n /** revolute angle, prismatic translation or distance length limits, null when free */\n limit: Nullable<[number, number]>;\n /** distance joints: a real spring at rest length limit[0] instead of a rope between the limits */\n spring: boolean;\n /** stiffest soft limit, mapped to Box3D spring or constraint softness per body pair */\n stiffness: number;\n damping: number;\n angularStiffness: boolean;\n}\n\nclass Box3DConstraintData {\n public joints: number[] = [];\n public pairs: Array<{ parent: PhysicsBody; parentIndex: number; child: PhysicsBody; childIndex: number; parentData: Box3DBodyData; childData: Box3DBodyData }> = [];\n public type: PhysicsConstraintType = PhysicsConstraintType.LOCK;\n public jointType = 0;\n public enabled = true;\n public collisions = false;\n public frames = new Float32Array(14);\n public length = 0;\n public axes = new Map<PhysicsConstraintAxis, IAxisState>();\n /** SIX_DOF only */\n public plan: Nullable<ISixDofPlan> = null;\n}\n\n// shim joint types\nconst enum Box3DJointType {\n WELD = 0,\n SPHERICAL = 1,\n REVOLUTE = 2,\n PRISMATIC = 3,\n DISTANCE = 4,\n FILTER = 5,\n WHEEL = 6,\n PARALLEL = 7,\n}\n\n/**\n * Options for a Box3D wheel joint (Box3D specific, no Babylon equivalent).\n * The suspension travels along axisA (chassis space), the wheel spins about spinAxisB (wheel space)\n * and steers about the suspension axis.\n */\nexport interface IBox3DWheelJointOptions {\n /** anchor on the chassis, chassis local space */\n pivotA: Vector3;\n /** suspension axis in chassis local space (usually up) */\n axisA?: Vector3;\n /** axle direction in chassis local space, the wheel spins about it (default +z) */\n axleA?: Vector3;\n /** anchor on the wheel, wheel local space */\n pivotB?: Vector3;\n /** suspension spring stiffness in hertz */\n suspensionHertz?: number;\n /** suspension spring damping ratio */\n suspensionDampingRatio?: number;\n /** suspension travel limits along axisA */\n suspensionLimits?: [number, number];\n /** whether the wheel is driven */\n enableSpinMotor?: boolean;\n /** maximum drive torque */\n maxSpinTorque?: number;\n /** whether the wheel steers */\n enableSteering?: boolean;\n /** steering spring stiffness in hertz */\n steeringHertz?: number;\n /** steering spring damping ratio */\n steeringDampingRatio?: number;\n /** maximum steering torque */\n maxSteeringTorque?: number;\n /** steering angle limits in radians */\n steeringLimits?: [number, number];\n}\n\n/**\n * Handle to a Box3D wheel joint created with Box3DPlugin.createWheelJoint.\n */\nexport class Box3DWheelJoint {\n /**\n * @internal\n */\n public constructor(\n private _plugin: Box3DPlugin,\n /** @internal */\n public _slot: number\n ) {}\n\n /**\n * Sets the target angular speed of the spin motor.\n * @param speed radians per second\n */\n public setSpinSpeed(speed: number): void {\n this._plugin._wheelCall(\"_bx_WheelJoint_SetSpinMotorSpeed\", this._slot, speed);\n }\n\n /**\n * Sets the maximum torque the spin motor can apply.\n * @param torque newton meters\n */\n public setMaxSpinTorque(torque: number): void {\n this._plugin._wheelCall(\"_bx_WheelJoint_SetMaxSpinTorque\", this._slot, torque);\n }\n\n /**\n * Enables or disables the spin motor (disabled wheels roll freely).\n * @param enabled true to enable\n */\n public enableSpinMotor(enabled: boolean): void {\n this._plugin._wheelCall(\"_bx_WheelJoint_EnableSpinMotor\", this._slot, enabled ? 1 : 0);\n }\n\n /**\n * Sets the target steering angle.\n * @param radians steering angle\n */\n public setSteeringAngle(radians: number): void {\n this._plugin._wheelCall(\"_bx_WheelJoint_SetTargetSteeringAngle\", this._slot, radians);\n }\n\n /**\n * Tunes the suspension spring.\n * @param hertz stiffness\n * @param dampingRatio damping ratio\n */\n public setSuspension(hertz: number, dampingRatio: number): void {\n this._plugin._wheelCall(\"_bx_WheelJoint_SetSuspension\", this._slot, hertz, dampingRatio);\n }\n\n /**\n * Removes the joint.\n */\n public dispose(): void {\n this._plugin._destroyExtraJoint(this._slot);\n this._slot = 0;\n }\n}\n\n/**\n * Body event mask bits, the same values Havok's plugin uses so masks can be copied over from Havok code.\n * Box3D reports begin and end touch events together (they are one shape flag) and hit events separately.\n */\nconst enum Box3DEventBits {\n COLLISION_STARTED = 1,\n COLLISION_CONTINUED = 2,\n COLLISION_FINISHED = 4,\n ALL = 7,\n}\n\n/**\n * How much heavier a locked rotation axis is made than the heaviest free one. Babylon locks an axis with a zero inertia\n * component, Box3D needs an invertible tensor; 1e5 leaves a body a hundred thousand times harder to turn about that axis\n * while the tensor stays well conditioned in float32.\n */\nconst LockedInertiaRatio = 1e5;\n\n/**\n * Diagonalizes a symmetric inertia tensor [ixx, iyy, izz, ixy, ixz, iyz] into its principal moments and the rotation\n * that turns principal axes into body axes (Babylon's inertiaOrientation). Jacobi rotations, a few sweeps are plenty for\n * a 3x3, and the common diagonal case exits immediately.\n */\nfunction DiagonalizeInertia(tensor: ArrayLike<number>, moments: Vector3, orientation: Quaternion): void {\n const a = [\n [tensor[0], tensor[3], tensor[4]],\n [tensor[3], tensor[1], tensor[5]],\n [tensor[4], tensor[5], tensor[2]],\n ];\n orientation.set(0, 0, 0, 1);\n moments.set(tensor[0], tensor[1], tensor[2]);\n const q = [0, 0, 0, 1];\n for (let sweep = 0; sweep < 24; sweep++) {\n // rotation matrix of q, columns are the current principal axes\n const [x, y, z, w] = q;\n const r = [\n [1 - 2 * (y * y + z * z), 2 * (x * y - z * w), 2 * (x * z + y * w)],\n [2 * (x * y + z * w), 1 - 2 * (x * x + z * z), 2 * (y * z - x * w)],\n [2 * (x * z - y * w), 2 * (y * z + x * w), 1 - 2 * (x * x + y * y)],\n ];\n // d = transpose(r) * a * r\n const d = [0, 1, 2].map((i) => [0, 1, 2].map((j) => [0, 1, 2].reduce((sum, k) => sum + r[k][i] * [0, 1, 2].reduce((s2, l) => s2 + a[k][l] * r[l][j], 0), 0)));\n moments.set(d[0][0], d[1][1], d[2][2]);\n orientation.set(q[0], q[1], q[2], q[3]);\n const offDiagonal = [Math.abs(d[1][2]), Math.abs(d[0][2]), Math.abs(d[0][1])];\n const k = offDiagonal.indexOf(Math.max(...offDiagonal));\n const k1 = (k + 1) % 3;\n const k2 = (k + 2) % 3;\n const off = d[k1][k2];\n const scale = Math.abs(d[0][0]) + Math.abs(d[1][1]) + Math.abs(d[2][2]) + 1e-30;\n if (Math.abs(off) <= 1e-9 * scale) {\n return;\n }\n let theta = (d[k2][k2] - d[k1][k1]) / (2 * off);\n const sign = theta > 0 ? 1 : -1;\n theta *= sign;\n const t = sign / (theta + (theta < 1e6 ? Math.sqrt(theta * theta + 1) : theta));\n const c = 1 / Math.sqrt(t * t + 1);\n if (c === 1) {\n return;\n }\n const jacobi = [0, 0, 0, 0];\n // d is transpose(r) * a * r and the step right multiplies q, so d becomes transpose(jacobi) * d * jacobi: the\n // quaternion has to turn by -theta where the matrix form of the Jacobi rotation turns by +theta. With the other\n // sign every sweep puts the off diagonal term straight back and the loop never converges.\n jacobi[k] = -sign * Math.sqrt((1 - c) / 2);\n jacobi[3] = Math.sqrt(1 - jacobi[k] * jacobi[k]);\n // q = q * jacobi\n const [qx, qy, qz, qw] = q;\n const [jx, jy, jz, jw] = jacobi;\n q[0] = qw * jx + qx * jw + qy * jz - qz * jy;\n q[1] = qw * jy - qx * jz + qy * jw + qz * jx;\n q[2] = qw * jz + qx * jy - qy * jx + qz * jw;\n q[3] = qw * jw - qx * jx - qy * jy - qz * jz;\n const length = Math.hypot(q[0], q[1], q[2], q[3]) || 1;\n for (let i = 0; i < 4; i++) {\n q[i] /= length;\n }\n }\n}\n\n/** Builds the symmetric tensor [ixx, iyy, izz, ixy, ixz, iyz] of principal moments rotated into body space. */\nfunction ComposeInertia(moments: ArrayLike<number>, orientation: Quaternion): number[] {\n const { x, y, z, w } = orientation;\n const r = [\n [1 - 2 * (y * y + z * z), 2 * (x * y - z * w), 2 * (x * z + y * w)],\n [2 * (x * y + z * w), 1 - 2 * (x * x + z * z), 2 * (y * z - x * w)],\n [2 * (x * z - y * w), 2 * (y * z + x * w), 1 - 2 * (x * x + y * y)],\n ];\n const at = (i: number, j: number) => r[i][0] * moments[0] * r[j][0] + r[i][1] * moments[1] * r[j][1] + r[i][2] * moments[2] * r[j][2];\n return [at(0, 0), at(1, 1), at(2, 2), at(0, 1), at(0, 2), at(1, 2)];\n}\n\n/** Shape description properties that Box3D can change on live shapes, see bx_Body_SyncShapeDesc. */\nconst enum Box3DShapeSync {\n FILTER = 1,\n MATERIAL = 2,\n DENSITY = 4,\n}\n\nconst MOVE_STRIDE = 9;\nconst CONTACT_STRIDE = 14;\nconst SENSOR_STRIDE = 5;\nconst RAY_STRIDE = 11;\n\n/**\n * Collects mesh geometry in the physics body's local space (scaling baked in).\n */\nclass MeshGeometryAccumulator {\n private _vertices: number[] = [];\n private _indices: number[] = [];\n\n public constructor(\n private _collectIndices: boolean,\n private _flipWinding: boolean\n ) {}\n\n public addNodeMeshes(mesh: TransformNode, includeChildren: boolean): void {\n mesh.computeWorldMatrix(true);\n const rootScaled = TmpVectors.Matrix[0];\n Matrix.ScalingToRef(mesh.absoluteScaling.x, mesh.absoluteScaling.y, mesh.absoluteScaling.z, rootScaled);\n if (mesh instanceof Mesh) {\n this._addMesh(mesh, rootScaled);\n } else if (mesh instanceof InstancedMesh) {\n this._addMesh(mesh.sourceMesh, rootScaled);\n }\n if (includeChildren) {\n const worldToRoot = TmpVectors.Matrix[1];\n mesh.computeWorldMatrix().invertToRef(worldToRoot);\n const worldToRootScaled = TmpVectors.Matrix[2];\n worldToRoot.multiplyToRef(rootScaled, worldToRootScaled);\n const children = mesh.getChildMeshes(false).filter((m: any) => !m.physicsBody);\n for (const m of children) {\n const childToWorld = m.computeWorldMatrix();\n const childToRootScaled = TmpVectors.Matrix[3];\n childToWorld.multiplyToRef(worldToRootScaled, childToRootScaled);\n if (m instanceof Mesh) {\n this._addMesh(m, childToRootScaled);\n } else if (m instanceof InstancedMesh) {\n this._addMesh(m.sourceMesh, childToRootScaled);\n }\n }\n }\n }\n\n private _addMesh(mesh: Mesh, meshToRoot: Matrix): void {\n const vertexData = mesh.getVerticesData(VertexBuffer.PositionKind) || [];\n const numVerts = vertexData.length / 3;\n const indexOffset = this._vertices.length / 3;\n const p = TmpVectors.Vector3[0];\n for (let v = 0; v < numVerts; v++) {\n p.set(vertexData[v * 3 + 0], vertexData[v * 3 + 1], vertexData[v * 3 + 2]);\n Vector3.TransformCoordinatesToRef(p, meshToRoot, p);\n this._vertices.push(p.x, p.y, p.z);\n }\n if (this._collectIndices) {\n const meshIndices = mesh.getIndices();\n if (meshIndices) {\n for (let i = 0; i < meshIndices.length; i += 3) {\n if (this._flipWinding) {\n this._indices.push(meshIndices[i + 2] + indexOffset, meshIndices[i + 1] + indexOffset, meshIndices[i + 0] + indexOffset);\n } else {\n this._indices.push(meshIndices[i + 0] + indexOffset, meshIndices[i + 1] + indexOffset, meshIndices[i + 2] + indexOffset);\n }\n }\n }\n }\n }\n\n public get vertexCount(): number {\n return this._vertices.length / 3;\n }\n\n public get triangleCount(): number {\n return this._indices.length / 3;\n }\n\n public get vertices(): number[] {\n return this._vertices;\n }\n\n public get indices(): number[] {\n return this._indices;\n }\n}\n\n/**\n * Every native entry point the plugin calls. The constructor checks that the module has all of them, because the two ways this goes wrong\n * in practice - a box3d.js loader left behind by an older install, or a box3d.wasm served from a stale copy - otherwise turn into a physics\n * world where nothing ever happens. A test keeps the list in step with the code.\n */\nconst RequiredNativeExports = [\n \"_bx_Body_AllowFastRotation\", \"_bx_Body_ApplyAngularImpulse\", \"_bx_Body_ApplyForce\", \"_bx_Body_ApplyLinearImpulse\",\n \"_bx_Body_ApplyMassFromShapes\", \"_bx_Body_ApplyTorque\", \"_bx_Body_ComputeShapeMassData\", \"_bx_Body_EnableSleep\", \"_bx_Body_GetAABB\",\n \"_bx_Body_GetAngularDamping\", \"_bx_Body_GetAngularVelocity\", \"_bx_Body_GetGravityScale\", \"_bx_Body_GetLinearDamping\",\n \"_bx_Body_GetLinearVelocity\", \"_bx_Body_GetMassData\", \"_bx_Body_GetTransform\", \"_bx_Body_SetAngularDamping\", \"_bx_Body_SetAngularVelocity\",\n \"_bx_Body_SetAwake\", \"_bx_Body_SetEventFlags\", \"_bx_Body_SetGravityScale\", \"_bx_Body_SetLinearDamping\", \"_bx_Body_SetLinearVelocity\",\n \"_bx_Body_SetMassDataFull\", \"_bx_Body_SetMotionLocks\", \"_bx_Body_SetShape\", \"_bx_Body_SetTargetTransform\", \"_bx_Body_SetTransform\",\n \"_bx_Body_SetType\", \"_bx_Body_SyncShapeDesc\", \"_bx_ComputeAlignedFrameB\", \"_bx_ContactEventsPtr\", \"_bx_CreateBody\", \"_bx_CreateJoint\",\n \"_bx_CreateWorld\", \"_bx_DebugIndexCount\", \"_bx_DebugIndicesPtr\", \"_bx_DebugPositionsPtr\", \"_bx_DestroyBody\", \"_bx_DestroyJoint\",\n \"_bx_DestroyWorld\", \"_bx_GetMaxWorkers\", \"_bx_GetRejectedSlotCount\", \"_bx_Joint_EnableLimit\", \"_bx_Joint_EnableMotor\",\n \"_bx_Joint_EnableSpring\", \"_bx_Joint_IsValid\",\n \"_bx_Joint_SetCollideConnected\", \"_bx_Joint_SetConstraintTuning\", \"_bx_Joint_SetLimits\", \"_bx_Joint_SetMaxMotorForce\",\n \"_bx_Joint_SetMotorSpeed\", \"_bx_Joint_SetSphericalMotor\", \"_bx_Joint_SetSphericalTarget\", \"_bx_Joint_SetSpring\", \"_bx_Joint_SetTarget\",\n \"_bx_Joint_SetTwistLimits\", \"_bx_Joint_UpdateMotorFrame\", \"_bx_Joint_WakeBodies\", \"_bx_MoveEventsPtr\", \"_bx_RayHitsPtr\", \"_bx_Scratch\",\n \"_bx_SensorEventsPtr\", \"_bx_ShapeDesc_AddChild\", \"_bx_ShapeDesc_BuildDebugGeometry\", \"_bx_ShapeDesc_CreateBox\", \"_bx_ShapeDesc_CreateCapsule\",\n \"_bx_ShapeDesc_CreateContainer\", \"_bx_ShapeDesc_CreateCylinder\", \"_bx_ShapeDesc_CreateHeightField\", \"_bx_ShapeDesc_CreateHull\",\n \"_bx_ShapeDesc_CreateMesh\", \"_bx_ShapeDesc_CreateSphere\", \"_bx_ShapeDesc_Destroy\", \"_bx_ShapeDesc_GetAABB\", \"_bx_ShapeDesc_GetCategoryBits\",\n \"_bx_ShapeDesc_GetChildCount\", \"_bx_ShapeDesc_GetDensity\", \"_bx_ShapeDesc_GetFriction\", \"_bx_ShapeDesc_GetMaskBits\",\n \"_bx_ShapeDesc_GetRestitution\", \"_bx_ShapeDesc_RemoveChild\", \"_bx_ShapeDesc_SetDensity\", \"_bx_ShapeDesc_SetFilter\", \"_bx_ShapeDesc_SetGroup\",\n \"_bx_ShapeDesc_SetMaterial\", \"_bx_ShapeDesc_SetRollingResistance\", \"_bx_ShapeDesc_SetSensor\", \"_bx_World_CastRay\", \"_bx_World_EnableContinuous\",\n \"_bx_World_EnableSleeping\", \"_bx_World_Explode\", \"_bx_World_GetContactEvents\", \"_bx_World_GetMaximumLinearSpeed\", \"_bx_World_GetMoveEvents\",\n \"_bx_World_GetSensorEvents\", \"_bx_World_GetStats\", \"_bx_World_GetWorkerCount\", \"_bx_World_SetGravity\", \"_bx_World_SetMaximumLinearSpeed\",\n \"_bx_World_Step\"\n];\n\n/**\n * Options for the Box3D plugin, passed to the constructor after the module.\n */\nexport interface IBox3DPluginOptions {\n /**\n * Workers box3d may put on a world step, counting the thread the step is called on. 1 (the default) keeps\n * everything on the calling thread. Anything above 1 needs the threaded build of the module\n * (`LoadBox3D({ threads: true })` or `babylon-box3d/wasm/threads`), which in turn needs a cross origin isolated\n * page; on the single threaded module the request is clamped to 1 and a warning explains why.\n * \"auto\" asks for half of `navigator.hardwareConcurrency`, capped at what the build supports: box3d gains little\n * from the second thread of a core, and leaving room for rendering matters more than the last worker.\n * The world is created in the constructor and box3d builds its threads with it, so this cannot change later.\n */\n workerCount?: number | \"auto\";\n /**\n * Solver sub steps per world step. Box3D's default of 4 is what keeps tall stacks standing; 2 roughly halves\n * solver time and is worth trying for scenes that are mostly loose bodies, 8 buys stiffness in exchange for time.\n */\n subStepCount?: number;\n}\n\n/**\n * Box3D physics plugin for Babylon.js physics v2.\n * Box3D is Erin Catto's 3D rigid body engine (https://github.com/erincatto/box3d). This plugin drives the\n * WebAssembly build that ships in this package (a flat, handle based C shim over box3d).\n * Usage mirrors the Havok plugin:\n * ```ts\n * import { Box3D, Box3DPlugin } from \"babylon-box3d\";\n * const box3d = await Box3D();\n * scene.enablePhysics(new Vector3(0, -9.81, 0), new Box3DPlugin(true, box3d));\n * ```\n * On a cross origin isolated page the threaded module can spread a step over several workers:\n * ```ts\n * import { LoadBox3D, Box3DPlugin } from \"babylon-box3d\";\n * const box3d = await LoadBox3D({ threads: \"auto\" });\n * scene.enablePhysics(new Vector3(0, -9.81, 0), new Box3DPlugin(true, box3d, { workerCount: \"auto\" }));\n * ```\n */\nexport class Box3DPlugin implements IPhysicsEnginePluginV2 {\n /** Reference to the WASM module (the value resolved by the module factory). */\n public world: any;\n /** Name of the plugin */\n public name = \"Box3DPlugin\";\n /** Number of solver sub steps per world step. Box3D recommends 4. */\n public subStepCount = 4;\n /** Workers box3d puts on a world step, counting the calling thread. 1 unless the threaded module asked for more. */\n public readonly workerCount: number = 1;\n /** Wall clock time of the last world step in milliseconds (JavaScript side, includes the event sync). */\n public lastStepTimeMs = 0;\n\n private _b3: any;\n private _worldSlot = 0;\n private _fixedTimeStep = 1 / 60;\n private _timeStep = 1 / 60;\n private _maxAngularVelocity = 4 * Math.PI * 10;\n private _bodies: Array<{ body: PhysicsBody; index: number; data: Box3DBodyData } | undefined> = [];\n private _shapes: Array<Box3DShapeData | undefined> = [];\n private _bodyCollisionObservable = new Map<number, Observable<IPhysicsCollisionEvent>>();\n private _bodyCollisionEndedObservable = new Map<number, Observable<IBasePhysicsCollisionEvent>>();\n private _touchedInstanceMeshes = new Set<Mesh>();\n /** spherical joints whose velocity motor target has to be re-expressed in world space every step */\n private _motorJoints = new Set<number>();\n private _tmpVec3 = [new Vector3(), new Vector3(), new Vector3(), new Vector3()];\n private _tmpQuat = [new Quaternion(), new Quaternion(), new Quaternion()];\n private _warned = new Set<string>();\n /** the shim's rejected slot counter as of the last step, see executeStep */\n private _rejectedSlots = 0;\n\n /** Observable for collision started and continued events */\n public onCollisionObservable = new Observable<IPhysicsCollisionEvent>();\n /** Observable for collision ended events */\n public onCollisionEndedObservable = new Observable<IBasePhysicsCollisionEvent>();\n /** Observable for trigger entered and exited events */\n public onTriggerCollisionObservable = new Observable<IBasePhysicsCollisionEvent>();\n\n /**\n * Creates a Box3D plugin.\n * @param _useDeltaForWorldStep step the world with the frame delta (true) or a fixed time step (false)\n * @param box3dModule the resolved Box3D WASM module (await Box3DModule())\n * @param options worker count and sub steps, see IBox3DPluginOptions\n */\n public constructor(\n private _useDeltaForWorldStep = true,\n box3dModule: any,\n options?: IBox3DPluginOptions\n ) {\n if (!box3dModule) {\n throw new Error(\"Box3D module is required: pass the awaited result of the Box3D module factory.\");\n }\n const missing = RequiredNativeExports.filter((name) => typeof box3dModule[name] !== \"function\");\n if (missing.length > 0) {\n throw new Error(\n `Box3DPlugin: the Box3D module is missing ${missing.length} entry point${missing.length === 1 ? \"\" : \"s\"} this build needs` +\n ` (${missing.slice(0, 3).join(\", \")}${missing.length > 3 ? \", ...\" : \"\"}). box3d.js and box3d.wasm have to come from the` +\n \" same build of this package: check what locateFile points at and clear any copied or cached box3d.wasm.\"\n );\n }\n this._b3 = box3dModule;\n this.world = box3dModule;\n if (options?.subStepCount !== undefined) {\n this.subStepCount = Math.max(1, Math.round(options.subStepCount));\n }\n this._worldSlot = this._b3._bx_CreateWorld(0, -9.81, 0, this._resolveWorkerCount(options?.workerCount));\n if (!this._worldSlot) {\n throw new Error(\"Box3D: could not create a world (max worlds reached?)\");\n }\n // what box3d settled on, which is the request clamped to what this build of the module can run\n this.workerCount = Math.max(1, this._b3._bx_World_GetWorkerCount(this._worldSlot));\n }\n\n /**\n * Turns the requested worker count into one this module can honour. Only the threaded build reports more than one,\n * and asking a single threaded build for workers is quiet enough to look like it worked, so say so once.\n * @param requested the constructor option\n * @returns the count to create the world with\n */\n private _resolveWorkerCount(requested: number | \"auto\" | undefined): number {\n const supported = Math.max(1, this._b3._bx_GetMaxWorkers());\n if (requested === undefined) {\n return 1;\n }\n let wanted: number;\n if (requested === \"auto\") {\n const cores = (typeof navigator !== \"undefined\" && navigator.hardwareConcurrency) || 4;\n // half the reported cores: the other half is usually the second thread of each core, and box3d gains\n // little from those, while the renderer still needs somewhere to run\n wanted = Math.max(1, Math.floor(cores / 2));\n } else {\n wanted = Math.max(1, Math.round(requested));\n }\n if (wanted > 1 && supported === 1) {\n this._warnOnce(\n \"single-threaded-module\",\n `${wanted} workers were requested, but this Box3D module was built without threads, so the step stays on the calling ` +\n \"thread. Load the threaded build (LoadBox3D({ threads: true }), or babylon-box3d/wasm/threads) from a cross origin \" +\n \"isolated page: it needs SharedArrayBuffer, which browsers only allow with the COOP and COEP headers set.\"\n );\n }\n return Math.min(wanted, supported);\n }\n\n // ----------------------------------------------------------------------------------------\n // helpers\n // ----------------------------------------------------------------------------------------\n\n private _scratch(): Float32Array {\n return new Float32Array(this._b3.HEAPF32.buffer, this._b3._bx_Scratch(), 64);\n }\n\n private _warnOnce(key: string, message: string): void {\n if (!this._warned.has(key)) {\n this._warned.add(key);\n Logger.Warn(`Box3DPlugin: ${message}`);\n }\n }\n\n private _getPluginReference(body: PhysicsBody, instanceIndex?: number): Box3DBodyData {\n return body._pluginDataInstances?.length ? body._pluginDataInstances[instanceIndex ?? 0] : body._pluginData;\n }\n\n private _applyToBodyOrInstances(body: PhysicsBody, fn: (data: Box3DBodyData) => void, instanceIndex?: number): void {\n if (body._pluginDataInstances?.length > 0 && instanceIndex === undefined) {\n for (const data of body._pluginDataInstances) {\n fn(data);\n }\n } else {\n fn(this._getPluginReference(body, instanceIndex));\n }\n }\n\n private _motionTypeToNative(motionType: PhysicsMotionType): number {\n switch (motionType) {\n case PhysicsMotionType.STATIC:\n return 0;\n case PhysicsMotionType.ANIMATED:\n return 1;\n default:\n return 2;\n }\n }\n\n private _nodeTransformToRef(node: TransformNode, position: Vector3, orientation: Quaternion): void {\n if (node.parent) {\n node.computeWorldMatrix(true);\n position.copyFrom(node.absolutePosition);\n orientation.copyFrom(node.absoluteRotationQuaternion);\n return;\n }\n position.copyFrom(node.position);\n if (node.rotationQuaternion) {\n orientation.copyFrom(node.rotationQuaternion);\n } else {\n Quaternion.FromEulerAnglesToRef(node.rotation.x, node.rotation.y, node.rotation.z, orientation);\n }\n }\n\n // ----------------------------------------------------------------------------------------\n // world\n // ----------------------------------------------------------------------------------------\n\n public setGravity(gravity: Vector3): void {\n this._b3._bx_World_SetGravity(this._worldSlot, gravity.x, gravity.y, gravity.z);\n }\n\n public setTimeStep(timeStep: number): void {\n this._fixedTimeStep = timeStep;\n }\n\n public getTimeStep(): number {\n return this._fixedTimeStep;\n }\n\n public executeStep(delta: number, physicsBodies: Array<PhysicsBody>): void {\n for (const physicsBody of physicsBodies) {\n if (physicsBody.disablePreStep) {\n continue;\n }\n this.setPhysicsBodyTransformation(physicsBody, physicsBody.transformNode);\n }\n\n for (const joint of this._motorJoints) {\n // a joint whose bodies were destroyed is gone with them, drop it instead of holding the slot forever\n if (this._b3._bx_Joint_IsValid(joint)) {\n this._b3._bx_Joint_UpdateMotorFrame(joint);\n } else {\n this._motorJoints.delete(joint);\n }\n }\n\n const deltaTime = this._useDeltaForWorldStep ? delta : this._fixedTimeStep;\n this._timeStep = deltaTime;\n const start = performance.now();\n this._b3._bx_World_Step(this._worldSlot, deltaTime, this.subStepCount);\n\n // Only bodies that moved report an event, so sync those instead of iterating every body.\n const moveCount = this._b3._bx_World_GetMoveEvents(this._worldSlot);\n if (moveCount > 0) {\n const movePointer = this._b3._bx_MoveEventsPtr();\n let buffer = new Float32Array(this._b3.HEAPF32.buffer, movePointer, moveCount * MOVE_STRIDE);\n for (let i = 0; i < moveCount; i++) {\n if (buffer.buffer !== this._b3.HEAPF32.buffer) {\n // a world matrix observer grew the wasm memory; the records are still in place\n buffer = new Float32Array(this._b3.HEAPF32.buffer, movePointer, moveCount * MOVE_STRIDE);\n }\n const offset = i * MOVE_STRIDE;\n const ref = this._bodies[buffer[offset]];\n if (!ref || ref.body.disableSync) {\n continue;\n }\n this._syncBodyFromBuffer(ref.body, ref.index, buffer, offset + 1);\n }\n for (const mesh of this._touchedInstanceMeshes) {\n mesh.thinInstanceBufferUpdated(\"matrix\");\n }\n this._touchedInstanceMeshes.clear();\n }\n\n this._notifyCollisions();\n this._notifyTriggers();\n this.lastStepTimeMs = performance.now() - start;\n\n // Every native entry point returns quietly when it does not recognize a handle. That is what teardown needs and\n // it hides everything else, so say it once instead of simulating a world where half the calls do nothing.\n const rejected = this._b3._bx_GetRejectedSlotCount();\n if (rejected > this._rejectedSlots) {\n this._rejectedSlots = rejected;\n this._warnOnce(\n \"rejected-slots\",\n `the native module did not recognize ${rejected} of the handles it was given, and those calls did nothing. Something is using a ` +\n \"body, shape or joint after it was destroyed, or box3d.js and box3d.wasm are from different builds.\"\n );\n }\n }\n\n public getPluginVersion(): number {\n return 2;\n }\n\n public setVelocityLimits(maxLinearVelocity: number, maxAngularVelocity: number): void {\n this._b3._bx_World_SetMaximumLinearSpeed(this._worldSlot, maxLinearVelocity);\n this._maxAngularVelocity = maxAngularVelocity;\n }\n\n public getMaxLinearVelocity(): number {\n return this._b3._bx_World_GetMaximumLinearSpeed(this._worldSlot);\n }\n\n public getMaxAngularVelocity(): number {\n return this._maxAngularVelocity;\n }\n\n /**\n * Box3D counters and timings for the current world.\n * @returns body, shape, contact, joint and island counts plus the last step time in milliseconds\n */\n public getStats(): { bodies: number; shapes: number; contacts: number; joints: number; islands: number; stepMs: number; collideMs: number; solveMs: number } {\n this._b3._bx_World_GetStats(this._worldSlot);\n const s = this._scratch();\n return { bodies: s[0], shapes: s[1], contacts: s[2], joints: s[3], islands: s[4], stepMs: s[5], collideMs: s[6], solveMs: s[7] };\n }\n\n /**\n * Enables or disables island sleeping.\n * @param enabled true to let resting bodies sleep\n */\n public setSleepingEnabled(enabled: boolean): void {\n this._b3._bx_World_EnableSleeping(this._worldSlot, enabled ? 1 : 0);\n }\n\n /**\n * Enables or disables continuous collision against static geometry.\n * @param enabled true to enable continuous collision\n */\n public setContinuousEnabled(enabled: boolean): void {\n this._b3._bx_World_EnableContinuous(this._worldSlot, enabled ? 1 : 0);\n }\n\n // ----------------------------------------------------------------------------------------\n // bodies\n // ----------------------------------------------------------------------------------------\n\n private _createNativeBody(motionType: PhysicsMotionType, position: Vector3, orientation: Quaternion, startAsleep: boolean): Box3DBodyData {\n const slot = this._b3._bx_CreateBody(\n this._worldSlot,\n this._motionTypeToNative(motionType),\n position.x,\n position.y,\n position.z,\n orientation.x,\n orientation.y,\n orientation.z,\n orientation.w,\n startAsleep ? 0 : 1\n );\n const data = new Box3DBodyData(slot);\n data.motionType = motionType;\n return data;\n }\n\n public initBody(body: PhysicsBody, motionType: PhysicsMotionType, position: Vector3, orientation: Quaternion): void {\n const data = this._createNativeBody(motionType, position, orientation, body.startAsleep);\n body._pluginData = data;\n this._bodies[data.slot] = { body, index: 0, data };\n }\n\n public initBodyInstances(body: PhysicsBody, motionType: PhysicsMotionType, mesh: Mesh): void {\n const instancesCount = mesh._thinInstanceDataStorage?.instancesCount ?? 0;\n const matrixData = mesh._thinInstanceDataStorage?.matrixData;\n if (!matrixData) {\n return;\n }\n const shape = body.shape?._pluginData as Box3DShapeData | undefined;\n if (instancesCount > 8 && shape && this._bakesMeshCopies(shape)) {\n this._warnOnce(\n \"instanced-mesh-child\",\n \"a mesh inside a container has no local transform in Box3D, so every instance gets its own baked copy of the mesh data; \" +\n \"put the mesh on the body directly, or bake the offset into the mesh, to share it.\"\n );\n }\n this._createOrUpdateBodyInstances(body, motionType, matrixData, 0, instancesCount, false);\n }\n\n private _createOrUpdateBodyInstances(body: PhysicsBody, motionType: PhysicsMotionType, matrixData: Float32Array, startIndex: number, endIndex: number, update: boolean): void {\n const rotation = TmpVectors.Quaternion[0];\n const rotationMatrix = TmpVectors.Matrix[0];\n const position = TmpVectors.Vector3[0];\n for (let i = startIndex; i < endIndex; i++) {\n position.set(matrixData[i * 16 + 12], matrixData[i * 16 + 13], matrixData[i * 16 + 14]);\n Matrix.FromArrayToRef(matrixData, i * 16, rotationMatrix);\n rotationMatrix.decompose(undefined, rotation, undefined);\n if (update) {\n const data = body._pluginDataInstances[i];\n this._b3._bx_Body_SetTransform(data.slot, position.x, position.y, position.z, rotation.x, rotation.y, rotation.z, rotation.w);\n } else {\n const data = this._createNativeBody(motionType, position, rotation, body.startAsleep);\n const sibling = body._pluginDataInstances[0] as Box3DBodyData | undefined;\n if (sibling) {\n // a new instance behaves like the ones already there: same mass properties, events and activation\n data.userMassProps = sibling.userMassProps;\n data.eventMask = sibling.eventMask;\n this._applyEventFlags(data);\n if (sibling.activation !== PhysicsActivationControl.SIMULATION_CONTROLLED) {\n data.activation = sibling.activation;\n this._applyNativeMotionType(data);\n this._b3._bx_Body_EnableSleep(data.slot, sibling.activation === PhysicsActivationControl.ALWAYS_ACTIVE ? 0 : 1);\n }\n }\n body._pluginDataInstances.push(data);\n this._bodies[data.slot] = { body, index: i, data };\n }\n }\n }\n\n public updateBodyInstances(body: PhysicsBody, mesh: Mesh): void {\n const instancesCount = mesh._thinInstanceDataStorage?.instancesCount ?? 0;\n const matrixData = mesh._thinInstanceDataStorage?.matrixData;\n if (!matrixData) {\n return;\n }\n const pluginInstancesCount = body._pluginDataInstances.length;\n const motionType = this.getMotionType(body);\n if (instancesCount > pluginInstancesCount) {\n this._createOrUpdateBodyInstances(body, motionType, matrixData, pluginInstancesCount, instancesCount, false);\n const shape = body.shape;\n if (shape && shape._pluginData) {\n for (let i = pluginInstancesCount; i < instancesCount; i++) {\n this._setBodyShape(body._pluginDataInstances[i], shape._pluginData as Box3DShapeData);\n }\n }\n } else if (instancesCount < pluginInstancesCount) {\n const instancesToRemove = pluginInstancesCount - instancesCount;\n for (let i = 0; i < instancesToRemove; i++) {\n const data = body._pluginDataInstances.pop() as Box3DBodyData;\n this._destroyBodyData(data);\n }\n this._createOrUpdateBodyInstances(body, motionType, matrixData, 0, instancesCount, true);\n }\n }\n\n private _destroyBodyData(data: Box3DBodyData): void {\n if (!data) {\n return;\n }\n for (const shape of this._shapes) {\n shape?.users.delete(data);\n }\n this._bodyCollisionObservable.delete(data.slot);\n this._bodyCollisionEndedObservable.delete(data.slot);\n this._bodies[data.slot] = undefined;\n this._b3._bx_DestroyBody(data.slot);\n data.slot = 0;\n }\n\n public removeBody(body: PhysicsBody): void {\n // Box3D has no add/remove without destroying. The body is destroyed and re-created by initBody if needed.\n if (body._pluginDataInstances?.length) {\n for (const data of body._pluginDataInstances) {\n this._destroyBodyData(data);\n }\n }\n if (body._pluginData) {\n this._destroyBodyData(body._pluginData);\n }\n }\n\n public sync(body: PhysicsBody): void {\n this.syncTransform(body, body.transformNode);\n }\n\n private _syncBodyFromBuffer(body: PhysicsBody, index: number, buffer: Float32Array, offset: number): void {\n const node = body.transformNode;\n if (body._pluginDataInstances.length) {\n const m = node as Mesh;\n const matrixData = m._thinInstanceDataStorage?.matrixData;\n if (!matrixData) {\n return;\n }\n const scale = this._tmpVec3[0];\n const base = index * 16;\n scale.set(\n Math.hypot(matrixData[base], matrixData[base + 1], matrixData[base + 2]),\n Math.hypot(matrixData[base + 4], matrixData[base + 5], matrixData[base + 6]),\n Math.hypot(matrixData[base + 8], matrixData[base + 9], matrixData[base + 10])\n );\n const quat = this._tmpQuat[0];\n quat.set(buffer[offset + 3], buffer[offset + 4], buffer[offset + 5], buffer[offset + 6]);\n const position = this._tmpVec3[1];\n position.set(buffer[offset], buffer[offset + 1], buffer[offset + 2]);\n const matrix = TmpVectors.Matrix[0];\n Matrix.ComposeToRef(scale, quat, position, matrix);\n matrix.copyToArray(matrixData, base);\n this._touchedInstanceMeshes.add(m);\n return;\n }\n this._applyTransformToNode(node, buffer[offset], buffer[offset + 1], buffer[offset + 2], buffer[offset + 3], buffer[offset + 4], buffer[offset + 5], buffer[offset + 6]);\n }\n\n private _applyTransformToNode(node: TransformNode, px: number, py: number, pz: number, qx: number, qy: number, qz: number, qw: number): void {\n const quat = this._tmpQuat[0];\n quat.set(qx, qy, qz, qw);\n const parent = node.parent as TransformNode;\n if (parent && !parent.getWorldMatrix().isIdentity()) {\n parent.computeWorldMatrix(true);\n const savedScaling = this._tmpVec3[2];\n savedScaling.copyFrom(node.scaling);\n const finalTransform = TmpVectors.Matrix[0];\n const finalTranslation = this._tmpVec3[3];\n finalTranslation.set(px, py, pz);\n Matrix.ComposeToRef(node.absoluteScaling, quat, finalTranslation, finalTransform);\n const parentInverse = TmpVectors.Matrix[1];\n parent.getWorldMatrix().invertToRef(parentInverse);\n const localTransform = TmpVectors.Matrix[2];\n finalTransform.multiplyToRef(parentInverse, localTransform);\n localTransform.decomposeToTransformNode(node);\n node.rotationQuaternion?.normalize();\n node.scaling.copyFrom(savedScaling);\n } else {\n node.position.set(px, py, pz);\n if (node.rotationQuaternion) {\n node.rotationQuaternion.copyFrom(quat);\n } else {\n quat.toEulerAnglesToRef(node.rotation);\n }\n }\n }\n\n public syncTransform(body: PhysicsBody, transformNode: TransformNode): void {\n if (body._pluginDataInstances.length) {\n const m = transformNode as Mesh;\n const matrixData = m._thinInstanceDataStorage?.matrixData;\n if (!matrixData) {\n return;\n }\n for (let i = 0; i < body._pluginDataInstances.length; i++) {\n const data = body._pluginDataInstances[i] as Box3DBodyData;\n this._b3._bx_Body_GetTransform(data.slot);\n this._syncBodyFromBuffer(body, i, this._scratch(), 0);\n }\n m.thinInstanceBufferUpdated(\"matrix\");\n this._touchedInstanceMeshes.delete(m);\n return;\n }\n const data = body._pluginData as Box3DBodyData;\n if (!data || !data.slot) {\n return;\n }\n this._b3._bx_Body_GetTransform(data.slot);\n const s = this._scratch();\n this._applyTransformToNode(transformNode, s[0], s[1], s[2], s[3], s[4], s[5], s[6]);\n }\n\n /**\n * Pushes the transform node's pose into the physics body (called during the pre step).\n * @param body the physics body\n * @param node the transform node to read from\n */\n public setPhysicsBodyTransformation(body: PhysicsBody, node: TransformNode): void {\n const prestep = body.getPrestepType();\n if (prestep == PhysicsPrestepType.TELEPORT) {\n if (body._pluginDataInstances.length > 0) {\n const m = node as Mesh;\n const matrixData = m._thinInstanceDataStorage?.matrixData;\n if (!matrixData) {\n return;\n }\n this._createOrUpdateBodyInstances(body, body.getMotionType(), matrixData, 0, body._pluginDataInstances.length, true);\n return;\n }\n const data = body._pluginData as Box3DBodyData;\n const position = this._tmpVec3[0];\n const orientation = this._tmpQuat[0];\n this._nodeTransformToRef(node, position, orientation);\n this._b3._bx_Body_SetTransform(data.slot, position.x, position.y, position.z, orientation.x, orientation.y, orientation.z, orientation.w);\n } else if (prestep == PhysicsPrestepType.ACTION) {\n this.setTargetTransform(body, node.absolutePosition, node.absoluteRotationQuaternion);\n } else if (prestep == PhysicsPrestepType.DISABLED) {\n Logger.Warn(\"Prestep type is set to DISABLED. Unable to set physics body transformation.\");\n }\n }\n\n public setTargetTransform(body: PhysicsBody, position: Vector3, rotation: Quaternion, instanceIndex?: number): void {\n this._applyToBodyOrInstances(\n body,\n (data) => {\n this._b3._bx_Body_SetTargetTransform(data.slot, position.x, position.y, position.z, rotation.x, rotation.y, rotation.z, rotation.w, this._timeStep);\n },\n instanceIndex\n );\n }\n\n /** True when the shape puts a mesh inside a container, which Box3D can only do by baking a copy per body. */\n private _bakesMeshCopies(data: Box3DShapeData, visited = new Set<Box3DShapeData>()): boolean {\n if (visited.has(data)) {\n return false;\n }\n visited.add(data);\n return data.children.some((child) => child.type === PhysicsShapeType.MESH || this._bakesMeshCopies(child, visited));\n }\n\n private _setBodyShape(data: Box3DBodyData, shape: Nullable<Box3DShapeData>): void {\n for (const existing of this._shapes) {\n existing?.users.delete(data);\n }\n this._b3._bx_Body_SetShape(data.slot, shape ? shape.slot : 0);\n if (shape) {\n shape.users.add(data);\n }\n this._applyEventFlags(data);\n this._internalUpdateMassProperties(data);\n }\n\n public setShape(body: PhysicsBody, shape: Nullable<PhysicsShape>): void {\n const shapeData = shape && shape._pluginData ? (shape._pluginData as Box3DShapeData) : null;\n this._applyToBodyOrInstances(body, (data) => this._setBodyShape(data, shapeData));\n }\n\n public getShape(body: PhysicsBody): Nullable<PhysicsShape> {\n return body.shape ?? null;\n }\n\n public getShapeType(shape: PhysicsShape): PhysicsShapeType {\n return shape.type ?? (shape._pluginData as Box3DShapeData)?.type ?? PhysicsShapeType.CONTAINER;\n }\n\n /** Turns the body's event mask into Box3D's two shape flags, so a body only pays for the events it asked for. */\n private _applyEventFlags(data: Box3DBodyData): void {\n const touch = data.eventMask & (Box3DEventBits.COLLISION_STARTED | Box3DEventBits.COLLISION_FINISHED) ? 1 : 0;\n const hit = data.eventMask & Box3DEventBits.COLLISION_CONTINUED ? 1 : 0;\n this._b3._bx_Body_SetEventFlags(data.slot, touch, hit);\n }\n\n public setEventMask(body: PhysicsBody, eventMask: number, instanceIndex?: number): void {\n this._applyToBodyOrInstances(\n body,\n (data) => {\n data.eventMask = eventMask;\n this._applyEventFlags(data);\n },\n instanceIndex\n );\n }\n\n public getEventMask(body: PhysicsBody, instanceIndex?: number): number {\n return this._getPluginReference(body, instanceIndex).eventMask;\n }\n\n public setMotionType(body: PhysicsBody, motionType: PhysicsMotionType, instanceIndex?: number): void {\n this._applyToBodyOrInstances(\n body,\n (data) => {\n data.motionType = motionType;\n this._applyNativeMotionType(data);\n this._internalUpdateMassProperties(data);\n },\n instanceIndex\n );\n }\n\n /** The Box3D body type: the Babylon motion type, unless the body is parked by ALWAYS_INACTIVE. */\n private _applyNativeMotionType(data: Box3DBodyData): void {\n const native = data.activation === PhysicsActivationControl.ALWAYS_INACTIVE ? 0 : this._motionTypeToNative(data.motionType);\n this._b3._bx_Body_SetType(data.slot, native);\n }\n\n /**\n * Babylon's activation control, matched to Havok's behaviour with Box3D sleeping.\n * ALWAYS_ACTIVE turns sleeping off for the body, SIMULATION_CONTROLLED turns it back on. ALWAYS_INACTIVE parks the\n * body: in Havok such a body ignores impulses and velocity changes, is not woken by anything that touches it and\n * still blocks other bodies, which Box3D sleeping alone cannot do, so it becomes a static Box3D body until the\n * control changes. Coming back it is left asleep, like Havok, until something wakes it.\n * @param body the physics body\n * @param controlMode how the body may be activated and deactivated\n * @param instanceIndex optional thin instance index\n */\n public setActivationControl(body: PhysicsBody, controlMode: PhysicsActivationControl, instanceIndex?: number): void {\n this._applyToBodyOrInstances(\n body,\n (data) => {\n if (data.activation === controlMode) {\n return;\n }\n const wasInactive = data.activation === PhysicsActivationControl.ALWAYS_INACTIVE;\n data.activation = controlMode;\n if (controlMode === PhysicsActivationControl.ALWAYS_INACTIVE) {\n this._b3._bx_Body_SetLinearVelocity(data.slot, 0, 0, 0);\n this._b3._bx_Body_SetAngularVelocity(data.slot, 0, 0, 0);\n this._applyNativeMotionType(data);\n return;\n }\n this._applyNativeMotionType(data);\n this._internalUpdateMassProperties(data);\n this._b3._bx_Body_EnableSleep(data.slot, controlMode === PhysicsActivationControl.ALWAYS_ACTIVE ? 0 : 1);\n if (wasInactive && controlMode === PhysicsActivationControl.SIMULATION_CONTROLLED) {\n this._b3._bx_Body_SetAwake(data.slot, 0);\n }\n },\n instanceIndex\n );\n }\n\n public getMotionType(body: PhysicsBody, instanceIndex?: number): PhysicsMotionType {\n return this._getPluginReference(body, instanceIndex).motionType;\n }\n\n /**\n * Reads Box3D's mass data and converts it to Babylon's form: the inertia is the principal moments of the tensor\n * divided by the mass (Babylon's inertia is per unit mass) and the orientation rotates the principal axes into\n * body space.\n */\n private _readMassData(data: Box3DBodyData): PhysicsMassProperties {\n // Box3D keeps mass 0 on static and kinematic bodies; Havok reports what the shapes weigh whatever the type\n if (data.motionType === PhysicsMotionType.DYNAMIC && data.activation !== PhysicsActivationControl.ALWAYS_INACTIVE) {\n this._b3._bx_Body_GetMassData(data.slot);\n } else {\n this._b3._bx_Body_ComputeShapeMassData(data.slot);\n }\n const s = this._scratch();\n const mass = s[0];\n const principal = new Vector3();\n const orientation = new Quaternion();\n DiagonalizeInertia([s[4], s[5], s[6], s[7], s[8], s[9]], principal, orientation);\n if (mass > 0) {\n principal.scaleInPlace(1 / mass);\n }\n return {\n mass,\n centerOfMass: new Vector3(s[1], s[2], s[3]),\n inertia: principal,\n inertiaOrientation: orientation,\n };\n }\n\n /** The mass properties of the body: what the user asked for, filled in from the shapes where they said nothing. */\n private _resolveMassProperties(data: Box3DBodyData): Required<PhysicsMassProperties> {\n const computed = this._readMassData(data);\n const user = data.userMassProps ?? {};\n // no invented mass here: a body with no shapes really does weigh nothing, only the tensor written to Box3D\n // needs a positive mass (see _internalUpdateMassProperties)\n const mass = user.mass !== undefined && user.mass > 0 ? user.mass : computed.mass!;\n return {\n mass,\n centerOfMass: user.centerOfMass ?? computed.centerOfMass!,\n inertia: user.inertia ?? computed.inertia!,\n inertiaOrientation: user.inertiaOrientation ?? (user.inertia ? Quaternion.Identity() : computed.inertiaOrientation!),\n };\n }\n\n private _internalUpdateMassProperties(data: Box3DBodyData): void {\n if (data.motionType !== PhysicsMotionType.DYNAMIC || data.activation === PhysicsActivationControl.ALWAYS_INACTIVE) {\n // motion locks are world space velocity locks, they would fight a kinematic body's target transform\n this._applyMotionLocks(data, false, false, false);\n return;\n }\n this._b3._bx_Body_ApplyMassFromShapes(data.slot);\n const user = data.userMassProps;\n const hasUser = !!user && (user.mass !== undefined || !!user.centerOfMass || !!user.inertia || !!user.inertiaOrientation);\n if (!hasUser) {\n this._applyMotionLocks(data, false, false, false);\n return;\n }\n const props = this._resolveMassProperties(data);\n // a dynamic body with no mass at all would ignore gravity and every impulse\n const mass = props.mass > 0 ? props.mass : 1;\n const inertia = props.inertia;\n const orientation = props.inertiaOrientation;\n // Babylon's inertia is per unit mass and a zero component means infinite inertia about that principal axis.\n // Box3D needs an invertible tensor, so a locked axis gets a very large moment; where the free axes stay aligned\n // with the world, Box3D's motion locks are added on top and make it exact.\n const locked = [inertia.x <= 0, inertia.y <= 0, inertia.z <= 0];\n const largest = Math.max(inertia.x, inertia.y, inertia.z, 1e-4) * LockedInertiaRatio;\n const moments = [locked[0] ? largest : inertia.x, locked[1] ? largest : inertia.y, locked[2] ? largest : inertia.z].map((value) => value * mass);\n const tensor = ComposeInertia(moments, orientation);\n this._b3._bx_Body_SetMassDataFull(\n data.slot,\n mass,\n props.centerOfMass.x,\n props.centerOfMass.y,\n props.centerOfMass.z,\n tensor[0],\n tensor[1],\n tensor[2],\n tensor[3],\n tensor[4],\n tensor[5]\n );\n this._applyLockedAxes(data, locked, orientation);\n }\n\n /**\n * Box3D locks are world space, Babylon's zero inertia components are body local. Locking two of them leaves a single\n * free axis, and if that axis is world aligned the body can only ever spin about it, so the world locks are exact\n * and stay exact. Everything else relies on the large moment above.\n */\n private _applyLockedAxes(data: Box3DBodyData, locked: boolean[], orientation: Quaternion): void {\n const count = locked.filter(Boolean).length;\n if (count === 3) {\n this._applyMotionLocks(data, true, true, true);\n return;\n }\n if (count !== 2) {\n this._applyMotionLocks(data, false, false, false);\n return;\n }\n this._b3._bx_Body_GetTransform(data.slot);\n const s = this._scratch();\n const bodyRotation = this._tmpQuat[0].set(s[3], s[4], s[5], s[6]);\n const free = locked.indexOf(false);\n const axis = this._tmpVec3[0].set(free === 0 ? 1 : 0, free === 1 ? 1 : 0, free === 2 ? 1 : 0);\n axis.applyRotationQuaternionInPlace(orientation).applyRotationQuaternionInPlace(bodyRotation);\n const components = [Math.abs(axis.x), Math.abs(axis.y), Math.abs(axis.z)];\n const dominant = components.indexOf(Math.max(...components));\n if (components[dominant] > 0.9999) {\n this._applyMotionLocks(data, dominant !== 0, dominant !== 1, dominant !== 2);\n } else {\n this._applyMotionLocks(data, false, false, false);\n }\n }\n\n private _applyMotionLocks(data: Box3DBodyData, x: boolean, y: boolean, z: boolean): void {\n const locks = (x ? 1 : 0) | (y ? 2 : 0) | (z ? 4 : 0);\n if (locks === data.angularLocks) {\n return;\n }\n data.angularLocks = locks;\n this._b3._bx_Body_SetMotionLocks(data.slot, 0, 0, 0, x ? 1 : 0, y ? 1 : 0, z ? 1 : 0);\n }\n\n public computeMassProperties(body: PhysicsBody, instanceIndex?: number): PhysicsMassProperties {\n const data = this._getPluginReference(body, instanceIndex);\n this._b3._bx_Body_ApplyMassFromShapes(data.slot);\n const computed = this._readMassData(data);\n this._internalUpdateMassProperties(data);\n return computed;\n }\n\n public setMassProperties(body: PhysicsBody, massProps: PhysicsMassProperties, instanceIndex?: number): void {\n this._applyToBodyOrInstances(\n body,\n (data) => {\n data.userMassProps = massProps;\n this._internalUpdateMassProperties(data);\n },\n instanceIndex\n );\n }\n\n public getMassProperties(body: PhysicsBody, instanceIndex?: number): PhysicsMassProperties {\n return this._resolveMassProperties(this._getPluginReference(body, instanceIndex));\n }\n\n public setLinearDamping(body: PhysicsBody, damping: number, instanceIndex?: number): void {\n this._applyToBodyOrInstances(body, (data) => this._b3._bx_Body_SetLinearDamping(data.slot, damping), instanceIndex);\n }\n\n public getLinearDamping(body: PhysicsBody, instanceIndex?: number): number {\n return this._b3._bx_Body_GetLinearDamping(this._getPluginReference(body, instanceIndex).slot);\n }\n\n public setAngularDamping(body: PhysicsBody, damping: number, instanceIndex?: number): void {\n this._applyToBodyOrInstances(body, (data) => this._b3._bx_Body_SetAngularDamping(data.slot, damping), instanceIndex);\n }\n\n public getAngularDamping(body: PhysicsBody, instanceIndex?: number): number {\n return this._b3._bx_Body_GetAngularDamping(this._getPluginReference(body, instanceIndex).slot);\n }\n\n public setLinearVelocity(body: PhysicsBody, linVel: Vector3, instanceIndex?: number): void {\n this._applyToBodyOrInstances(body, (data) => this._b3._bx_Body_SetLinearVelocity(data.slot, linVel.x, linVel.y, linVel.z), instanceIndex);\n }\n\n public getLinearVelocityToRef(body: PhysicsBody, linVel: Vector3, instanceIndex?: number): void {\n this._b3._bx_Body_GetLinearVelocity(this._getPluginReference(body, instanceIndex).slot);\n const s = this._scratch();\n linVel.set(s[0], s[1], s[2]);\n }\n\n public applyImpulse(body: PhysicsBody, impulse: Vector3, location: Vector3, instanceIndex?: number): void {\n this._applyToBodyOrInstances(\n body,\n (data) => this._b3._bx_Body_ApplyLinearImpulse(data.slot, impulse.x, impulse.y, impulse.z, location.x, location.y, location.z),\n instanceIndex\n );\n }\n\n public applyAngularImpulse(body: PhysicsBody, angularImpulse: Vector3, instanceIndex?: number): void {\n this._applyToBodyOrInstances(body, (data) => this._b3._bx_Body_ApplyAngularImpulse(data.slot, angularImpulse.x, angularImpulse.y, angularImpulse.z), instanceIndex);\n }\n\n public applyForce(body: PhysicsBody, force: Vector3, location: Vector3, instanceIndex?: number): void {\n this._applyToBodyOrInstances(body, (data) => this._b3._bx_Body_ApplyForce(data.slot, force.x, force.y, force.z, location.x, location.y, location.z), instanceIndex);\n }\n\n public applyTorque(body: PhysicsBody, torque: Vector3, instanceIndex?: number): void {\n this._applyToBodyOrInstances(body, (data) => this._b3._bx_Body_ApplyTorque(data.slot, torque.x, torque.y, torque.z), instanceIndex);\n }\n\n public setAngularVelocity(body: PhysicsBody, angVel: Vector3, instanceIndex?: number): void {\n this._applyToBodyOrInstances(body, (data) => this._b3._bx_Body_SetAngularVelocity(data.slot, angVel.x, angVel.y, angVel.z), instanceIndex);\n }\n\n public getAngularVelocityToRef(body: PhysicsBody, angVel: Vector3, instanceIndex?: number): void {\n this._b3._bx_Body_GetAngularVelocity(this._getPluginReference(body, instanceIndex).slot);\n const s = this._scratch();\n angVel.set(s[0], s[1], s[2]);\n }\n\n public getBodyGeometry(body: PhysicsBody): { positions: Float32Array | number[]; indices: Uint32Array | number[] } {\n const shape = body.shape?._pluginData as Box3DShapeData | undefined;\n if (!shape) {\n return { positions: [], indices: [] };\n }\n const vertexCount = this._b3._bx_ShapeDesc_BuildDebugGeometry(shape.slot);\n const indexCount = this._b3._bx_DebugIndexCount();\n if (!vertexCount || !indexCount) {\n return { positions: [], indices: [] };\n }\n const positions = new Float32Array(this._b3.HEAPF32.buffer, this._b3._bx_DebugPositionsPtr(), vertexCount * 3).slice();\n const indices = new Uint32Array(this._b3.HEAPU32.buffer, this._b3._bx_DebugIndicesPtr(), indexCount).slice();\n return { positions, indices };\n }\n\n public disposeBody(body: PhysicsBody): void {\n this.removeBody(body);\n body._pluginData = undefined;\n body._pluginDataInstances.length = 0;\n }\n\n public setCollisionCallbackEnabled(body: PhysicsBody, enabled: boolean, instanceIndex?: number): void {\n // Havok replaces the mask with all three collision events, or clears it\n this.setEventMask(body, enabled ? Box3DEventBits.ALL : 0, instanceIndex);\n }\n\n public setCollisionEndedCallbackEnabled(body: PhysicsBody, enabled: boolean, instanceIndex?: number): void {\n this._applyToBodyOrInstances(\n body,\n (data) => {\n data.eventMask = enabled ? data.eventMask | Box3DEventBits.COLLISION_FINISHED : data.eventMask & ~Box3DEventBits.COLLISION_FINISHED;\n this._applyEventFlags(data);\n },\n instanceIndex\n );\n }\n\n public getCollisionObservable(body: PhysicsBody, instanceIndex?: number): Observable<IPhysicsCollisionEvent> {\n const slot = this._getPluginReference(body, instanceIndex).slot;\n let observable = this._bodyCollisionObservable.get(slot);\n if (!observable) {\n observable = new Observable<IPhysicsCollisionEvent>();\n this._bodyCollisionObservable.set(slot, observable);\n }\n return observable;\n }\n\n public getCollisionEndedObservable(body: PhysicsBody, instanceIndex?: number): Observable<IBasePhysicsCollisionEvent> {\n const slot = this._getPluginReference(body, instanceIndex).slot;\n let observable = this._bodyCollisionEndedObservable.get(slot);\n if (!observable) {\n observable = new Observable<IBasePhysicsCollisionEvent>();\n this._bodyCollisionEndedObservable.set(slot, observable);\n }\n return observable;\n }\n\n public setGravityFactor(body: PhysicsBody, factor: number, instanceIndex?: number): void {\n this._applyToBodyOrInstances(body, (data) => this._b3._bx_Body_SetGravityScale(data.slot, factor), instanceIndex);\n }\n\n public getGravityFactor(body: PhysicsBody, instanceIndex?: number): number {\n return this._b3._bx_Body_GetGravityScale(this._getPluginReference(body, instanceIndex).slot);\n }\n\n // ----------------------------------------------------------------------------------------\n // shapes\n // ----------------------------------------------------------------------------------------\n\n private _registerShape(shape: PhysicsShape, slot: number, type: PhysicsShapeType): Box3DShapeData {\n if (!slot) {\n throw new Error(\"Box3DPlugin: shape creation failed (degenerate geometry?)\");\n }\n const data = new Box3DShapeData(slot, type);\n shape._pluginData = data;\n this._shapes[slot] = data;\n return data;\n }\n\n private _withFloatBuffer<T>(values: ArrayLike<number>, fn: (ptr: number) => T): T {\n const ptr = this._b3._malloc(values.length * 4);\n new Float32Array(this._b3.HEAPF32.buffer, ptr, values.length).set(values);\n try {\n return fn(ptr);\n } finally {\n this._b3._free(ptr);\n }\n }\n\n /** Copies bytes into the module for the length of `fn`; with no bytes, `fn` gets a null pointer. */\n private _withByteBuffer<T>(values: Nullable<Uint8Array>, fn: (ptr: number) => T): T {\n if (!values || values.length === 0) {\n return fn(0);\n }\n const ptr = this._b3._malloc(values.length);\n new Uint8Array(this._b3.HEAPU8.buffer, ptr, values.length).set(values);\n try {\n return fn(ptr);\n } finally {\n this._b3._free(ptr);\n }\n }\n\n private _withIntBuffer<T>(values: ArrayLike<number>, fn: (ptr: number) => T): T {\n const ptr = this._b3._malloc(values.length * 4);\n new Int32Array(this._b3.HEAP32.buffer, ptr, values.length).set(values);\n try {\n return fn(ptr);\n } finally {\n this._b3._free(ptr);\n }\n }\n\n private _createOptionsFromGroundMesh(options: PhysicsShapeParameters): void {\n const mesh = options.groundMesh;\n if (!mesh) {\n return;\n }\n const pos = mesh.getVerticesData(VertexBuffer.PositionKind) as FloatArray;\n const transform = mesh.computeWorldMatrix(true);\n const transformed: number[] = [];\n const p = TmpVectors.Vector3[0];\n for (let i = 0; i < pos.length; i += 3) {\n Vector3.FromArrayToRef(pos, i, p);\n Vector3.TransformCoordinatesToRef(p, transform, p);\n p.toArray(transformed, i);\n }\n const arraySize = ~~(Math.sqrt(transformed.length / 3) - 1);\n const boundingInfo = mesh.getBoundingInfo();\n const dim = Math.min(boundingInfo.boundingBox.extendSizeWorld.x, boundingInfo.boundingBox.extendSizeWorld.z);\n const minX = boundingInfo.boundingBox.minimumWorld.x;\n const minY = boundingInfo.boundingBox.minimumWorld.y;\n const minZ = boundingInfo.boundingBox.minimumWorld.z;\n const matrix = new Float32Array((arraySize + 1) * (arraySize + 1));\n const elementSize = (dim * 2) / arraySize;\n matrix.fill(minY);\n for (let i = 0; i < transformed.length; i += 3) {\n const x = Math.round((transformed[i + 0] - minX) / elementSize);\n const z = arraySize - Math.round((transformed[i + 2] - minZ) / elementSize);\n matrix[z * (arraySize + 1) + x] = transformed[i + 1] - minY;\n }\n options.numHeightFieldSamplesX = arraySize + 1;\n options.numHeightFieldSamplesZ = arraySize + 1;\n options.heightFieldSizeX = boundingInfo.boundingBox.extendSizeWorld.x * 2;\n options.heightFieldSizeZ = boundingInfo.boundingBox.extendSizeWorld.z * 2;\n options.heightFieldData = matrix;\n }\n\n public initShape(shape: PhysicsShape, type: PhysicsShapeType, options: PhysicsShapeParameters): void {\n const b3 = this._b3;\n const center = options.center ?? Vector3.ZeroReadOnly;\n const rotation = options.rotation ?? Quaternion.Identity();\n switch (type) {\n case PhysicsShapeType.SPHERE: {\n const radius = options.radius ?? 1;\n this._registerShape(shape, b3._bx_ShapeDesc_CreateSphere(center.x, center.y, center.z, radius), type);\n break;\n }\n case PhysicsShapeType.CAPSULE: {\n const a = options.pointA ?? Vector3.ZeroReadOnly;\n const b = options.pointB ?? Vector3.UpReadOnly;\n this._registerShape(shape, b3._bx_ShapeDesc_CreateCapsule(a.x, a.y, a.z, b.x, b.y, b.z, options.radius ?? 0), type);\n break;\n }\n case PhysicsShapeType.BOX: {\n const extents = options.extents ?? Vector3.OneReadOnly;\n this._registerShape(\n shape,\n b3._bx_ShapeDesc_CreateBox(extents.x * 0.5, extents.y * 0.5, extents.z * 0.5, center.x, center.y, center.z, rotation.x, rotation.y, rotation.z, rotation.w),\n type\n );\n break;\n }\n case PhysicsShapeType.CYLINDER: {\n const a = options.pointA ?? Vector3.ZeroReadOnly;\n const b = options.pointB ?? Vector3.UpReadOnly;\n const axis = b.subtract(a);\n const height = axis.length();\n const q = this._tmpQuat[0];\n if (height > 1e-6) {\n axis.scaleInPlace(1 / height);\n Quaternion.FromUnitVectorsToRef(Vector3.UpReadOnly, axis, q);\n } else {\n q.set(0, 0, 0, 1);\n }\n // Box3D's cylinder runs from 0 to height along its local Y, so it goes at pointA, not at the middle.\n this._registerShape(shape, b3._bx_ShapeDesc_CreateCylinder(height, options.radius ?? 0, 16, a.x, a.y, a.z, q.x, q.y, q.z, q.w), type);\n break;\n }\n case PhysicsShapeType.CONVEX_HULL:\n case PhysicsShapeType.MESH: {\n if (!options.mesh && options.positions) {\n this._initShapeFromPositions(shape, type, options.positions, options.positionIndices);\n break;\n }\n const mesh = options.mesh;\n if (!mesh) {\n throw new Error(\"No mesh provided to create physics shape.\");\n }\n const needIndices = type === PhysicsShapeType.MESH;\n const flipWinding = !mesh.getScene().useRightHandedSystem;\n const accum = new MeshGeometryAccumulator(needIndices, flipWinding);\n accum.addNodeMeshes(mesh, !!options.includeChildMeshes);\n if (type === PhysicsShapeType.CONVEX_HULL) {\n const slot = this._withFloatBuffer(accum.vertices, (ptr) => b3._bx_ShapeDesc_CreateHull(ptr, accum.vertexCount));\n this._registerShape(shape, slot, type);\n } else {\n const slot = this._withFloatBuffer(accum.vertices, (vptr) =>\n this._withIntBuffer(accum.indices, (iptr) => b3._bx_ShapeDesc_CreateMesh(vptr, accum.vertexCount, iptr, accum.triangleCount, 1, 1, 1, 0, 0))\n );\n this._registerShape(shape, slot, type);\n }\n break;\n }\n case PhysicsShapeType.HEIGHTFIELD: {\n if (options.groundMesh) {\n this._createOptionsFromGroundMesh(options);\n }\n const nx = options.numHeightFieldSamplesX;\n const nz = options.numHeightFieldSamplesZ;\n if (!nx || !nz || !options.heightFieldSizeX || !options.heightFieldSizeZ || !options.heightFieldData) {\n throw new Error(\"Missing required heightfield parameters\");\n }\n const heights = new Float32Array(nx * nz);\n for (let x = 0; x < nx; x++) {\n for (let z = 0; z < nz; z++) {\n // box3d rows run along z (index z * countX + x); Babylon data rows are flipped along z\n heights[z * nx + x] = options.heightFieldData[(nz - 1 - z) * nx + x];\n }\n }\n const scaleX = options.heightFieldSizeX / (nx - 1);\n const scaleZ = options.heightFieldSizeZ / (nz - 1);\n const cellsX = nx - 1;\n const cellsZ = nz - 1;\n const source = options.heightFieldMaterials;\n if (source && source.length !== cellsX * cellsZ) {\n throw new Error(`heightFieldMaterials needs ${cellsX * cellsZ} cells (${cellsX} \u00D7 ${cellsZ}), got ${source.length}`);\n }\n // Cells flip along z the same way the heights do.\n const materials = source ? new Uint8Array(cellsX * cellsZ) : null;\n if (source && materials) {\n for (let x = 0; x < cellsX; x++) {\n for (let z = 0; z < cellsZ; z++) {\n materials[z * cellsX + x] = source[(cellsZ - 1 - z) * cellsX + x];\n }\n }\n }\n const slot = this._withFloatBuffer(heights, (heightsPtr) =>\n this._withByteBuffer(materials, (materialsPtr) =>\n b3._bx_ShapeDesc_CreateHeightField(\n heightsPtr,\n materialsPtr,\n nx,\n nz,\n scaleX,\n 1,\n scaleZ,\n 0,\n -options.heightFieldSizeX! * 0.5,\n 0,\n -options.heightFieldSizeZ! * 0.5\n )\n )\n );\n this._registerShape(shape, slot, type);\n break;\n }\n case PhysicsShapeType.CONTAINER: {\n this._registerShape(shape, b3._bx_ShapeDesc_CreateContainer(), type);\n break;\n }\n default:\n throw new Error(\"Unsupported Shape Type.\");\n }\n }\n\n private _initShapeFromPositions(shape: PhysicsShape, type: PhysicsShapeType, positions: ArrayLike<number>, indices: ArrayLike<number> | undefined): void {\n const b3 = this._b3;\n if (positions.length % 3 !== 0) {\n throw new Error(`positions needs x, y, z triplets, got ${positions.length} numbers`);\n }\n const vertexCount = positions.length / 3;\n if (type === PhysicsShapeType.CONVEX_HULL) {\n this._registerShape(\n shape,\n this._withFloatBuffer(positions, (ptr) => b3._bx_ShapeDesc_CreateHull(ptr, vertexCount)),\n type\n );\n return;\n }\n if (!indices || indices.length % 3 !== 0) {\n throw new Error(\"a MESH shape from positions needs positionIndices, three per triangle\");\n }\n for (let i = 0; i < indices.length; i++) {\n if (indices[i] < 0 || indices[i] >= vertexCount || !Number.isInteger(indices[i])) {\n throw new Error(`positionIndices[${i}] is ${indices[i]}, but there are ${vertexCount} points`);\n }\n }\n this._registerShape(\n shape,\n this._withFloatBuffer(positions, (vptr) =>\n this._withIntBuffer(indices, (iptr) => b3._bx_ShapeDesc_CreateMesh(vptr, vertexCount, iptr, indices.length / 3, 1, 1, 1, 0, 0))\n ),\n type\n );\n }\n\n // Re-instantiates the shape on every body that uses it (or uses a container holding it). Only needed for geometry\n // and child changes; filters, materials and density are applied in place, see _syncShapeUsers.\n private _refreshShapeUsers(data: Box3DShapeData, visited = new Set<Box3DShapeData>()): void {\n if (visited.has(data)) {\n return;\n }\n visited.add(data);\n for (const body of data.users) {\n this._b3._bx_Body_SetShape(body.slot, data.slot);\n this._applyEventFlags(body);\n this._internalUpdateMassProperties(body);\n }\n for (const parent of data.parents) {\n this._refreshShapeUsers(parent, visited);\n }\n }\n\n /**\n * Pushes changed description properties into the Box3D shapes that are already on the bodies using this shape,\n * directly or through a container. Rebuilding them instead would drop their contacts and re-apply the body mass.\n */\n private _syncShapeUsers(data: Box3DShapeData, what: Box3DShapeSync, visited = new Set<Box3DShapeData>(), changed = data): void {\n if (visited.has(data)) {\n return;\n }\n visited.add(data);\n for (const body of data.users) {\n this._b3._bx_Body_SyncShapeDesc(body.slot, changed.slot, what);\n if (what & Box3DShapeSync.DENSITY) {\n this._internalUpdateMassProperties(body);\n }\n }\n for (const parent of data.parents) {\n this._syncShapeUsers(parent, what, visited, changed);\n }\n }\n\n public setShapeFilterMembershipMask(shape: PhysicsShape, membershipMask: number): void {\n const data = shape._pluginData as Box3DShapeData;\n const collide = this._b3._bx_ShapeDesc_GetMaskBits(data.slot);\n this._b3._bx_ShapeDesc_SetFilter(data.slot, membershipMask >>> 0, collide >>> 0);\n this._syncShapeUsers(data, Box3DShapeSync.FILTER);\n }\n\n public getShapeFilterMembershipMask(shape: PhysicsShape): number {\n return this._b3._bx_ShapeDesc_GetCategoryBits((shape._pluginData as Box3DShapeData).slot);\n }\n\n public setShapeFilterCollideMask(shape: PhysicsShape, collideMask: number): void {\n const data = shape._pluginData as Box3DShapeData;\n const membership = this._b3._bx_ShapeDesc_GetCategoryBits(data.slot);\n this._b3._bx_ShapeDesc_SetFilter(data.slot, membership >>> 0, collideMask >>> 0);\n this._syncShapeUsers(data, Box3DShapeSync.FILTER);\n }\n\n public getShapeFilterCollideMask(shape: PhysicsShape): number {\n return this._b3._bx_ShapeDesc_GetMaskBits((shape._pluginData as Box3DShapeData).slot);\n }\n\n public setMaterial(shape: PhysicsShape, material: PhysicsMaterial): void {\n const data = shape._pluginData as Box3DShapeData;\n data.material = material;\n this._b3._bx_ShapeDesc_SetMaterial(data.slot, material.friction ?? 0.5, material.restitution ?? 0);\n this._syncShapeUsers(data, Box3DShapeSync.MATERIAL);\n }\n\n public getMaterial(shape: PhysicsShape): PhysicsMaterial {\n const data = shape._pluginData as Box3DShapeData;\n return {\n friction: this._b3._bx_ShapeDesc_GetFriction(data.slot),\n staticFriction: data.material.staticFriction,\n restitution: this._b3._bx_ShapeDesc_GetRestitution(data.slot),\n frictionCombine: data.material.frictionCombine,\n restitutionCombine: data.material.restitutionCombine,\n };\n }\n\n public setDensity(shape: PhysicsShape, density: number): void {\n const data = shape._pluginData as Box3DShapeData;\n this._b3._bx_ShapeDesc_SetDensity(data.slot, density);\n this._syncShapeUsers(data, Box3DShapeSync.DENSITY);\n }\n\n public getDensity(shape: PhysicsShape): number {\n return this._b3._bx_ShapeDesc_GetDensity((shape._pluginData as Box3DShapeData).slot);\n }\n\n public addChild(shape: PhysicsShape, newChild: PhysicsShape, translation?: Vector3, rotation?: Quaternion, scale?: Vector3): void {\n const parent = shape._pluginData as Box3DShapeData;\n const child = newChild._pluginData as Box3DShapeData;\n const t = translation ?? Vector3.ZeroReadOnly;\n const r = rotation ?? Quaternion.Identity();\n const s = scale ?? Vector3.OneReadOnly;\n this._b3._bx_ShapeDesc_AddChild(parent.slot, child.slot, t.x, t.y, t.z, r.x, r.y, r.z, r.w, s.x, s.y, s.z);\n parent.children.push(child);\n child.parents.add(parent);\n this._refreshShapeUsers(parent);\n }\n\n public removeChild(shape: PhysicsShape, childIndex: number): void {\n const parent = shape._pluginData as Box3DShapeData;\n this._b3._bx_ShapeDesc_RemoveChild(parent.slot, childIndex);\n const [child] = parent.children.splice(childIndex, 1);\n if (child && !parent.children.includes(child)) {\n child.parents.delete(parent);\n }\n this._refreshShapeUsers(parent);\n }\n\n public getNumChildren(shape: PhysicsShape): number {\n return this._b3._bx_ShapeDesc_GetChildCount((shape._pluginData as Box3DShapeData).slot);\n }\n\n public getBoundingBox(shape: PhysicsShape): BoundingBox {\n this._b3._bx_ShapeDesc_GetAABB((shape._pluginData as Box3DShapeData).slot);\n const s = this._scratch();\n TmpVectors.Vector3[0].set(s[0], s[1], s[2]);\n TmpVectors.Vector3[1].set(s[3], s[4], s[5]);\n return new BoundingBox(TmpVectors.Vector3[0], TmpVectors.Vector3[1], Matrix.IdentityReadOnly);\n }\n\n public getBodyBoundingBox(body: PhysicsBody): BoundingBox {\n const data = this._getPluginReference(body);\n this._b3._bx_Body_GetAABB(data.slot);\n const s = this._scratch();\n TmpVectors.Vector3[0].set(s[0], s[1], s[2]);\n TmpVectors.Vector3[1].set(s[3], s[4], s[5]);\n return new BoundingBox(TmpVectors.Vector3[0], TmpVectors.Vector3[1], Matrix.IdentityReadOnly);\n }\n\n public disposeShape(shape: PhysicsShape): void {\n const data = shape._pluginData as Box3DShapeData;\n if (!data) {\n return;\n }\n for (const parent of data.parents) {\n const index = parent.children.indexOf(data);\n if (index >= 0) {\n parent.children.splice(index, 1);\n this._b3._bx_ShapeDesc_RemoveChild(parent.slot, index);\n }\n }\n for (const child of data.children) {\n child.parents.delete(data);\n }\n this._shapes[data.slot] = undefined;\n this._b3._bx_ShapeDesc_Destroy(data.slot);\n shape._pluginData = undefined;\n }\n\n public setTrigger(shape: PhysicsShape, isTrigger: boolean): void {\n const data = shape._pluginData as Box3DShapeData;\n this._b3._bx_ShapeDesc_SetSensor(data.slot, isTrigger ? 1 : 0);\n // Box3D decides at creation whether a shape is a sensor, so this one does need a rebuild\n this._refreshShapeUsers(data);\n }\n\n // ----------------------------------------------------------------------------------------\n // constraints\n // ----------------------------------------------------------------------------------------\n\n private _frameToBuffer(buffer: Float32Array, offset: number, pivot: Vector3, xAxis: Vector3, yAxis: Vector3, zAxis: Vector3): void {\n const m = TmpVectors.Matrix[0];\n Matrix.FromValuesToRef(xAxis.x, xAxis.y, xAxis.z, 0, yAxis.x, yAxis.y, yAxis.z, 0, zAxis.x, zAxis.y, zAxis.z, 0, 0, 0, 0, 1, m);\n const q = this._tmpQuat[2];\n Quaternion.FromRotationMatrixToRef(m, q);\n q.normalize();\n buffer[offset] = pivot.x;\n buffer[offset + 1] = pivot.y;\n buffer[offset + 2] = pivot.z;\n buffer[offset + 3] = q.x;\n buffer[offset + 4] = q.y;\n buffer[offset + 5] = q.z;\n buffer[offset + 6] = q.w;\n }\n\n private _buildFrames(cdata: Box3DConstraintData, constraint: PhysicsConstraint, bodyA: Box3DBodyData, bodyB: Box3DBodyData): void {\n const options = constraint.options;\n const pivotA = options.pivotA ?? Vector3.ZeroReadOnly;\n const pivotB = options.pivotB ?? Vector3.ZeroReadOnly;\n const axisA = (options.axisA ?? Vector3.RightReadOnly).normalizeToNew();\n const axisB = (options.axisB ?? Vector3.RightReadOnly).normalizeToNew();\n const perpA = options.perpAxisA ? options.perpAxisA.normalizeToNew() : axisA.getNormalToRef(new Vector3());\n const perpB = options.perpAxisB ? options.perpAxisB.normalizeToNew() : axisB.getNormalToRef(new Vector3());\n // Gram-Schmidt in case the user's perp axis is not exactly perpendicular\n perpA.subtractInPlace(axisA.scale(Vector3.Dot(axisA, perpA))).normalize();\n perpB.subtractInPlace(axisB.scale(Vector3.Dot(axisB, perpB))).normalize();\n const thirdA = Vector3.Cross(axisA, perpA);\n const thirdB = Vector3.Cross(axisB, perpB);\n\n if (!constraint._initOptions) {\n constraint._initOptions = {\n axisA: axisA.clone(),\n axisB: axisB.clone(),\n perpAxisA: perpA.clone(),\n perpAxisB: perpB.clone(),\n pivotA: pivotA.clone(),\n pivotB: pivotB.clone(),\n };\n }\n\n const frames = cdata.frames;\n if (cdata.plan) {\n // SIX_DOF: the constraint basis is Havok's [axis, perpAxis, axis x perpAxis]; the plan picks which of them\n // becomes Box3D's frame x, y and z (cyclic permutations, so the frames stay right handed)\n const basis = cdata.plan.basis;\n if (basis) {\n const basisA = [axisA, perpA, thirdA];\n const basisB = [axisB, perpB, thirdB];\n this._frameToBuffer(frames, 0, pivotA, basisA[basis[0]], basisA[basis[1]], basisA[basis[2]]);\n this._frameToBuffer(frames, 7, pivotB, basisB[basis[0]], basisB[basis[1]], basisB[basis[2]]);\n } else {\n frames.set([pivotA.x, pivotA.y, pivotA.z, 0, 0, 0, 1, pivotB.x, pivotB.y, pivotB.z, 0, 0, 0, 1]);\n }\n return;\n }\n switch (cdata.type) {\n case PhysicsConstraintType.HINGE:\n case PhysicsConstraintType.BALL_AND_SOCKET:\n // box3d: revolute rotates about the frame z axis, spherical cone is centered on frame A z\n this._frameToBuffer(frames, 0, pivotA, perpA, Vector3.Cross(axisA, perpA), axisA);\n this._frameToBuffer(frames, 7, pivotB, perpB, Vector3.Cross(axisB, perpB), axisB);\n break;\n case PhysicsConstraintType.PRISMATIC:\n case PhysicsConstraintType.SLIDER:\n // box3d: prismatic slides along the frame A x axis\n this._frameToBuffer(frames, 0, pivotA, axisA, perpA, thirdA);\n this._frameToBuffer(frames, 7, pivotB, axisB, perpB, thirdB);\n break;\n case PhysicsConstraintType.LOCK: {\n // weld the bodies in their current relative pose\n this._b3._bx_Body_GetTransform(bodyA.slot);\n let s = this._scratch();\n const qA = this._tmpQuat[0];\n qA.set(s[3], s[4], s[5], s[6]);\n this._b3._bx_Body_GetTransform(bodyB.slot);\n s = this._scratch();\n const qB = this._tmpQuat[1];\n qB.set(s[3], s[4], s[5], s[6]);\n // frameB rotation = inv(qB) * qA so both frames coincide in world space now\n const rel = qB.invert().multiply(qA).normalize();\n frames.set([pivotA.x, pivotA.y, pivotA.z, 0, 0, 0, 1, pivotB.x, pivotB.y, pivotB.z, rel.x, rel.y, rel.z, rel.w]);\n break;\n }\n default:\n frames.set([pivotA.x, pivotA.y, pivotA.z, 0, 0, 0, 1, pivotB.x, pivotB.y, pivotB.z, 0, 0, 0, 1]);\n break;\n }\n }\n\n private _createJoint(cdata: Box3DConstraintData, bodyA: Box3DBodyData, bodyB: Box3DBodyData): number {\n this._scratch().set(cdata.frames);\n const joint = this._b3._bx_CreateJoint(this._worldSlot, cdata.jointType, bodyA.slot, bodyB.slot, cdata.collisions ? 1 : 0, cdata.length);\n if (!joint) {\n Logger.Warn(\"Box3DPlugin: joint creation failed.\");\n return 0;\n }\n // A slider allows rotation about the axis in Havok. Box3D's prismatic locks it.\n this._applyAxisState(cdata, joint, bodyA, bodyB);\n return joint;\n }\n\n /** Reads Physics6DoFConstraint.limits into the axis table with Havok's rules. */\n private _readSixDofLimits(cdata: Box3DConstraintData, limits: ReadonlyArray<Physics6DoFLimit> | undefined): void {\n for (const limit of limits ?? []) {\n const state = this._axisState(cdata, limit.axis);\n if (limit.minLimit === 0 && limit.maxLimit === 0) {\n state.mode = PhysicsConstraintAxisLimitMode.LOCKED;\n state.min = 0;\n state.max = 0;\n } else if (limit.minLimit !== undefined || limit.maxLimit !== undefined) {\n // a missing side is unbounded\n state.mode = PhysicsConstraintAxisLimitMode.LIMITED;\n state.min = limit.minLimit ?? -Infinity;\n state.max = limit.maxLimit ?? Infinity;\n }\n state.stiffness = limit.stiffness ?? 0;\n state.damping = limit.damping ?? 0;\n }\n }\n\n /**\n * Maps the six axes of a SIX_DOF constraint onto one Box3D joint, following Havok's semantics: an axis that is not\n * listed is free, 0/0 is locked, anything else is limited. The constraint frame is [axis, perpAxis, axis x perpAxis];\n * ANGULAR_X rotates about axis, ANGULAR_Y about perpAxis and ANGULAR_Z about axis x perpAxis, all measured as the\n * rotation of the child frame relative to the parent frame (right handed, like Havok).\n * - all linear locked, all angular locked: weld\n * - all linear locked, one angular axis open: revolute about it, with its limits (one sided ranges work)\n * - all linear locked, two or three angular axes open: spherical, twist limits from ANGULAR_X and one symmetric\n * cone from ANGULAR_Y/Z (Box3D has no elliptical cone, the larger swing range is used)\n * - two linear locked, angular locked: prismatic along the open linear axis\n * - only LINEAR_DISTANCE constrained: distance joint (a spring when min == max and a stiffness is set)\n * - nothing constrained: filter joint (collision filtering only)\n * Anything else warns once and uses the closest of these.\n */\n private _planSixDof(cdata: Box3DConstraintData): ISixDofPlan {\n const Axis = PhysicsConstraintAxis;\n const Mode = PhysicsConstraintAxisLimitMode;\n const mode = (axis: PhysicsConstraintAxis) => cdata.axes.get(axis)?.mode ?? Mode.FREE;\n const range = (axis: PhysicsConstraintAxis): [number, number] => {\n const state = cdata.axes.get(axis)!;\n return state.mode === Mode.LOCKED ? [0, 0] : [Math.min(state.min, state.max), Math.max(state.min, state.max)];\n };\n const clamp = (value: number, limit: number) => Math.max(-limit, Math.min(limit, value));\n const maxAngle = 0.99 * Math.PI;\n // Box3D's B3_HUGE, keeps an unbounded side of a linear range out of the solver as a real number\n const maxLength = 100000;\n const plan: ISixDofPlan = {\n jointType: Box3DJointType.WELD,\n basis: [0, 1, 2],\n primaryAxis: null,\n coneAngle: -1,\n twist: null,\n limit: null,\n spring: false,\n stiffness: 0,\n damping: 0,\n angularStiffness: false,\n };\n for (const [axis, state] of cdata.axes) {\n if ((state.stiffness > 0 || state.damping > 0) && state.stiffness >= plan.stiffness) {\n plan.stiffness = state.stiffness;\n plan.damping = state.damping;\n plan.angularStiffness = axis === Axis.ANGULAR_X || axis === Axis.ANGULAR_Y || axis === Axis.ANGULAR_Z;\n }\n }\n const linear = [Axis.LINEAR_X, Axis.LINEAR_Y, Axis.LINEAR_Z];\n const angular = [Axis.ANGULAR_X, Axis.ANGULAR_Y, Axis.ANGULAR_Z];\n const linearLocked = linear.filter((a) => mode(a) === Mode.LOCKED).length;\n const linearFree = linear.filter((a) => mode(a) === Mode.FREE).length;\n const angularOpen = angular.filter((a) => mode(a) !== Mode.LOCKED);\n const angularFree = angular.filter((a) => mode(a) === Mode.FREE).length;\n const distanceMode = mode(Axis.LINEAR_DISTANCE);\n\n if (distanceMode !== Mode.FREE) {\n if (linearFree === 3 && angularFree === 3) {\n const [lower, upper] = range(Axis.LINEAR_DISTANCE);\n plan.jointType = Box3DJointType.DISTANCE;\n plan.basis = null;\n plan.primaryAxis = Axis.LINEAR_DISTANCE;\n plan.limit = [Math.min(Math.max(0, lower), maxLength), Math.min(Math.max(0, upper), maxLength)];\n plan.spring = plan.stiffness > 0 && Math.abs(upper - lower) < 1e-6 && isFinite(lower);\n return plan;\n }\n this._warnOnce(\"sixdof-distance\", \"SIX_DOF: LINEAR_DISTANCE combined with other constrained axes is not supported with Box3D, the distance limit is ignored.\");\n }\n\n // one open linear axis (free or limited) with the other two locked slides; see the prismatic case below\n let pointJoint = linearLocked === 3;\n if (!pointJoint && linearLocked !== 2 && linearFree === 0) {\n this._warnOnce(\"sixdof-linear-limited\", \"SIX_DOF: two or more limited linear axes are treated as locked with Box3D.\");\n pointJoint = true;\n }\n if (pointJoint) {\n if (angularOpen.length === 0) {\n return plan;\n }\n if (angularOpen.length === 1) {\n // Box3D revolutes rotate about frame z\n const axis = angularOpen[0];\n plan.jointType = Box3DJointType.REVOLUTE;\n plan.basis = [\n [1, 2, 0],\n [2, 0, 1],\n [0, 1, 2],\n ][angular.indexOf(axis)] as [number, number, number];\n plan.primaryAxis = axis;\n if (mode(axis) === Mode.LIMITED) {\n const [lower, upper] = range(axis);\n plan.limit = [clamp(lower, maxAngle), clamp(upper, maxAngle)];\n }\n return plan;\n }\n // spherical: cone centered on frame z (axis), twist about frame z\n plan.jointType = Box3DJointType.SPHERICAL;\n plan.basis = [1, 2, 0];\n if (mode(Axis.ANGULAR_X) !== Mode.FREE) {\n const [lower, upper] = range(Axis.ANGULAR_X);\n plan.twist = [clamp(lower, maxAngle), clamp(upper, maxAngle)];\n }\n const swingModes = [mode(Axis.ANGULAR_Y), mode(Axis.ANGULAR_Z)];\n if (swingModes.some((m) => m !== Mode.FREE)) {\n const extents: number[] = [];\n let asymmetric = false;\n for (const axis of [Axis.ANGULAR_Y, Axis.ANGULAR_Z]) {\n if (mode(axis) === Mode.FREE) {\n continue;\n }\n const [lower, upper] = range(axis);\n extents.push(Math.max(Math.abs(lower), Math.abs(upper)));\n asymmetric ||= Math.abs(lower + upper) > 1e-4;\n }\n const cone = Math.max(...extents);\n if (isFinite(cone)) {\n if (swingModes.includes(Mode.FREE) || Math.abs(extents[0] - extents[1]) > 1e-4 || asymmetric) {\n this._warnOnce(\n \"sixdof-cone\",\n \"SIX_DOF: Box3D has one symmetric swing cone, ANGULAR_Y and ANGULAR_Z use the larger of their ranges.\"\n );\n }\n if (cone > Math.PI / 2) {\n this._warnOnce(\"sixdof-cone-90\", \"SIX_DOF: Box3D cone limits are at most 90 degrees, larger swing ranges are clamped.\");\n }\n plan.coneAngle = Math.min(cone, Math.PI / 2);\n }\n }\n return plan;\n }\n\n if (linearLocked === 2) {\n // Box3D prismatics slide along frame x\n const slide = linear.find((a) => mode(a) !== Mode.LOCKED)!;\n plan.jointType = Box3DJointType.PRISMATIC;\n plan.basis = [\n [0, 1, 2],\n [1, 2, 0],\n [2, 0, 1],\n ][linear.indexOf(slide)] as [number, number, number];\n plan.primaryAxis = slide;\n if (mode(slide) === Mode.LIMITED) {\n const [lower, upper] = range(slide);\n plan.limit = [clamp(lower, maxLength), clamp(upper, maxLength)];\n }\n if (angularOpen.length) {\n this._warnOnce(\"sixdof-prismatic\", \"SIX_DOF: a sliding axis with rotation is not supported with Box3D, rotation is locked.\");\n }\n return plan;\n }\n\n plan.jointType = Box3DJointType.FILTER;\n plan.basis = null;\n if (linearFree !== 3 || angularFree !== 3) {\n this._warnOnce(\"sixdof-unsupported\", \"SIX_DOF: this combination of free and limited axes is not supported with Box3D, the bodies are left unconstrained.\");\n }\n return plan;\n }\n\n /** Box3D spring settings for a Havok spring constant and damping on a body pair. */\n private _springToHertz(stiffness: number, damping: number, angular: boolean, bodyA: Box3DBodyData, bodyB: Box3DBodyData): { hertz: number; dampingRatio: number } {\n // effective mass (or rotational inertia) of the pair, a static or animated body counts as infinitely heavy\n const inverse = (data: Box3DBodyData) => {\n if (data.motionType !== PhysicsMotionType.DYNAMIC) {\n return 0;\n }\n this._b3._bx_Body_GetMassData(data.slot);\n const s = this._scratch();\n const value = angular ? (s[4] + s[5] + s[6]) / 3 : s[0];\n return value > 0 ? 1 / value : 0;\n };\n const inverseSum = inverse(bodyA) + inverse(bodyB);\n const mass = inverseSum > 0 ? 1 / inverseSum : 1;\n const k = Math.max(stiffness, 0);\n return {\n hertz: Math.sqrt(k / mass) / (2 * Math.PI),\n dampingRatio: k > 0 ? damping / (2 * Math.sqrt(k * mass)) : 1,\n };\n }\n\n public initConstraint(constraint: PhysicsConstraint, body: PhysicsBody, childBody: PhysicsBody, instanceIndex?: number, childInstanceIndex?: number): void {\n const type = constraint.type;\n const options = constraint.options;\n if (!type || !options) {\n Logger.Warn(\"No constraint type or options. Constraint is invalid.\");\n return;\n }\n if ((body._pluginDataInstances.length > 0 && instanceIndex === undefined) || (childBody._pluginDataInstances.length > 0 && childInstanceIndex === undefined)) {\n Logger.Warn(\"Body is instanced but no instance index was specified. Constraint will not be applied.\");\n return;\n }\n const firstPair = !constraint._pluginData;\n const cdata: Box3DConstraintData = constraint._pluginData ?? new Box3DConstraintData();\n constraint._pluginData = cdata;\n cdata.type = type;\n if (firstPair) {\n cdata.collisions = !!options.collision;\n }\n switch (type) {\n case PhysicsConstraintType.BALL_AND_SOCKET:\n cdata.jointType = Box3DJointType.SPHERICAL;\n break;\n case PhysicsConstraintType.HINGE:\n cdata.jointType = Box3DJointType.REVOLUTE;\n break;\n case PhysicsConstraintType.PRISMATIC:\n case PhysicsConstraintType.SLIDER:\n cdata.jointType = Box3DJointType.PRISMATIC;\n break;\n case PhysicsConstraintType.LOCK:\n cdata.jointType = Box3DJointType.WELD;\n break;\n case PhysicsConstraintType.DISTANCE:\n cdata.jointType = Box3DJointType.DISTANCE;\n break;\n case PhysicsConstraintType.SIX_DOF:\n // later pairs of the same constraint share the axis table, including changes made since the first pair\n if (firstPair) {\n this._readSixDofLimits(cdata, (constraint as Physics6DoFConstraint).limits);\n }\n cdata.plan = this._planSixDof(cdata);\n cdata.jointType = cdata.plan.jointType;\n break;\n default:\n Logger.Warn(\"Box3DPlugin: unknown constraint type \" + type);\n return;\n }\n\n const bodyA = this._getPluginReference(body, instanceIndex);\n const bodyB = this._getPluginReference(childBody, childInstanceIndex);\n this._buildFrames(cdata, constraint, bodyA, bodyB);\n this._updateJointLength(cdata, options.maxDistance, bodyA, bodyB);\n // joints[i] belongs to pairs[i], 0 while the constraint is disabled or when creation failed\n const joint = cdata.enabled ? this._createJoint(cdata, bodyA, bodyB) : 0;\n cdata.joints.push(joint);\n cdata.pairs.push({ parent: body, parentIndex: instanceIndex ?? 0, child: childBody, childIndex: childInstanceIndex ?? 0, parentData: bodyA, childData: bodyB });\n }\n\n /** Length parameter passed to Box3D's distance joint at creation (the rest length of its spring). */\n private _updateJointLength(cdata: Box3DConstraintData, maxDistance: number | undefined, bodyA: Box3DBodyData, bodyB: Box3DBodyData): void {\n if (cdata.type === PhysicsConstraintType.DISTANCE) {\n cdata.length = maxDistance ?? 0;\n } else if (cdata.plan?.jointType === Box3DJointType.DISTANCE && cdata.plan.limit) {\n // a spring rests at its (single) limit; for a rope the rest length is unused, its limits do the work\n cdata.length = cdata.plan.limit[0];\n } else {\n return;\n }\n if (cdata.length <= 0) {\n // use the current distance between the world space pivots\n cdata.length = Math.max(0.01, this._currentPivotDistance(cdata, bodyA, bodyB));\n }\n }\n\n private _currentPivotDistance(cdata: Box3DConstraintData, bodyA: Box3DBodyData, bodyB: Box3DBodyData): number {\n const f = cdata.frames;\n const worldA = this._tmpVec3[0];\n const worldB = this._tmpVec3[1];\n this._b3._bx_Body_GetTransform(bodyA.slot);\n let s = this._scratch();\n this._tmpQuat[0].set(s[3], s[4], s[5], s[6]);\n worldA.set(f[0], f[1], f[2]).applyRotationQuaternionInPlace(this._tmpQuat[0]).addInPlaceFromFloats(s[0], s[1], s[2]);\n this._b3._bx_Body_GetTransform(bodyB.slot);\n s = this._scratch();\n this._tmpQuat[0].set(s[3], s[4], s[5], s[6]);\n worldB.set(f[7], f[8], f[9]).applyRotationQuaternionInPlace(this._tmpQuat[0]).addInPlaceFromFloats(s[0], s[1], s[2]);\n return Vector3.Distance(worldA, worldB);\n }\n\n public setEnabled(constraint: PhysicsConstraint, isEnabled: boolean): void {\n const cdata = constraint._pluginData as Box3DConstraintData;\n if (!cdata || cdata.enabled === isEnabled) {\n return;\n }\n cdata.enabled = isEnabled;\n // Box3D has no enable flag on joints: destroy them, or re-create them from the saved frames, plan and axis state.\n this._recreateJoints(cdata);\n }\n\n private _destroyJoint(joint: number): void {\n this._motorJoints.delete(joint);\n this._b3._bx_DestroyJoint(joint);\n }\n\n private _recreateJoints(cdata: Box3DConstraintData): void {\n for (let i = 0; i < cdata.pairs.length; i++) {\n if (cdata.joints[i]) {\n this._destroyJoint(cdata.joints[i]);\n }\n const pair = cdata.pairs[i];\n cdata.joints[i] = cdata.enabled && pair.parentData.slot && pair.childData.slot ? this._createJoint(cdata, pair.parentData, pair.childData) : 0;\n }\n }\n\n public getEnabled(constraint: PhysicsConstraint): boolean {\n return (constraint._pluginData as Box3DConstraintData)?.enabled ?? false;\n }\n\n public setCollisionsEnabled(constraint: PhysicsConstraint, isEnabled: boolean): void {\n const cdata = constraint._pluginData as Box3DConstraintData;\n cdata.collisions = isEnabled;\n for (const joint of cdata.joints) {\n if (joint) {\n this._b3._bx_Joint_SetCollideConnected(joint, isEnabled ? 1 : 0);\n }\n }\n }\n\n public getCollisionsEnabled(constraint: PhysicsConstraint): boolean {\n return (constraint._pluginData as Box3DConstraintData)?.collisions ?? false;\n }\n\n // The one axis box3d exposes for this constraint type.\n private _primaryAxis(cdata: Box3DConstraintData): Nullable<PhysicsConstraintAxis> {\n switch (cdata.type) {\n case PhysicsConstraintType.HINGE:\n return PhysicsConstraintAxis.ANGULAR_X;\n case PhysicsConstraintType.PRISMATIC:\n case PhysicsConstraintType.SLIDER:\n return PhysicsConstraintAxis.LINEAR_X;\n case PhysicsConstraintType.DISTANCE:\n return PhysicsConstraintAxis.LINEAR_DISTANCE;\n case PhysicsConstraintType.BALL_AND_SOCKET:\n return PhysicsConstraintAxis.ANGULAR_Y;\n case PhysicsConstraintType.SIX_DOF:\n return cdata.plan?.primaryAxis ?? null;\n default:\n return null;\n }\n }\n\n private _isAngularAxis(axis: PhysicsConstraintAxis): boolean {\n return axis === PhysicsConstraintAxis.ANGULAR_X || axis === PhysicsConstraintAxis.ANGULAR_Y || axis === PhysicsConstraintAxis.ANGULAR_Z;\n }\n\n private _isPrimaryAxis(cdata: Box3DConstraintData, axis: PhysicsConstraintAxis): boolean {\n if (cdata.type === PhysicsConstraintType.BALL_AND_SOCKET || cdata.plan?.jointType === Box3DJointType.SPHERICAL) {\n return this._isAngularAxis(axis);\n }\n return axis === this._primaryAxis(cdata);\n }\n\n private _axisState(cdata: Box3DConstraintData, axis: PhysicsConstraintAxis): IAxisState {\n let state = cdata.axes.get(axis);\n if (!state) {\n state = {\n mode: PhysicsConstraintAxisLimitMode.FREE,\n min: 0,\n max: 0,\n motor: PhysicsConstraintMotorType.NONE,\n target: 0,\n maxForce: 0,\n friction: 0,\n stiffness: 0,\n damping: 0,\n };\n cdata.axes.set(axis, state);\n }\n return state;\n }\n\n private _applyAxisState(cdata: Box3DConstraintData, joint: number, bodyA: Box3DBodyData, bodyB: Box3DBodyData): void {\n const b3 = this._b3;\n if (cdata.plan) {\n this._applySixDofPlan(cdata, joint, bodyA, bodyB);\n b3._bx_Joint_WakeBodies(joint);\n return;\n }\n const primary = this._primaryAxis(cdata);\n if (primary === null) {\n return;\n }\n for (const [axis, state] of cdata.axes) {\n if (!this._isPrimaryAxis(cdata, axis)) {\n continue;\n }\n if (cdata.type === PhysicsConstraintType.BALL_AND_SOCKET) {\n if (axis === PhysicsConstraintAxis.ANGULAR_X) {\n // twist about the primary axis (frame z in box3d)\n b3._bx_Joint_SetTwistLimits(joint, state.mode === PhysicsConstraintAxisLimitMode.FREE ? 0 : 1, state.min, state.max);\n continue;\n }\n }\n const limited = state.mode !== PhysicsConstraintAxisLimitMode.FREE;\n if (limited) {\n const min = state.mode === PhysicsConstraintAxisLimitMode.LOCKED ? 0 : state.min;\n const max = state.mode === PhysicsConstraintAxisLimitMode.LOCKED ? 0 : state.max;\n b3._bx_Joint_SetLimits(joint, min, max);\n }\n b3._bx_Joint_EnableLimit(joint, limited ? 1 : 0);\n if (cdata.type !== PhysicsConstraintType.BALL_AND_SOCKET) {\n this._applyMotor(joint, state);\n }\n }\n if (cdata.type === PhysicsConstraintType.BALL_AND_SOCKET) {\n this._applySphericalMotor(cdata, joint);\n }\n b3._bx_Joint_WakeBodies(joint);\n }\n\n /**\n * Box3D's spherical joint has one motor for the whole joint: a relative angular velocity, and one spring towards a\n * target rotation. Babylon has a motor per axis, so the three angular axes are combined into one target in the\n * joint frame (ANGULAR_X about frame z, ANGULAR_Y about frame x, ANGULAR_Z about frame y).\n */\n private _applySphericalMotor(cdata: Box3DConstraintData, joint: number): void {\n const b3 = this._b3;\n const twist = cdata.axes.get(PhysicsConstraintAxis.ANGULAR_X);\n const swing1 = cdata.axes.get(PhysicsConstraintAxis.ANGULAR_Y);\n const swing2 = cdata.axes.get(PhysicsConstraintAxis.ANGULAR_Z);\n const states = [twist, swing1, swing2];\n const velocity = (state?: IAxisState) => (state?.motor === PhysicsConstraintMotorType.VELOCITY ? state.target : 0);\n const hasVelocity = states.some((state) => state?.motor === PhysicsConstraintMotorType.VELOCITY);\n const hasPosition = states.some((state) => state?.motor === PhysicsConstraintMotorType.POSITION);\n const maxTorque = Math.max(...states.map((state) => (state?.motor === PhysicsConstraintMotorType.VELOCITY ? state.maxForce : 0)));\n b3._bx_Joint_SetSphericalMotor(joint, hasVelocity ? 1 : 0, velocity(swing1), velocity(swing2), velocity(twist), maxTorque);\n const target = velocity(swing1) !== 0 || velocity(swing2) !== 0 || velocity(twist) !== 0;\n if (hasVelocity && target) {\n // the world space target has to follow body A as it turns\n this._motorJoints.add(joint);\n } else {\n this._motorJoints.delete(joint);\n }\n b3._bx_Joint_EnableSpring(joint, hasPosition ? 1 : 0);\n if (hasPosition) {\n const position = (state?: IAxisState) => (state?.motor === PhysicsConstraintMotorType.POSITION ? state.target : 0);\n const rotation = this._tmpQuat[0];\n Quaternion.RotationYawPitchRollToRef(0, 0, position(twist), rotation);\n const swing = this._tmpQuat[1];\n Quaternion.RotationYawPitchRollToRef(position(swing2), position(swing1), 0, swing);\n rotation.multiplyInPlace(swing);\n b3._bx_Joint_SetSpring(joint, 5, 1);\n b3._bx_Joint_SetSphericalTarget(joint, rotation.x, rotation.y, rotation.z, rotation.w);\n }\n }\n\n private _applyMotor(joint: number, state: IAxisState): void {\n const b3 = this._b3;\n switch (state.motor) {\n case PhysicsConstraintMotorType.VELOCITY:\n b3._bx_Joint_EnableSpring(joint, 0);\n b3._bx_Joint_EnableMotor(joint, 1);\n b3._bx_Joint_SetMotorSpeed(joint, state.target);\n b3._bx_Joint_SetMaxMotorForce(joint, state.maxForce);\n break;\n case PhysicsConstraintMotorType.POSITION:\n b3._bx_Joint_EnableMotor(joint, 0);\n b3._bx_Joint_EnableSpring(joint, 1);\n b3._bx_Joint_SetSpring(joint, 5, 1);\n b3._bx_Joint_SetTarget(joint, state.target);\n break;\n default:\n b3._bx_Joint_EnableMotor(joint, 0);\n b3._bx_Joint_EnableSpring(joint, 0);\n break;\n }\n }\n\n /** Applies a SIX_DOF plan's limits, springs and motors to one of its Box3D joints. */\n private _applySixDofPlan(cdata: Box3DConstraintData, joint: number, bodyA: Box3DBodyData, bodyB: Box3DBodyData): void {\n const b3 = this._b3;\n const plan = cdata.plan!;\n switch (plan.jointType) {\n case Box3DJointType.SPHERICAL:\n if (plan.coneAngle >= 0) {\n b3._bx_Joint_SetLimits(joint, -plan.coneAngle, plan.coneAngle);\n }\n b3._bx_Joint_EnableLimit(joint, plan.coneAngle >= 0 ? 1 : 0);\n b3._bx_Joint_SetTwistLimits(joint, plan.twist ? 1 : 0, plan.twist ? plan.twist[0] : 0, plan.twist ? plan.twist[1] : 0);\n break;\n case Box3DJointType.REVOLUTE:\n case Box3DJointType.PRISMATIC:\n if (plan.limit) {\n b3._bx_Joint_SetLimits(joint, plan.limit[0], plan.limit[1]);\n }\n b3._bx_Joint_EnableLimit(joint, plan.limit ? 1 : 0);\n break;\n case Box3DJointType.DISTANCE:\n if (plan.spring) {\n const spring = this._springToHertz(plan.stiffness, plan.damping, false, bodyA, bodyB);\n b3._bx_Joint_EnableLimit(joint, 0);\n b3._bx_Joint_EnableSpring(joint, 1);\n b3._bx_Joint_SetSpring(joint, spring.hertz, spring.dampingRatio);\n b3._bx_Joint_SetTarget(joint, cdata.length);\n } else {\n // an enabled spring with 0 hertz leaves the length free between the limits (a rope); Box3D keeps\n // equal limits rigid\n b3._bx_Joint_SetLimits(joint, plan.limit![0], plan.limit![1]);\n b3._bx_Joint_EnableLimit(joint, 1);\n b3._bx_Joint_EnableSpring(joint, 1);\n b3._bx_Joint_SetSpring(joint, 0, 0);\n }\n break;\n default:\n break;\n }\n if (plan.stiffness > 0 && !plan.spring) {\n this._warnOnce(\n \"sixdof-softness\",\n \"SIX_DOF: limit stiffness and damping are approximated with Box3D's per joint constraint softness, which applies to every axis of the joint.\"\n );\n const soft = this._springToHertz(plan.stiffness, plan.damping, plan.angularStiffness, bodyA, bodyB);\n b3._bx_Joint_SetConstraintTuning(joint, soft.hertz, soft.dampingRatio);\n }\n if (plan.jointType === Box3DJointType.SPHERICAL) {\n this._applySphericalMotor(cdata, joint);\n } else if (plan.primaryAxis !== null && plan.jointType !== Box3DJointType.DISTANCE) {\n const state = cdata.axes.get(plan.primaryAxis);\n if (state) {\n this._applyMotor(joint, state);\n }\n }\n }\n\n private _setAxis(constraint: PhysicsConstraint, axis: PhysicsConstraintAxis, apply: (state: IAxisState) => void): void {\n const cdata = constraint._pluginData as Box3DConstraintData;\n if (!cdata) {\n return;\n }\n const state = this._axisState(cdata, axis);\n const previousMotor = { motor: state.motor, target: state.target, maxForce: state.maxForce };\n apply(state);\n if (cdata.plan) {\n // SIX_DOF: every axis shapes the plan. A different Box3D joint type or frame needs new joints.\n const plan = this._planSixDof(cdata);\n const rebuild = plan.jointType !== cdata.plan.jointType || String(plan.basis) !== String(cdata.plan.basis);\n cdata.plan = plan;\n cdata.jointType = plan.jointType;\n const motorChanged = previousMotor.motor !== state.motor || previousMotor.target !== state.target || previousMotor.maxForce !== state.maxForce;\n if (motorChanged && state.motor !== PhysicsConstraintMotorType.NONE && !this._isPrimaryAxis(cdata, axis)) {\n this._warnOnce(`axis-motor-${axis}`, `SIX_DOF: a motor on axis ${axis} has no effect with the Box3D joint this constraint maps to.`);\n }\n const first = cdata.pairs[0];\n if (first) {\n // the rest length of a distance joint follows its limits, whether or not the joint is rebuilt\n this._updateJointLength(cdata, constraint.options.maxDistance, first.parentData, first.childData);\n }\n if (rebuild) {\n if (first) {\n this._buildFrames(cdata, constraint, first.parentData, first.childData);\n }\n this._recreateJoints(cdata);\n return;\n }\n } else if (!this._isPrimaryAxis(cdata, axis)) {\n this._warnOnce(`axis-${cdata.type}-${axis}`, `axis ${axis} is not configurable on constraint type ${cdata.type} with Box3D; the value is stored but has no effect.`);\n return;\n }\n for (let i = 0; i < cdata.joints.length; i++) {\n if (cdata.joints[i]) {\n this._applyAxisState(cdata, cdata.joints[i], cdata.pairs[i].parentData, cdata.pairs[i].childData);\n }\n }\n }\n\n public setAxisFriction(constraint: PhysicsConstraint, axis: PhysicsConstraintAxis, friction: number): void {\n const cdata = constraint._pluginData as Box3DConstraintData;\n if (cdata) {\n this._axisState(cdata, axis).friction = friction;\n }\n }\n\n public getAxisFriction(constraint: PhysicsConstraint, axis: PhysicsConstraintAxis): Nullable<number> {\n return (constraint._pluginData as Box3DConstraintData)?.axes.get(axis)?.friction ?? null;\n }\n\n public setAxisMode(constraint: PhysicsConstraint, axis: PhysicsConstraintAxis, limitMode: PhysicsConstraintAxisLimitMode): void {\n this._setAxis(constraint, axis, (state) => (state.mode = limitMode));\n }\n\n public getAxisMode(constraint: PhysicsConstraint, axis: PhysicsConstraintAxis): Nullable<PhysicsConstraintAxisLimitMode> {\n return (constraint._pluginData as Box3DConstraintData)?.axes.get(axis)?.mode ?? null;\n }\n\n public setAxisMinLimit(constraint: PhysicsConstraint, axis: PhysicsConstraintAxis, minLimit: number): void {\n this._setAxis(constraint, axis, (state) => {\n state.min = minLimit;\n if (state.mode === PhysicsConstraintAxisLimitMode.FREE) {\n state.mode = PhysicsConstraintAxisLimitMode.LIMITED;\n }\n });\n }\n\n public getAxisMinLimit(constraint: PhysicsConstraint, axis: PhysicsConstraintAxis): Nullable<number> {\n return (constraint._pluginData as Box3DConstraintData)?.axes.get(axis)?.min ?? null;\n }\n\n public setAxisMaxLimit(constraint: PhysicsConstraint, axis: PhysicsConstraintAxis, limit: number): void {\n this._setAxis(constraint, axis, (state) => {\n state.max = limit;\n if (state.mode === PhysicsConstraintAxisLimitMode.FREE) {\n state.mode = PhysicsConstraintAxisLimitMode.LIMITED;\n }\n });\n }\n\n public getAxisMaxLimit(constraint: PhysicsConstraint, axis: PhysicsConstraintAxis): Nullable<number> {\n return (constraint._pluginData as Box3DConstraintData)?.axes.get(axis)?.max ?? null;\n }\n\n public setAxisMotorType(constraint: PhysicsConstraint, axis: PhysicsConstraintAxis, motorType: PhysicsConstraintMotorType): void {\n this._setAxis(constraint, axis, (state) => (state.motor = motorType));\n }\n\n public getAxisMotorType(constraint: PhysicsConstraint, axis: PhysicsConstraintAxis): Nullable<PhysicsConstraintMotorType> {\n return (constraint._pluginData as Box3DConstraintData)?.axes.get(axis)?.motor ?? null;\n }\n\n public setAxisMotorTarget(constraint: PhysicsConstraint, axis: PhysicsConstraintAxis, target: number): void {\n this._setAxis(constraint, axis, (state) => (state.target = target));\n }\n\n public getAxisMotorTarget(constraint: PhysicsConstraint, axis: PhysicsConstraintAxis): Nullable<number> {\n return (constraint._pluginData as Box3DConstraintData)?.axes.get(axis)?.target ?? null;\n }\n\n public setAxisMotorMaxForce(constraint: PhysicsConstraint, axis: PhysicsConstraintAxis, maxForce: number): void {\n this._setAxis(constraint, axis, (state) => (state.maxForce = maxForce));\n }\n\n public getAxisMotorMaxForce(constraint: PhysicsConstraint, axis: PhysicsConstraintAxis): Nullable<number> {\n return (constraint._pluginData as Box3DConstraintData)?.axes.get(axis)?.maxForce ?? null;\n }\n\n public disposeConstraint(constraint: PhysicsConstraint): void {\n const cdata = constraint._pluginData as Box3DConstraintData;\n if (!cdata) {\n return;\n }\n for (const joint of cdata.joints) {\n if (joint) {\n this._destroyJoint(joint);\n }\n }\n cdata.joints.length = 0;\n cdata.pairs.length = 0;\n }\n\n public getBodiesUsingConstraint(constraint: PhysicsConstraint): ConstrainedBodyPair[] {\n const cdata = constraint._pluginData as Box3DConstraintData;\n if (!cdata) {\n return [];\n }\n return cdata.pairs.map((p) => ({ parentBody: p.parent, parentBodyIndex: p.parentIndex, childBody: p.child, childBodyIndex: p.childIndex }));\n }\n\n public addConstraint(body: PhysicsBody, childBody: PhysicsBody, constraint: PhysicsConstraint, instanceIndex?: number, childInstanceIndex?: number): void {\n this.initConstraint(constraint, body, childBody, instanceIndex, childInstanceIndex);\n }\n\n // ----------------------------------------------------------------------------------------\n // Box3D specific extras\n // ----------------------------------------------------------------------------------------\n\n /**\n * Applies a radial impulse to every shape within the radius, like a grenade.\n * @param position world position of the explosion\n * @param radius radius of the explosion\n * @param impulsePerArea impulse per surface area of the affected shapes\n * @param falloff distance beyond the radius over which the impulse fades to zero\n */\n public explode(position: Vector3, radius: number, impulsePerArea: number, falloff = 0): void {\n this._b3._bx_World_Explode(this._worldSlot, position.x, position.y, position.z, radius, falloff, impulsePerArea);\n }\n\n /**\n * Box2D style collision group. Shapes sharing a negative group never collide with each other,\n * shapes sharing a positive group always collide. Zero means no group.\n * @param shape the shape\n * @param groupIndex the group index\n */\n public setShapeFilterGroup(shape: PhysicsShape, groupIndex: number): void {\n const data = shape._pluginData as Box3DShapeData;\n this._b3._bx_ShapeDesc_SetGroup(data.slot, groupIndex | 0);\n this._syncShapeUsers(data, Box3DShapeSync.FILTER);\n }\n\n /**\n * Rolling resistance for spheres and capsules (Babylon materials have no equivalent).\n * @param shape the shape\n * @param value resistance, typically in [0, 1]\n */\n public setShapeRollingResistance(shape: PhysicsShape, value: number): void {\n const data = shape._pluginData as Box3DShapeData;\n this._b3._bx_ShapeDesc_SetRollingResistance(data.slot, value);\n this._syncShapeUsers(data, Box3DShapeSync.MATERIAL);\n }\n\n /**\n * Lets a body spin faster than the default angular speed cap (wheels).\n * @param body the body\n * @param allow true to allow fast rotation\n * @param instanceIndex optional thin instance index\n */\n public setAllowFastRotation(body: PhysicsBody, allow: boolean, instanceIndex?: number): void {\n this._applyToBodyOrInstances(body, (data) => this._b3._bx_Body_AllowFastRotation(data.slot, allow ? 1 : 0), instanceIndex);\n }\n\n /**\n * Creates a Box3D wheel joint between a chassis and a wheel body.\n * @param chassis the chassis body\n * @param wheel the wheel body\n * @param options wheel joint options\n * @returns a handle used to drive and steer the wheel\n */\n public createWheelJoint(chassis: PhysicsBody, wheel: PhysicsBody, options: IBox3DWheelJointOptions): Box3DWheelJoint {\n const s = this._scratch();\n const axisA = (options.axisA ?? Vector3.UpReadOnly).normalizeToNew();\n const axleA = (options.axleA ?? Vector3.Forward()).normalizeToNew();\n // suspension travels along frame A x, the wheel spins about frame z\n axleA.subtractInPlace(axisA.scale(Vector3.Dot(axisA, axleA))).normalize();\n this._frameToBuffer(s, 0, options.pivotA, axisA, Vector3.Cross(axleA, axisA), axleA);\n // frame B must coincide with frame A in world space at creation, compute it from the current poses\n const pivotB = options.pivotB ?? Vector3.ZeroReadOnly;\n s[7] = pivotB.x;\n s[8] = pivotB.y;\n s[9] = pivotB.z;\n const chassisData = this._getPluginReference(chassis);\n const wheelData = this._getPluginReference(wheel);\n this._b3._bx_ComputeAlignedFrameB(chassisData.slot, wheelData.slot);\n const susp = options.suspensionLimits ?? [-0.2, 0.2];\n const steer = options.steeringLimits ?? [-Math.PI / 4, Math.PI / 4];\n s.set(\n [\n 1,\n options.suspensionHertz ?? 4,\n options.suspensionDampingRatio ?? 0.7,\n 1,\n susp[0],\n susp[1],\n options.enableSpinMotor ? 1 : 0,\n options.maxSpinTorque ?? 5,\n 0,\n options.enableSteering ? 1 : 0,\n options.steeringHertz ?? 10,\n options.steeringDampingRatio ?? 0.7,\n 0,\n options.maxSteeringTorque ?? 5,\n 1,\n steer[0],\n steer[1],\n ],\n 14\n );\n const slot = this._b3._bx_CreateJoint(this._worldSlot, Box3DJointType.WHEEL, chassisData.slot, wheelData.slot, 0, 0);\n if (!slot) {\n throw new Error(\"Box3DPlugin: wheel joint creation failed\");\n }\n return new Box3DWheelJoint(this, slot);\n }\n\n /**\n * Creates a Box3D parallel joint: a spring that keeps a local axis of bodyB parallel to an axis\n * of bodyA, for example to keep a vehicle upright without locking its motion.\n * @param bodyA first body (often a static body)\n * @param bodyB body to align\n * @param axisA axis in bodyA local space\n * @param axisB axis in bodyB local space\n * @param hertz spring stiffness\n * @param dampingRatio spring damping\n * @param maxTorque maximum spring torque\n * @returns a joint slot that can be passed to disposeExtraJoint\n */\n public createParallelJoint(bodyA: PhysicsBody, bodyB: PhysicsBody, axisA: Vector3, axisB: Vector3, hertz = 1, dampingRatio = 1, maxTorque = 3.4e38): number {\n const s = this._scratch();\n const a = axisA.normalizeToNew();\n const pa = a.getNormalToRef(new Vector3());\n this._frameToBuffer(s, 0, Vector3.ZeroReadOnly, pa, Vector3.Cross(a, pa), a);\n const b = axisB.normalizeToNew();\n const pb = b.getNormalToRef(new Vector3());\n this._frameToBuffer(s, 7, Vector3.ZeroReadOnly, pb, Vector3.Cross(b, pb), b);\n s.set([hertz, dampingRatio, maxTorque], 14);\n return this._b3._bx_CreateJoint(this._worldSlot, Box3DJointType.PARALLEL, this._getPluginReference(bodyA).slot, this._getPluginReference(bodyB).slot, 1, 0);\n }\n\n /**\n * Destroys a joint created by createParallelJoint.\n * @param slot the joint slot\n */\n public disposeExtraJoint(slot: number): void {\n this._destroyExtraJoint(slot);\n }\n\n /**\n * @internal\n */\n public _destroyExtraJoint(slot: number): void {\n if (slot) {\n this._destroyJoint(slot);\n }\n }\n\n /**\n * @internal\n */\n public _wheelCall(fn: string, slot: number, ...args: number[]): void {\n if (slot) {\n this._b3[fn](slot, ...args);\n }\n }\n\n // ----------------------------------------------------------------------------------------\n // queries\n // ----------------------------------------------------------------------------------------\n\n public raycast(from: Vector3, to: Vector3, result: PhysicsRaycastResult | Array<PhysicsRaycastResult>, query?: IRaycastQuery): void {\n const results = Array.isArray(result) ? result : [result];\n for (const r of results) {\n r.reset(from, to);\n }\n const membership = (query?.membership ?? ~0) >>> 0;\n const collideWith = (query?.collideWith ?? ~0) >>> 0;\n const ignore = query?.ignoreBody ? ((query.ignoreBody._pluginData as Box3DBodyData)?.slot ?? 0) : 0;\n const closestOnly = results.length === 1;\n const count = this._b3._bx_World_CastRay(\n this._worldSlot,\n from.x,\n from.y,\n from.z,\n to.x - from.x,\n to.y - from.y,\n to.z - from.z,\n membership,\n collideWith,\n ignore,\n query?.shouldHitTriggers ? 1 : 0,\n closestOnly ? 1 : 0\n );\n if (count <= 0) {\n return;\n }\n const buffer = new Float32Array(this._b3.HEAPF32.buffer, this._b3._bx_RayHitsPtr(), count * RAY_STRIDE);\n const hits: number[] = [];\n for (let i = 0; i < count; i++) {\n hits.push(i);\n }\n hits.sort((a, b) => buffer[a * RAY_STRIDE + 6] - buffer[b * RAY_STRIDE + 6]);\n if (!results.length) {\n for (let i = 0; i < count; i++) {\n const r = new PhysicsRaycastResult();\n r.reset(from, to);\n results.push(r);\n }\n }\n const n = Math.min(count, results.length);\n for (let i = 0; i < n; i++) {\n const o = hits[i] * RAY_STRIDE;\n const r = results[i];\n const bodyRef = this._bodies[buffer[o + 7]];\n r.body = bodyRef?.body;\n r.bodyIndex = bodyRef?.index;\n r.shape = bodyRef?.body.shape ?? undefined;\n r.setHitData({ x: buffer[o + 3], y: buffer[o + 4], z: buffer[o + 5] }, { x: buffer[o], y: buffer[o + 1], z: buffer[o + 2] }, buffer[o + 9]);\n r.calculateHitDistance();\n }\n }\n\n // ----------------------------------------------------------------------------------------\n // events\n // ----------------------------------------------------------------------------------------\n\n /**\n * Copies `count` event records out of wasm memory and resolves their two body slots (at `slotOffset`) to the plugin's\n * body references. Observers run user code that can grow the wasm memory, which detaches every HEAPF32 view (creating\n * bodies or shapes, casting rays), or dispose bodies and hand their slots to new ones, so nothing is read from wasm\n * memory or the slot table once the first observer has been called.\n */\n private _readEvents(pointer: number, count: number, stride: number, slotOffset: number) {\n const records = new Float32Array(this._b3.HEAPF32.buffer, pointer, count * stride).slice();\n const refs: Array<{ body: PhysicsBody; index: number; data: Box3DBodyData } | undefined> = new Array(count * 2);\n for (let i = 0; i < count; i++) {\n refs[i * 2] = this._bodies[records[i * stride + slotOffset]];\n refs[i * 2 + 1] = this._bodies[records[i * stride + slotOffset + 1]];\n }\n return { records, refs };\n }\n\n private _notifyCollisions(): void {\n const count = this._b3._bx_World_GetContactEvents(this._worldSlot);\n if (!count) {\n return;\n }\n const { records: buffer, refs } = this._readEvents(this._b3._bx_ContactEventsPtr(), count, CONTACT_STRIDE, 3);\n for (let i = 0; i < count; i++) {\n const o = i * CONTACT_STRIDE;\n const kind = buffer[o];\n const refA = refs[i * 2];\n const refB = refs[i * 2 + 1];\n // a body disposed by an earlier observer has slot 0, its remaining events are dropped\n if (!refA || !refB || !refA.data.slot || !refB.data.slot) {\n continue;\n }\n // like Havok, an event is reported when either body asked for that event type\n const bit = kind === 0 ? Box3DEventBits.COLLISION_STARTED : kind === 1 ? Box3DEventBits.COLLISION_FINISHED : Box3DEventBits.COLLISION_CONTINUED;\n if (((refA.data.eventMask | refB.data.eventMask) & bit) === 0) {\n continue;\n }\n if (kind === 1) {\n const ended: IBasePhysicsCollisionEvent = {\n collider: refA.body,\n colliderIndex: refA.index,\n collidedAgainst: refB.body,\n collidedAgainstIndex: refB.index,\n type: PhysicsEventType.COLLISION_FINISHED,\n };\n this.onCollisionEndedObservable.notifyObservers(ended);\n this._bodyCollisionEndedObservable.get(refA.data.slot)?.notifyObservers(ended);\n const endedB = this._bodyCollisionEndedObservable.get(refB.data.slot);\n if (endedB) {\n endedB.notifyObservers({ ...ended, collider: refB.body, colliderIndex: refB.index, collidedAgainst: refA.body, collidedAgainstIndex: refA.index });\n }\n continue;\n }\n // begin events carry the manifold point, normal and normal impulse, hit events the approach speed\n const type = kind === 0 ? PhysicsEventType.COLLISION_STARTED : PhysicsEventType.COLLISION_CONTINUED;\n const point = new Vector3(buffer[o + 5], buffer[o + 6], buffer[o + 7]);\n const normal = new Vector3(buffer[o + 8], buffer[o + 9], buffer[o + 10]);\n const info: IPhysicsCollisionEvent = {\n collider: refA.body,\n colliderIndex: refA.index,\n collidedAgainst: refB.body,\n collidedAgainstIndex: refB.index,\n type,\n point,\n normal,\n distance: 0,\n impulse: buffer[o + 11],\n };\n this.onCollisionObservable.notifyObservers(info);\n if (this._bodyCollisionObservable.size) {\n this._bodyCollisionObservable.get(refA.data.slot)?.notifyObservers(info);\n const obsB = this._bodyCollisionObservable.get(refB.data.slot);\n if (obsB) {\n obsB.notifyObservers({\n ...info,\n collider: refB.body,\n colliderIndex: refB.index,\n collidedAgainst: refA.body,\n collidedAgainstIndex: refA.index,\n normal: normal ? normal.negate() : null,\n });\n }\n }\n }\n }\n\n private _notifyTriggers(): void {\n const count = this._b3._bx_World_GetSensorEvents(this._worldSlot);\n if (!count || !this.onTriggerCollisionObservable.hasObservers()) {\n return;\n }\n const { records: buffer, refs } = this._readEvents(this._b3._bx_SensorEventsPtr(), count, SENSOR_STRIDE, 3);\n for (let i = 0; i < count; i++) {\n const o = i * SENSOR_STRIDE;\n const refA = refs[i * 2];\n const refB = refs[i * 2 + 1];\n if (!refA || !refB || !refA.data.slot || !refB.data.slot) {\n continue;\n }\n this.onTriggerCollisionObservable.notifyObservers({\n collider: refA.body,\n colliderIndex: refA.index,\n collidedAgainst: refB.body,\n collidedAgainstIndex: refB.index,\n type: buffer[o] === 0 ? PhysicsEventType.TRIGGER_ENTERED : PhysicsEventType.TRIGGER_EXITED,\n });\n }\n }\n\n public dispose(): void {\n this._motorJoints.clear();\n this.onCollisionObservable.clear();\n this.onCollisionEndedObservable.clear();\n this.onTriggerCollisionObservable.clear();\n this._bodyCollisionObservable.clear();\n this._bodyCollisionEndedObservable.clear();\n for (const shape of this._shapes) {\n if (shape) {\n this._b3._bx_ShapeDesc_Destroy(shape.slot);\n }\n }\n this._shapes.length = 0;\n this._bodies.length = 0;\n if (this._worldSlot) {\n this._b3._bx_DestroyWorld(this._worldSlot);\n this._worldSlot = 0;\n }\n }\n}\n", "// Picks a Box3D module: the plain one, or the threaded one when the page can run it.\n//\n// The package ships two builds of the same wasm. The default is single threaded and runs anywhere. The threaded build\n// lets box3d spread a world step over its own worker threads, which is several times faster on a heavy scene, but it\n// needs SharedArrayBuffer, and browsers only hand that out on a cross origin isolated page:\n//\n// Cross-Origin-Opener-Policy: same-origin\n// Cross-Origin-Embedder-Policy: require-corp\n//\n// The threaded module is imported dynamically, so a page that never asks for threads never downloads it.\n\nimport type { Box3DModule, Box3DModuleOptions } from \"babylon-box3d/wasm\";\n\n/** Options for LoadBox3D: the emscripten module options plus which build to load. */\nexport interface ILoadBox3DOptions extends Box3DModuleOptions {\n /**\n * Which build to load. false (the default) is the single threaded one. true is the threaded one, and fails\n * loudly if the page is not cross origin isolated. \"auto\" uses the threaded build where it can and falls back\n * to the single threaded one everywhere else.\n */\n threads?: boolean | \"auto\";\n}\n\n/**\n * Whether the threaded Box3D build can run here: the page has to be cross origin isolated, which is what gives it\n * SharedArrayBuffer. Node and bundler test environments have SharedArrayBuffer without the flag.\n * @returns true when LoadBox3D({ threads: true }) will work\n */\nexport function CanUseBox3DThreads(): boolean {\n if (typeof SharedArrayBuffer === \"undefined\") {\n return false;\n }\n const isolated = (globalThis as { crossOriginIsolated?: boolean }).crossOriginIsolated;\n return isolated === undefined || isolated;\n}\n\n/**\n * Loads the Box3D WebAssembly module, optionally the threaded build.\n * The result goes to the plugin as it always does; ask the plugin for workers to put them to use:\n * ```ts\n * const box3d = await LoadBox3D({ threads: \"auto\" });\n * scene.enablePhysics(gravity, new Box3DPlugin(true, box3d, { workerCount: \"auto\" }));\n * ```\n * @param options which build to load, plus the emscripten options (locateFile and friends)\n * @returns the resolved module\n */\nexport async function LoadBox3D(options: ILoadBox3DOptions = {}): Promise<Box3DModule> {\n const { threads = false, ...moduleOptions } = options;\n const wantsThreads = threads === \"auto\" ? CanUseBox3DThreads() : threads;\n if (wantsThreads) {\n if (threads === true && !CanUseBox3DThreads()) {\n throw new Error(\n \"babylon-box3d: the threaded build needs SharedArrayBuffer, which this page does not have. Serve it with the \" +\n \"Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Embedder-Policy: require-corp headers, or use \" +\n 'LoadBox3D({ threads: \"auto\" }) to fall back to the single threaded build.'\n );\n }\n const threaded = await import(\"babylon-box3d/wasm/threads\");\n return threaded.default(moduleOptions);\n }\n const plain = await import(\"babylon-box3d/wasm\");\n return plain.default(moduleOptions);\n}\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": ["k", "data"]
|
|
7
7
|
}
|