Physics
new Physics(config : PhysicsConfig)Physics - Main Thread Physics Engine Interface
High-level API for initializing and controlling the physics engine from the main thread. Manages SharedArrayBuffer creation, worker lifecycle, and provides convenient accessors for physics state.
Architecture
The Physics acts as a facade between the main thread and the physics worker:
SharedArrayBuffer Communication
All physics state is synchronized via typed arrays backed by SharedArrayBuffer. Use Buffer-Backed Objects (BBO) for property-like access:
// Read player position (lock-free, no RPC)
const player = physics.getView('dynamic')[0];
mesh.position.set(player.positionx, player.positiony, player.positionz);
// Read camera state
const cam = physics.cameraState;
camera.position.set(cam.positionx, cam.positiony, cam.positionz);
Basic Usage
import { Physics } from '@three-blocks/pro';
import * as THREE from 'three/webgpu';
const physics = new Physics({ gravity: -9.81, debug: false });
await physics.init();
// Add bodies via worker API
await physics.workerApi.addDynamicBody(mesh, options);
await physics.workerApi.addStaticBody(mesh, options);
// Start simulation
await physics.start();
// Game loop - read state directly from SharedArrayBuffer
function animate() {
const player = physics.getView('dynamic')[0];
playerMesh.position.set(player.positionx, player.positiony, player.positionz);
renderer.render(scene, camera);
}
Events
// Listen for collision events
physics.on('static_collide_0', (data) => {
console.log('Player collided with static body');
});
// Listen for zone triggers
physics.on('enter_zone_5', (data) => {
console.log('Player entered zone 5');
});
physics.on('leave_zone_5', (data) => {
console.log('Player left zone 5');
});
Constructor Parameters
configoptionalPhysicsConfigDefault is
{}.See also
- {@link physicsState} - Worker-side state container
- {@link PhysicsController} - High-level player controller
Example
┌─────────────────────────────────────────────────────────────────┐
│ MAIN THREAD │
│ ┌─────────────┐ ┌─────────────┐ ┌───────────────────┐ │
│ │ Your Game │───▶│ Physics │◀──▶│ SharedArrayBuffer │ │
│ │ Code │ │ (facade) │ │ Views │ │
│ └─────────────┘ └──────┬──────┘ └───────────────────┘ │
│ │ Comlink RPC │
└────────────────────────────┼────────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────────┐
│ PHYSICS WORKER (60 FPS) │
│ - Collision detection (BVH raycasting) │
│ - Character controller (capsule-based) │
│ - Camera system (3rd person, 1st person, bird view) │
│ - Trigger zones and events │
└─────────────────────────────────────────────────────────────────┘
Properties
# .physicsState :
Get the global physics state view.
# .cameraState :
Get the camera state view.
# .player :
Get the main player body state (dynamic body at index 0).
Shorthand for getView('dynamic')[0].
# .sharedKinematic :
Get the shared kinematic body views array. Used by KinematicAnimator to write animation values to SharedArrayBuffer.
# .syncView :
Get the sync buffer view for Atomics-based synchronization.
# .physicsApi :
Get the physics API for direct calls. Returns a proxied API that automatically registers static meshes for debug visualization.
# .api :
Alias for physicsApi - provides cleaner access via physics.api
# .workerApi :
Legacy alias for physicsApi - for backwards compatibility
# .staticMeshes :
Get all static meshes array.
Methods
init#
init(workerInstance : Worker) : Promise<void>Initialize the physics engine. Creates SharedArrayBuffers and initializes the worker.
Parameters
workerInstanceoptionalWorkerDefault is
null.Returns
Promise<void>start#
start() : Promise<string>Start the physics simulation.
Returns
Promise<string> — Status messagestop#
stop() : Promise<string>Stop the physics simulation.
Returns
Promise<string> — Status messagepause#
pause()Pause the physics simulation.
resume#
resume()Resume the physics simulation.
getView#
getView(bodyType : string) : ObjectGet raw buffer view for a body type.
Advanced: Most users should use player, getDynamicBody(),
or getKinematicBody() instead. This method is for power users
who need direct SharedArrayBuffer access.
Parameters
bodyTypestringReturns
Object — Buffer viewgetDynamicBody#
getDynamicBody(index : number) : Object|nullGet a dynamic body by index.
Parameters
indexnumberReturns
Object | null — Body state or null if not foundgetKinematicBody#
getKinematicBody(index : number) : Object|nullGet a kinematic body by index.
Parameters
indexnumberReturns
Object | null — Body state or null if not foundbindInput#
bindInput(inputController : InputController, options : Object)Bind an InputController to automatically sync input to physics. Call this once after init() and after adding the player body.
This handles all internal view registration, so you don't need to manually call setPhysic() or access views directly.
Parameters
inputControllerInputControlleroptionsoptionalObjectDefault is
{}.playerIndexoptionalnumberWhich dynamic body receives input
Default is0.jumpVelocityoptionalnumberJump velocity to apply
Default is8.
updateInput#
updateInput()Sync input state to physics each frame. Call this in your render loop when using bindInput().
on#
on(eventTarget : string, handler : function)Add an event listener for physics events.
Parameters
eventTargetstringhandlerfunctionoff#
off(eventTarget : string, handler : function)Remove an event listener.
Parameters
eventTargetstringhandlerfunctionaddStaticBody#
addStaticBody(mesh : THREE.Object3D, options : Object) : Promise<number>Add a static body and store mesh reference for debug visualization.
Parameters
meshTHREE.Object3DoptionsObjectReturns
Promise<number> — Static body indexaddBody#
addBody(type : string, meshOrCollideBox : THREE.Mesh|THREE.Group|THREE.InstancedMesh|THREE.BatchedMesh, properties : Object, bodyProps : Object, options : Object) : Promise<Object>Add a physics body from a mesh. Convenience method that wraps the addBody helper.
Parameters
typestringmeshOrCollideBoxTHREE.Mesh | THREE.Group | THREE.InstancedMesh | THREE.BatchedMeshpropertiesoptionalObjectDefault is
{}.bodyPropsoptionalObjectDefault is
{}.optionsoptionalObjectDefault is
{}.Returns
Promise<Object> — The body API object containing index, collideBox, entity, and typeaddBodies#
addBodies(type : string, bodiesConfig : Array<Object>) : Promise<Array<Object>>Add multiple physics bodies in a single batch operation. Significantly faster than calling addBody multiple times for many meshes.
Parameters
typestringbodiesConfigArray<Object>meshTHREE.Mesh | THREE.GroupSee nested options below.
meshTHREE.Mesh|THREE.GroupThe mesh to create physics for.propertiesoptionalObjectPhysics properties (friction, mass, etc.).bodyPropsoptionalObjectBody properties (capsuleRadius, etc.).optionsoptionalObjectOptional settings (hitbox, side, etc.).
Returns
Promise<Array<Object>> — Array of body API objects.getStaticMesh#
getStaticMesh(index : number) : THREE.Object3D|nullGet the mesh associated with a static body index.
Parameters
indexnumberReturns
THREE.Object3D | null — The mesh or nulldispose#
dispose()Dispose of the physics engine and free resources.
setFrustumConfig#
setFrustumConfig(config : Object) : Promise<string>Configure the physics frustum culling system. Frustum culling optimizes collision detection by only testing bodies visible in the camera frustum. Near/far planes are inherited from the active camera automatically.
Parameters
configObjectmarginoptionalnumberPadding in world units around the frustum.
Default is10.enabledoptionalbooleanEnable/disable frustum culling.
Default istrue.
Returns
Promise<string> — Confirmation message from worker.setSpatialGridConfig#
setSpatialGridConfig(config : Object) : Promise<string>Configure the physics spatial grid optimization. Spatial grid provides finer-grained spatial filtering after frustum culling, reducing the number of bodies tested for collision based on proximity.
Parameters
configObjectcellSizeoptionalnumberSize of each grid cell in world units.
Default is4.enabledoptionalbooleanEnable/disable spatial grid.
Default istrue.
Returns
Promise<string> — Confirmation message from worker.Static Methods
isSupported#
isSupported() : booleanCheck if SharedArrayBuffer is supported.
Returns
boolean — True if supported