{"_id":"3d-tiles-colliders-rapier","name":"3d-tiles-colliders-rapier","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"3d-tiles-colliders-rapier","version":"0.1.0","description":"LOD-aware physics sync — dynamically creates and destroys Rapier trimesh colliders from streaming 3D Tiles","type":"module","main":"dist/index.cjs","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js","require":"./dist/react.cjs"}},"scripts":{"build":"tsup","dev":"tsup --watch","typecheck":"tsc --noEmit"},"keywords":["3d-tiles","rapier","physics","colliders","trimesh","threejs","3d-tiles-renderer","lod","terrain"],"repository":{"type":"git","url":"git+https://github.com/prmarshall/3d-tiles-colliders-rapier.git"},"license":"MIT","peerDependencies":{"@dimforge/rapier3d-compat":">=0.12.0","three":">=0.150.0"},"peerDependenciesMeta":{"@react-three/fiber":{"optional":true},"@react-three/rapier":{"optional":true},"react":{"optional":true}},"devDependencies":{"@dimforge/rapier3d-compat":"^0.14.0","@react-three/fiber":"^9.0.0","@react-three/rapier":"^2.2.0","@types/react":"^19.0.0","@types/three":"^0.170.0","react":"^19.0.0","three":"^0.170.0","tsup":"^8.0.0","typescript":"^5.6.0"},"_id":"3d-tiles-colliders-rapier@0.1.0","gitHead":"5115b12c5e72551c48b2827e154499ec3072e0cd","bugs":{"url":"https://github.com/prmarshall/3d-tiles-colliders-rapier/issues"},"homepage":"https://github.com/prmarshall/3d-tiles-colliders-rapier#readme","_nodeVersion":"20.20.0","_npmVersion":"10.8.2","dist":{"integrity":"sha512-Hka/k9v0QbyFISNW0gW3Pj8WXRQLXq5HNNzXMRJxuF2Zt6fvUUgGiyA8jN5TGBJoiGfALbDQnlj2BxdjdkMVpA==","shasum":"ffe54235e6cfaaad1089bd98194208f9098e655c","tarball":"https://registry.npmjs.org/3d-tiles-colliders-rapier/-/3d-tiles-colliders-rapier-0.1.0.tgz","fileCount":14,"unpackedSize":68232,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/3d-tiles-colliders-rapier@0.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDTU2yvEdckRTaM7ia2tnjSIQ3zsB0lnIseTIqBWXiRuQIhAKCThS66TJ0V2KXay4LmhpdSs5h6C8IiKfaRqHZjB7fP"}]},"_npmUser":{"name":"prmarshall","email":"prmarshall1990@gmail.com"},"directories":{},"maintainers":[{"name":"prmarshall","email":"prmarshall1990@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/3d-tiles-colliders-rapier_0.1.0_1772675685883_0.5612122397960875"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-05T01:54:45.827Z","0.1.0":"2026-03-05T01:54:46.017Z","modified":"2026-03-05T01:54:46.387Z"},"maintainers":[{"name":"prmarshall","email":"prmarshall1990@gmail.com"}],"description":"LOD-aware physics sync — dynamically creates and destroys Rapier trimesh colliders from streaming 3D Tiles","homepage":"https://github.com/prmarshall/3d-tiles-colliders-rapier#readme","keywords":["3d-tiles","rapier","physics","colliders","trimesh","threejs","3d-tiles-renderer","lod","terrain"],"repository":{"type":"git","url":"git+https://github.com/prmarshall/3d-tiles-colliders-rapier.git"},"bugs":{"url":"https://github.com/prmarshall/3d-tiles-colliders-rapier/issues"},"license":"MIT","readme":"# 3d-tiles-colliders-rapier\n\nLOD-aware physics sync — dynamically creates and destroys [Rapier](https://rapier.rs/) trimesh colliders from streaming [3D Tiles](https://github.com/NASA-AMMOS/3DTilesRendererJS).\n\nAs 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.\n\n## Install\n\n```bash\nnpm install 3d-tiles-colliders-rapier\n```\n\nPeer dependencies: `three` (>=0.150) and `@dimforge/rapier3d-compat` (>=0.12).\n\nFor the React hook, also install `@react-three/fiber` and `@react-three/rapier`.\n\n## Usage\n\n### Vanilla Three.js + Rapier\n\n```ts\nimport RAPIER from \"@dimforge/rapier3d-compat\";\nimport { TileColliderSync } from \"3d-tiles-colliders-rapier\";\n\nawait RAPIER.init();\nconst world = new RAPIER.World({ x: 0, y: -9.81, z: 0 });\n\nconst sync = new TileColliderSync(RAPIER, world, {\n  friction: 1.5,\n  callbacks: {\n    onFirstSync: (count) => console.log(`${count} tile colliders created`),\n  },\n});\n\n// In your render loop, after tilesRenderer.update():\nfunction animate() {\n  tilesRenderer.update();\n  sync.sync(tilesRenderer.group);\n  world.step();\n  requestAnimationFrame(animate);\n}\n\n// On cleanup:\nsync.dispose();\n```\n\n### React Three Fiber\n\n```tsx\nimport { useTileColliders } from \"3d-tiles-colliders-rapier/react\";\n\nfunction TilePhysics({ tilesGroup }) {\n  useTileColliders(tilesGroup, {\n    friction: 1.5,\n    callbacks: {\n      onFirstSync: (count) => console.log(`${count} tile colliders created`),\n    },\n  });\n  return null;\n}\n```\n\n## API\n\n### `TileColliderSync`\n\nThe core class. Framework-agnostic (Three.js + Rapier only).\n\n```ts\nnew TileColliderSync(rapier, world, options?)\n```\n\n| Option        | Type                        | Default | Description                          |\n| ------------- | --------------------------- | ------- | ------------------------------------ |\n| `friction`    | `number`                    | `1.0`   | Friction for all trimesh colliders   |\n| `restitution` | `number`                    | `0.0`   | Bounciness for all trimesh colliders |\n| `callbacks`   | `TileColliderSyncCallbacks` | `{}`    | Lifecycle callbacks                  |\n\n**Methods:**\n\n- `sync(group: Object3D)` — Diff meshes and update colliders. Call once per frame.\n- `dispose()` — Remove all colliders from the Rapier world.\n- `colliderCount` — Number of active colliders.\n\n### `useTileColliders` (React hook)\n\nR3F wrapper around `TileColliderSync`. Requires `@react-three/rapier` context.\n\n```ts\nuseTileColliders(group: Object3D | null, options?)\n```\n\nAccepts the same options as `TileColliderSync` plus:\n\n| Option     | Type     | Default | Description                           |\n| ---------- | -------- | ------- | ------------------------------------- |\n| `priority` | `number` | `0`     | `useFrame` priority for the sync pass |\n\n## How it works\n\nEach frame, `sync()` traverses the tile group and collects visible meshes by UUID. It diffs this set against the previous frame:\n\n1. **New meshes** — Extracts vertex positions, bakes the world matrix, builds a `Float32Array` of world-space vertices and a `Uint32Array` index buffer, then creates a Rapier trimesh collider.\n2. **Removed meshes** — Deletes the corresponding collider from the Rapier world.\n\nThis 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.\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-d657b26c0f51b6b33d97f829bf96381b"}