I’ve been trying to figure out how to properly use Cannon or Ammo for physics in BabylonJS but the documentation on this is very sparse.
Starting with AmmoJS I’m using the npm package “ammo.js”, there also seems to be one called “ammojs” so I’m not sure which is correct but I believe the former is what I’ve seen used. I’m using Typescript and this is what I have written:
import * as Ammo from "ammo.js";
async CreatePhysics(): Promise<void> {
await Ammo();
this.scene.enablePhysics(
new Vector3(0, -9.81, 0),
new AmmoJSPlugin(true, Ammo)
);
}
I get an error about type definitions for ammo.js and it looks like none exist when I try to run npm i --save-dev @types/ammo.js
I did find these topics in the forum:
Unfortunately, even after following what was mentioned there I still don’t get around this issue. I assume the definitions are preventing me from using this at all. Is there a way around this?
I’ve also tried using Cannon, but from what I’ve read it’s currently outdated. I don’t know if this would cause any issues with it being outdated. I started using “cannon-es” which is the updated version, but I also get an error when using that: TypeError: this.world.add is not a function
According to this Github Issue:
It looks like this might have been resolved but I still get the issue using this code:
(using the cannon-es NPM package)
`import * as CANNON from “cannon-es”;
async CreatePhysics(): Promise {
//tried using this from the example in the Github issue
// window.CANNON = CANNON;
this.scene.enablePhysics(
new Vector3(0, -9.81, 0),
new CannonJSPlugin(null, null, CANNON)
);
}
`
I’m going to try using the outdated cannon NPM package, but if someone can tell me what I’m doing wrong here and how to use an updated physics engine I would greatly appreciate it. Thanks.
For me, I am using Ammo.js typed package to get the typescript types properly, package.json:
"ammojs-typed": "^1.0.6"
Then I initialize it in my async function:
import Ammo from 'ammojs-typed'
const ammo = await Ammo()
let physics: AmmoJSPlugin = new AmmoJSPlugin(true, ammo)
scene.enablePhysics(new Vector3(0, -10, 0), physics)
I’ve tried both const ammo = await Ammo(); and const ammo = await Ammo.call(this); directly inside an async function that runs my entire BabylonJS app, and I keep getting an Uncaught (in promise) TypeError: this is undefined message in my console. I even tried this as specified in the README for ammojs-typed:
thats kind of an incomplete example, but arrow functions do not have a “this” context, which you may not be expecting? also await Ammo(Ammo) is wrong. If anything, it’d be
await Ammo().then((ammo) => { ammo maybe available here } . Idk if the ammo module returns itself, but either way, you’re probably better off just assigning ammo to the window instead of expecting it to be in the return value of the promise.
so like:
async funciton App() {
window.Ammo = await Ammo()
scene01.enablePhysics(new Vector3(0, -9.81, 0), new AmmoJSPlugin(true, window.Ammo));
@bigrig Legendary timing! Will look into how to apply this same method in Vite
UPDATE: This Webpack solution doesn’t seem to be as plug-and-play with Vite. I tried porting that Webpack method into a vite.config.js file like this, even after running npm install on kripken/ammo.js and fs:
//you can can remove this
//import “ammojs-typed”;
…
window.Ammo = await Ammo()
scene01.enablePhysics(new Vector3(0, -9.81, 0), new AmmoJSPlugin(true));
This is an emscripten issue that I hope they will resolve.
Short explanation - when running as es module, you don’t have the global context (when running functions in a module. i.e. - this is undefined). hence - it is not possible to assign anything to the global namespace. but emscripten is still trying to do it. and it fails.
Avoid polluting the global namespace, avoid importing using different mechanisms. Stick with vite and es modules - this is a wonderful way to get your app performing wonderfully, loading fast, and compiling even faster
It will actually load faster and compile faster by using the script tag. It will load faster because it will be parsed in a different thread by chrome and compile faster because it wont be compiled at all. Doesnt really matter tho i guess.
but i am not going to argue
My very personal opinion is that if your system works one way, and your build system works one way, and the framework you have decided to use works one way, use this way.
I also will not use someone else’s CDN when serving production code, because then you trust a system you don’t control. But that’s a different issue.
Anyhow - there are 100 different ways to solve this. I can only provide my 2 cents, and the way I personally think will be the cleanest.