{"id":51616234,"url":"https://github.com/monteslu/box3d-wasm","last_synced_at":"2026-07-14T02:32:32.951Z","repository":{"id":368870725,"uuid":"1287239931","full_name":"monteslu/box3d-wasm","owner":"monteslu","description":"Box3D (Erin Catto's 3D physics engine) compiled to WebAssembly with SIMD and wasm threads. npm: box3d","archived":false,"fork":false,"pushed_at":"2026-07-02T15:11:34.000Z","size":52,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-02T16:27:25.116Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/monteslu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-07-02T14:00:16.000Z","updated_at":"2026-07-02T15:12:28.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/monteslu/box3d-wasm","commit_stats":null,"previous_names":["monteslu/box3d-wasm"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/monteslu/box3d-wasm","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monteslu%2Fbox3d-wasm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monteslu%2Fbox3d-wasm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monteslu%2Fbox3d-wasm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monteslu%2Fbox3d-wasm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/monteslu","download_url":"https://codeload.github.com/monteslu/box3d-wasm/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/monteslu%2Fbox3d-wasm/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35443979,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-14T02:00:06.603Z","response_time":114,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-12T14:00:20.663Z","updated_at":"2026-07-14T02:32:32.945Z","avatar_url":"https://github.com/monteslu.png","language":"C++","funding_links":[],"categories":["Libraries"],"sub_categories":["JavaScript"],"readme":"# box3d-wasm\n\n[![npm version](https://img.shields.io/npm/v/box3d-wasm.svg)](https://www.npmjs.com/package/box3d-wasm)\n[![CI](https://github.com/monteslu/box3d-wasm/actions/workflows/ci.yml/badge.svg)](https://github.com/monteslu/box3d-wasm/actions/workflows/ci.yml)\n[![license](https://img.shields.io/npm/l/box3d-wasm.svg)](LICENSE)\n\n[Box3D](https://github.com/erincatto/box3d) compiled to WebAssembly, with SIMD and optional wasm threads. Works in browsers and Node.js from a single package.\n\nSee it in action: [live three.js demo](https://box3d.netlify.app/) ([source](https://github.com/monteslu/threejs-box3d-demo)) with ragdolls, dominoes, a drivable buggy, and more.\n\nBox3D is a 3D rigid body physics engine written by Erin Catto, the author of Box2D. All engine design and implementation credit belongs to him. This package only compiles his library to wasm and adds a JavaScript binding layer. Box3D is MIT licensed by Erin Catto; the full upstream license ships in this package as LICENSE.box3d.txt.\n\n## Install\n\n```bash\nnpm i box3d-wasm\n```\n\n## Quick start\n\n```js\nimport Box3D from 'box3d-wasm';\n\nconst b3 = await Box3D();\n\nconst world = new b3.World({ gravity: { x: 0, y: -10, z: 0 } });\n\nconst ground = world.createBody({ type: 'static', position: { x: 0, y: -0.5, z: 0 } });\nground.createBox({ halfExtents: { x: 20, y: 0.5, z: 20 } });\n\nconst body = world.createBody({ type: 'dynamic', position: { x: 0, y: 5, z: 0 } });\nbody.createBox({ halfExtents: { x: 0.5, y: 0.5, z: 0.5 }, density: 1, friction: 0.5 });\n\nfor (let i = 0; i \u003c 120; i++) {\n  world.step(1 / 60, 4);\n}\n\nconsole.log(body.getPosition()); // { x: ~0, y: ~0.5, z: ~0 }\n```\n\nThe same code runs in Node.js and in the browser. The default import auto-detects thread support and loads the best build. Both builds use wasm SIMD, which every modern browser and Node.js supports. The wasm file is loaded relative to the module, so bundlers that understand `new URL(..., import.meta.url)` (Vite, webpack 5, Rollup) pick it up automatically.\n\n## Flavours\n\n| import | threads | picked by the default import when |\n| --- | --- | --- |\n| `box3d-wasm/deluxe` | yes | SharedArrayBuffer is usable (Node.js, or a cross-origin isolated page) |\n| `box3d-wasm/standard` | no | everything else |\n\n`box3d-wasm` (the default import) runs the detection above and returns whichever module fits. Import a specific flavour directly when you want to skip detection:\n\n```js\nimport Box3D from 'box3d-wasm/deluxe';\n\nconst b3 = await Box3D();\nconst world = new b3.World({ gravity: { x: 0, y: -10, z: 0 }, workerCount: 4 });\n```\n\n`workerCount` enables Box3D's internal multithreaded solver. It is clamped to `[1, b3.maxWorkers]`. The single threaded builds ignore it. Check `b3.threaded` at runtime to see which build you got.\n\n### Serving requirements for threads\n\nWasm threads use SharedArrayBuffer. Browsers require the page to be cross-origin isolated, so serve your app with:\n\n```\nCross-Origin-Opener-Policy: same-origin\nCross-Origin-Embedder-Policy: require-corp\n```\n\nNode.js needs no special setup; worker threads are used automatically.\n\n## API overview\n\nVectors are plain objects `{ x, y, z }` and quaternions are `{ x, y, z, w }`, so values pass directly to and from libraries like three.js.\n\n### World\n\n```js\nconst world = new b3.World({\n  gravity: { x: 0, y: -10, z: 0 },\n  enableSleep: true,\n  enableContinuous: true,\n  workerCount: 4, // deluxe build only\n});\n\nworld.step(1 / 60, 4);          // timeStep, subStepCount\nworld.setGravity({ x: 0, y: -3.7, z: 0 });\nworld.getAwakeBodyCount();\nworld.castRayClosest(origin, translation, filter);\nworld.explode({ position, radius: 3, falloff: 2, impulsePerArea: 10 });\nworld.getBodyEvents();          // [{ userData, position, rotation, fellAsleep }]\nworld.getContactEvents();       // { begin: [...], end: [...], hit: [...] }\nworld.getSensorEvents();        // { begin: [...], end: [...] }\nworld.destroy();\n```\n\n### Bodies\n\n```js\nconst body = world.createBody({\n  type: 'dynamic',              // 'static' | 'kinematic' | 'dynamic'\n  position: { x: 0, y: 5, z: 0 },\n  rotation: { x: 0, y: 0, z: 0, w: 1 },\n  linearVelocity: { x: 0, y: 0, z: 0 },\n  angularDamping: 0.05,\n  motionLocks: { angularX: true, angularZ: true },\n});\n\nbody.getPosition(); body.getRotation(); body.getTransform();\nbody.setLinearVelocity(v); body.applyLinearImpulseToCenter(v, true);\nbody.applyForce(force, worldPoint, true); body.applyTorque(t, true);\nbody.getMass(); body.isAwake(); body.setAwake(true);\nbody.destroy();\n```\n\n### Shapes\n\nEach shape creator takes one options object with the geometry plus material fields (`density`, `friction`, `restitution`, `isSensor`, `filter`, event flags):\n\n```js\nbody.createBox({ halfExtents: { x: 1, y: 0.5, z: 2 }, friction: 0.7 });\nbody.createSphere({ radius: 0.5, restitution: 0.8 });\nbody.createCapsule({ height: 1.2, radius: 0.3 });\nbody.createHull({ points: [{ x, y, z }, ...] });\n```\n\n### Joints\n\nDistance, revolute, spherical, prismatic, weld, motor, wheel, parallel, and filter joints are bound:\n\n```js\nconst hinge = world.createRevoluteJoint(bodyA, bodyB, {\n  localFrameA: { position: { x: 0, y: 1, z: 0 } },\n  enableMotor: true,\n  motorSpeed: 5,\n  maxMotorTorque: 100,\n});\nhinge.getAngle();\n```\n\n### Events and userData tags\n\nEvery body and shape gets an auto-assigned numeric `userData` tag (you can overwrite it with your own number). Event arrays reference these tags, so you can map physics events back to your scene objects with a plain `Map`.\n\n### Memory notes\n\nWrapper objects returned by embind (`World`, `Body`, `Shape`, joints) are tiny handles. Call `.delete()` when you no longer need the JS handle, and `.destroy()` to remove the underlying object from the simulation. Destroying a world frees every body, shape, and joint inside it.\n\n## Building from source\n\nRequires [emsdk](https://emscripten.org/docs/getting_started/downloads.html) (tested with 4.0.18), CMake, and Node 22+.\n\n```bash\nnpm ci\nnpm run fetch-deps   # clones Box3D at the SHA pinned in scripts/versions.json\nnpm run build        # builds standard and deluxe flavours into dist/\nnpm test\n```\n\n## License\n\nMIT for the wrapper and build scripts, see LICENSE.\n\nBox3D itself is Copyright (c) Erin Catto and MIT licensed, see LICENSE.box3d.txt and the upstream repository at https://github.com/erincatto/box3d. If you use this package, the physics engine you are running is his work.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmonteslu%2Fbox3d-wasm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmonteslu%2Fbox3d-wasm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmonteslu%2Fbox3d-wasm/lists"}