3d-tiles-colliders-rapier
v0.1.0
Published
LOD-aware physics sync — dynamically creates and destroys Rapier trimesh colliders from streaming 3D Tiles
Maintainers
Readme
3d-tiles-colliders-rapier
LOD-aware physics sync — dynamically creates and destroys Rapier trimesh colliders from streaming 3D Tiles.
As tiles load and unload during LOD transitions, this library keeps the physics world in sync: new tile meshes get trimesh colliders, unloaded tiles have their colliders removed. No manual tracking required.
Install
npm install 3d-tiles-colliders-rapierPeer dependencies: three (>=0.150) and @dimforge/rapier3d-compat (>=0.12).
For the React hook, also install @react-three/fiber and @react-three/rapier.
Usage
Vanilla Three.js + Rapier
import RAPIER from "@dimforge/rapier3d-compat";
import { TileColliderSync } from "3d-tiles-colliders-rapier";
await RAPIER.init();
const world = new RAPIER.World({ x: 0, y: -9.81, z: 0 });
const sync = new TileColliderSync(RAPIER, world, {
friction: 1.5,
callbacks: {
onFirstSync: (count) => console.log(`${count} tile colliders created`),
},
});
// In your render loop, after tilesRenderer.update():
function animate() {
tilesRenderer.update();
sync.sync(tilesRenderer.group);
world.step();
requestAnimationFrame(animate);
}
// On cleanup:
sync.dispose();React Three Fiber
import { useTileColliders } from "3d-tiles-colliders-rapier/react";
function TilePhysics({ tilesGroup }) {
useTileColliders(tilesGroup, {
friction: 1.5,
callbacks: {
onFirstSync: (count) => console.log(`${count} tile colliders created`),
},
});
return null;
}API
TileColliderSync
The core class. Framework-agnostic (Three.js + Rapier only).
new TileColliderSync(rapier, world, options?)| Option | Type | Default | Description |
| ------------- | --------------------------- | ------- | ------------------------------------ |
| friction | number | 1.0 | Friction for all trimesh colliders |
| restitution | number | 0.0 | Bounciness for all trimesh colliders |
| callbacks | TileColliderSyncCallbacks | {} | Lifecycle callbacks |
Methods:
sync(group: Object3D)— Diff meshes and update colliders. Call once per frame.dispose()— Remove all colliders from the Rapier world.colliderCount— Number of active colliders.
useTileColliders (React hook)
R3F wrapper around TileColliderSync. Requires @react-three/rapier context.
useTileColliders(group: Object3D | null, options?)Accepts the same options as TileColliderSync plus:
| Option | Type | Default | Description |
| ---------- | -------- | ------- | ------------------------------------- |
| priority | number | 0 | useFrame priority for the sync pass |
How it works
Each frame, sync() traverses the tile group and collects visible meshes by UUID. It diffs this set against the previous frame:
- New meshes — Extracts vertex positions, bakes the world matrix, builds a
Float32Arrayof world-space vertices and aUint32Arrayindex buffer, then creates a Rapier trimesh collider. - Removed meshes — Deletes the corresponding collider from the Rapier world.
This handles LOD transitions transparently: when the tile renderer swaps a parent tile for higher-detail children (or vice versa), the physics colliders update to match.
License
MIT
