How to convert ammo.js to es6 module?

I’m facing a situation that can only import es6 module, can not use <script> tag.

How to convert ammo.js to es6 module?

If can’t convert, is there a way to wrap it in an es6 loader, and load it like what DRACOLoader loading draco_decoder.wasm?

I suggest you use the JS version instead of wasm (because wasm is a pain to wrap and performance difference with ammo specifically is quite low)

  1. make a local copy (or clone repo)
  2. go to the bottom of the file and add an export statement
  3. profit?
1 Like

Oh! There’s an ammo.js file in the official ammo.js repo.

( I consider EMScripten can only produce .wasm not .js before, and three.js repo only has ammo.wasm.js and ammo.wasm.wasm files too. )

Thanks a lot! I’ll try.



I found need one more step: delete this.Ammo=b; in ammo.js, otherwise will cause an error.
Seems to work fine:




Hello, @gonnavis! I have a problem. Maybe did you have it too? Three.js and Ammo-ES. Error: ammo-es.js:37 Uncaught TypeError: ia[J[((J[(a >> 2)] + 8) >> 2)]] is not a function

Sorry that I chose to use cannon-es and PhysX wasm later.
So no more use of ammo.

1 Like

Thank you very much for reply. I use cannon-es too but I hear about physx-js at first time. It needs for me to have the same physics engine on Web and Desktop (C++ client) for multiplayer game: Ammo.js and Bullet Physics. I must have the same physics engine on the client and server side for client predictions. It seems I can have physx-js for Web and PhysX for Desktop. I read that PhysX is free now. Can I use physx-js as ES6 module? I have the problem: physx-js as ES6 module · Issue #15 · ashconnell/physx-js · GitHub

We are using a customized PhysX wasm.
Not full-featured yet, but expose functions for our project’s needs specifically.

1 Like

Thanks a lot! Maybe I will try it later. I will use cannon-es with TypeScript and Parcel for a while.

It was my mistake. I forgot to send rbInfo to Ammo.btRigidBody() like this:

    const rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, colShape, localInertia);
    const body = new Ammo.btRigidBody(rbInfo);

Playground: Plunker - Ammo.js as ES6-module. Falling Box

Thank you very much for your solution which makes it possible to use Ammo.js with Rollup.

This is my example (3.9 KB) (ammo.js: (434.0 KB)) which outputs gravity to the console using Rollup as the bundler. These packages must be installed globally: npm i -g rollup uglify-js

Use these commands:

npm run dev is for development. Rollup will watch for file changes. You can set breakpoints in the browser

npm run release is for release. Rollup will create a bundle. Uglify will compress it.


<!DOCTYPE html>
<html lang="en">

    <meta charset="UTF-8">

    <!-- Since import maps are not yet supported by all browsers, it is
        necessary to add the polyfill es-module-shims.js
    <script async src=""></script>

    <script type="importmap">
            "imports": {
                "ammo-es": ""

    <script type="module" src="./js/bundle.js"></script>



import AmmoLib from "ammo-es";

let Ammo, physicsWorld;

function setupPhysicsWorld() {
    const collisionConfiguration = new Ammo.btDefaultCollisionConfiguration();
    const dispatcher = new Ammo.btCollisionDispatcher(collisionConfiguration);
    const overlappingPairCache = new Ammo.btDbvtBroadphase();
    const solver = new Ammo.btSequentialImpulseConstraintSolver();

    physicsWorld = new Ammo.btDiscreteDynamicsWorld(dispatcher, overlappingPairCache, solver, collisionConfiguration);
    physicsWorld.setGravity(new Ammo.btVector3(0, -10, 0));

function animationLoop() {
    const gravity = new Ammo.btVector3(0, -10, 0);
    console.log(`Gravity: (${gravity.x()}, ${gravity.y()}, ${gravity.z()})`);
    // requestAnimationFrame(animationLoop);

function init() {
    AmmoLib().then((re) => {
        Ammo = re;



export default {
    input: "./src/main.js",
    output: {
        file: "public/js/bundle.js"


  "name": "ammo-es-module-rollup-js",
  "version": "1.0.0",
  "description": "",
  "main": "rollup.config.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "rollup -cwm",
    "del-bundle-map": "del /f /q /s .\\public\\js\\",
    "bundle": "rollup -cm",
    "minify": "uglifyjs public/js/bundle.js -o public/js/bundle.js",
    "release": "npm run bundle && npm run minify && npm run del-bundle-map"
  "keywords": [],
  "author": "",
  "license": "ISC"
1 Like

is ammo unmaintained as well now? otherwise why don’t they just release an es export?

Ammo.js isn’t a separate library. This is just a direct build of C++ Bullet Physics code using Emscripten. You can get the Bullet Physics source code and build it yourself to JS. I think this is an Emscripten issue. If I’m not mistaken.

Ammo and Oimo are both shipped with the latest release of three so should be relatively kept i assume… three.js/examples/jsm/physics at dev · mrdoob/three.js · GitHub