Physics

@three-blocks/proMain ThreadSharedArrayBufferWorker
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
configoptionalPhysicsConfig
Configuration options
Default 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
workerInstanceoptionalWorker
Optional custom worker instance
Default is null.
Returns
Promise<void>

start#

start() : Promise<string>

Start the physics simulation.

Returns
Promise<string> — Status message

stop#

stop() : Promise<string>

Stop the physics simulation.

Returns
Promise<string> — Status message

pause#

pause()

Pause the physics simulation.

resume#

resume()

Resume the physics simulation.

getView#

getView(bodyType : string) : Object

Get 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
bodyTypestring
Body type: 'dynamic', 'kinematic', 'static', 'zone', 'camera', 'physic'
Returns
Object — Buffer view

getDynamicBody#

getDynamicBody(index : number) : Object|null

Get a dynamic body by index.

Parameters
indexnumber
The body index
Returns
Object | null — Body state or null if not found

getKinematicBody#

getKinematicBody(index : number) : Object|null

Get a kinematic body by index.

Parameters
indexnumber
The body index
Returns
Object | null — Body state or null if not found

bindInput#

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
inputControllerInputController
The input controller instance
optionsoptionalObject
Binding options
Default is {}.
  • playerIndexoptionalnumber
    Which dynamic body receives input
    Default is 0.
  • jumpVelocityoptionalnumber
    Jump velocity to apply
    Default is 8.

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
eventTargetstring
Event target identifier (e.g., "static_collide_0", "enter_zone_0", "leave_zone_0")
handlerfunction
Event handler function

off#

off(eventTarget : string, handler : function)

Remove an event listener.

Parameters
eventTargetstring
Event target identifier
handlerfunction
Event handler function

addStaticBody#

addStaticBody(mesh : THREE.Object3D, options : Object) : Promise<number>

Add a static body and store mesh reference for debug visualization.

Parameters
meshTHREE.Object3D
The mesh to create a static body for
optionsObject
Static body options
Returns
Promise<number> — Static body index

addBody#

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
typestring
Body type: 'static', 'dynamic', 'kinematic', 'zone'
meshOrCollideBoxTHREE.Mesh | THREE.Group | THREE.InstancedMesh | THREE.BatchedMesh
The mesh, group, instanced mesh, or batched mesh to create physics for
propertiesoptionalObject
Physics properties (friction, mass, etc.)
Default is {}.
bodyPropsoptionalObject
Body properties (capsuleRadius, capsuleLength, initialPosition, etc.)
Default is {}.
optionsoptionalObject
Optional settings (hitbox, debugMaterial, side, instanceMatrixIndex, sourceGeometry, customGeometryToBVHScript)
Default is {}.
Returns
Promise<Object> — The body API object containing index, collideBox, entity, and type

addBodies#

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
typestring
Body type: 'static', 'dynamic', 'kinematic', 'zone'
bodiesConfigArray<Object>
Array of body configurations.
meshTHREE.Mesh | THREE.Group

See nested options below.

  • meshTHREE.Mesh | THREE.Group
    The mesh to create physics for.
  • propertiesoptionalObject
    Physics properties (friction, mass, etc.).
  • bodyPropsoptionalObject
    Body properties (capsuleRadius, etc.).
  • optionsoptionalObject
    Optional settings (hitbox, side, etc.).
Returns
Promise<Array<Object>> — Array of body API objects.

getStaticMesh#

getStaticMesh(index : number) : THREE.Object3D|null

Get the mesh associated with a static body index.

Parameters
indexnumber
Static body index
Returns
THREE.Object3D | null — The mesh or null

dispose#

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
configObject
Configuration options.
  • marginoptionalnumber
    Padding in world units around the frustum.
    Default is 10.
  • enabledoptionalboolean
    Enable/disable frustum culling.
    Default is true.
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
configObject
Configuration options.
  • cellSizeoptionalnumber
    Size of each grid cell in world units.
    Default is 4.
  • enabledoptionalboolean
    Enable/disable spatial grid.
    Default is true.
Returns
Promise<string> — Confirmation message from worker.

Static Methods

isSupported#

isSupported() : boolean

Check if SharedArrayBuffer is supported.

Returns
boolean — True if supported