import { Vector3 } from "@babylonjs/core/Maths/math.vector"; import { Observable } from "@babylonjs/core/Misc/observable"; import { Scene } from "@babylonjs/core/scene"; import type { DeepImmutable } from "@babylonjs/core/types"; import { WasmSpinlock } from "../../../Misc/wasmSpinlock"; import type { IBulletWasmInstance } from "../bulletWasmInstance"; import type { Constraint } from "../constraint"; import type { RigidBody } from "../rigidBody"; import type { RigidBodyBundle } from "../rigidBodyBundle"; import type { IPhysicsRuntime } from "./IPhysicsRuntime"; import type { IRigidBodyBundleImpl } from "./IRigidBodyBundleImpl"; import type { IRigidBodyImpl } from "./IRigidBodyImpl"; import { PhysicsRuntimeEvaluationType } from "./physicsRuntimeEvaluationType"; /** * Options for creating a MultiPhysicsRuntime */ export interface IMultiPhysicsRuntimeCreationOptions { /** * Whether to allow dynamic rigid body shadows (default: false) * * If disabled, rigid body shadow creation will be allowed only if the rigid body physics mode is set to Static or Kinematic */ allowDynamicShadow?: boolean; /** * Whether to preserve the back buffer for the motion state (default: false) */ preserveBackBuffer?: boolean; } /** * MultiPhysicsRuntime handles the multiple physics simulations and provides an interface for managing rigid bodies and constraints * * It is responsible for evaluating the physics world and synchronizing the state of rigid bodies */ export declare class MultiPhysicsRuntime implements IPhysicsRuntime { /** * Observable that is triggered when the physics world is synchronized * in this observable callback scope, ensure that the physics world is not being evaluated */ readonly onSyncObservable: Observable; /** * Observable that is triggered on each physics tick * in this observable callback scope, physics may be evaluating on the worker thread when evaluation type is Buffered */ readonly onTickObservable: Observable; /** * @internal */ readonly wasmInstance: IBulletWasmInstance; /** * Spinlock for the physics runtime to synchronize access to the physics world state * @internal */ readonly lock: WasmSpinlock; private readonly _inner; private readonly _physicsWorld; private _scene; private _afterAnimationsBinded; private _evaluationType; private _usingWasmBackBuffer; private _rigidBodyUsingBackBuffer; private readonly _preserveBackBuffer; private _dynamicShadowCount; /** * Whether to use delta time for world step (default: true) * * If true, the delta time will be calculated based on the scene's delta time * If false, the `MultiPhysicsRuntime.timeStep` property will be used as the fixed time step */ useDeltaForWorldStep: boolean; /** * The time step for the physics simulation (default: 1/60) * * This value is used when `useDeltaForWorldStep` is set to false */ timeStep: number; /** * The maximum number of substeps for the physics simulation (default: 10) * * This value is used to control the maximum number of substeps taken in a single frame */ maxSubSteps: number; /** * The fixed time step for the physics simulation (default: 1/60) */ fixedTimeStep: number; private readonly _rigidBodyMap; private readonly _rigidBodyBundleMap; /** * Creates a new physics runtime * @param wasmInstance The Bullet WASM instance * @param options The creation options */ constructor(wasmInstance: IBulletWasmInstance, options?: IMultiPhysicsRuntimeCreationOptions); /** * Disposes the physics runtime */ dispose(): void; /** @internal */ get ptr(): number; private _nullCheck; /** @internal */ createRigidBodyImpl(): IRigidBodyImpl; /** @internal */ createRigidBodyBundleImpl(bundle: RigidBodyBundle): IRigidBodyBundleImpl; /** * Registers the physics runtime with the given scene * * This method binds the `afterAnimations` method to the scene's `onAfterAnimationsObservable` event * * You can manually call `afterAnimations` if you want to control the timing of the physics simulation * @param scene The scene to register with */ register(scene: Scene): void; /** * Unregisters the physics runtime from the scene */ unregister(): void; /** * Steps the physics simulation and synchronizes the state of rigid bodies * * In most cases, you do not need to call this method manually, * Instead, you can use the `register` method to bind it to the scene's `onAfterAnimationsObservable` event * @param deltaTime The time delta in milliseconds */ afterAnimations(deltaTime: number): void; /** * Animation evaluation type */ get evaluationType(): PhysicsRuntimeEvaluationType; set evaluationType(value: PhysicsRuntimeEvaluationType); private readonly _gravity; /** * Gets the gravity vector of the physics world (default: (0, -10, 0)) * @returns The gravity vector */ getGravityToRef(result: Vector3): Vector3; /** * Sets the gravity vector of the physics world * * If the runtime evaluation type is Buffered, the gravity will be set after waiting for the lock * @param gravity The gravity vector */ setGravity(gravity: DeepImmutable): void; /** * Adds a rigid body to the physics world * * If the world is not existing, it will be created * * If the runtime evaluation type is Buffered, the rigid body will be added after waiting for the lock * @param rigidBody The rigid body to add * @param worldId The ID of the world to add the rigid body to * @returns True if the rigid body was added successfully, false otherwise */ addRigidBody(rigidBody: RigidBody, worldId: number): boolean; /** * Removes a rigid body from the physics world * * If there are no more rigid bodies in the world, the world will be destroyed automatically * * If the runtime evaluation type is Buffered, the rigid body will be removed after waiting for the lock * @param rigidBody The rigid body to remove * @param worldId The ID of the world to remove the rigid body from * @returns True if the rigid body was removed successfully, false otherwise */ removeRigidBody(rigidBody: RigidBody, worldId: number): boolean; /** * Adds a rigid body bundle to the physics world * * If the world is not existing, it will be created * * If the runtime evaluation type is Buffered, the rigid body bundle will be added after waiting for the lock * @param rigidBodyBundle The rigid body bundle to add * @param worldId The ID of the world to add the rigid body bundle to * @returns True if the rigid body bundle was added successfully, false otherwise */ addRigidBodyBundle(rigidBodyBundle: RigidBodyBundle, worldId: number): boolean; /** * Removes a rigid body bundle from the physics world * * If there are no more rigid body bundles in the world, the world will be destroyed automatically * * If the runtime evaluation type is Buffered, the rigid body bundle will be removed after waiting for the lock * @param rigidBodyBundle The rigid body bundle to remove * @param worldId The ID of the world to remove the rigid body bundle from * @returns True if the rigid body bundle was removed successfully, false otherwise */ removeRigidBodyBundle(rigidBodyBundle: RigidBodyBundle, worldId: number): boolean; /** * Adds a rigid body to all worlds * * rigid body physics mode must be Static or Kinematic * * If the runtime evaluation type is Buffered, the rigid body will be added after waiting for the lock * @param rigidBody The rigid body to add * @returns True if the rigid body was added successfully, false otherwise */ addRigidBodyToGlobal(rigidBody: RigidBody): boolean; /** * Removes a rigid body from all worlds * * This method does not remove the rigid body that is added with `MultiPhysicsRuntime.addRigidBody` * * Only the rigid body that is added with `MultiPhysicsRuntime.addRigidBodyToGlobal` will be removed * * If there are no more rigid bodies in the world, the world will be destroyed automatically * * If the runtime evaluation type is Buffered, the rigid body will be removed after waiting for the lock * @param rigidBody The rigid body to remove * @returns True if the rigid body was removed successfully, false otherwise */ removeRigidBodyFromGlobal(rigidBody: RigidBody): boolean; /** * Adds a rigid body bundle to all worlds * * rigid body bundle physics mode must be Static or Kinematic * * If the runtime evaluation type is Buffered, the rigid body bundle will be added after waiting for the lock * @param rigidBodyBundle The rigid body bundle to add * @returns True if the rigid body bundle was added successfully, false otherwise */ addRigidBodyBundleToGlobal(rigidBodyBundle: RigidBodyBundle): boolean; /** * Removes a rigid body bundle from all worlds * * This method does not remove the rigid body bundle that is added with `MultiPhysicsRuntime.addRigidBodyBundle` * * Only the rigid body bundle that is added with `MultiPhysicsRuntime.addRigidBodyBundleToGlobal` will be removed * * If there are no more rigid body bundles in the world, the world will be destroyed automatically * * If the runtime evaluation type is Buffered, the rigid body bundle will be removed after waiting for the lock * @param rigidBodyBundle The rigid body bundle to remove * @returns True if the rigid body bundle was removed successfully, false otherwise */ removeRigidBodyBundleFromGlobal(rigidBodyBundle: RigidBodyBundle): boolean; /** * Adds a rigid body shadow to the physics world * * In case of Dynamic physics mode, Rigid body firstly needs to be added to the other world * * The worldId must be not equal to the worldId of the rigid body * * Rigid body shadow allows the rigid body to be added to multiple worlds * * If the runtime evaluation type is Buffered, the rigid body shadow will be added after waiting for the lock * @param rigidBody The rigid body to add * @param worldId The ID of the world to add the rigid body as shadow * @returns True if the rigid body shadow was added successfully, false otherwise */ addRigidBodyShadow(rigidBody: RigidBody, worldId: number): boolean; /** * Removes a rigid body shadow from the physics world * * If the runtime evaluation type is Buffered, the rigid body shadow will be removed after waiting for the lock * @param rigidBody The rigid body to remove * @param worldId The ID of the world to remove the rigid body shadow from * @returns True if the rigid body shadow was removed successfully, false otherwise */ removeRigidBodyShadow(rigidBody: RigidBody, worldId: number): boolean; /** * Adds a rigid body bundle shadow to the physics world * * In case of Dynamic physics mode, Rigid body bundle firstly needs to be added to the other world * * and the worldId must be not equal to the worldId of the rigid body bundle * * Rigid body bundle shadow allows the rigid body bundle to be added to multiple worlds * * If the runtime evaluation type is Buffered, the rigid body bundle shadow will be added after waiting for the lock * @param rigidBodyBundle The rigid body bundle to add * @param worldId The ID of the world to add the rigid body bundle as shadow * @returns True if the rigid body bundle shadow was added successfully, false otherwise */ addRigidBodyBundleShadow(rigidBodyBundle: RigidBodyBundle, worldId: number): boolean; /** * Removes a rigid body bundle shadow from the physics world * * If the runtime evaluation type is Buffered, the rigid body bundle shadow will be removed after waiting for the lock * @param rigidBodyBundle The rigid body bundle to remove * @param worldId The ID of the world to remove the rigid body bundle shadow from * @returns True if the rigid body bundle shadow was removed successfully, false otherwise */ removeRigidBodyBundleShadow(rigidBodyBundle: RigidBodyBundle, worldId: number): boolean; /** * Gets the rigid body reference count map */ get rigidBodyReferenceCountMap(): ReadonlyMap; /** * Gets the rigid body bundle reference count map */ get rigidBodyBundleReferenceCountMap(): ReadonlyMap; /** * Adds a constraint to the physics world * * Constraint worldId must be equal to the worldId of the connected rigid bodies * * If the runtime evaluation type is Buffered, the constraint will be added after waiting for the lock * @param constraint The constraint to add * @param worldId The ID of the world to add the constraint to * @param disableCollisionsBetweenLinkedBodies Whether to disable collisions between the linked bodies * @returns True if the constraint was added successfully, false otherwise */ addConstraint(constraint: Constraint, worldId: number, disableCollisionsBetweenLinkedBodies: boolean): boolean; /** * Removes a constraint from the physics world * * If the runtime evaluation type is Buffered, the constraint will be removed after waiting for the lock * @param constraint The constraint to remove * @param worldId The ID of the world to remove the constraint from * @returns True if the constraint was removed successfully, false otherwise */ removeConstraint(constraint: Constraint, worldId: number): boolean; }