ammo.js
ammo.js copied to clipboard
ES6 modules in ammo.js
I know it sounds a bit stupid and it's more emscripten-related rather than to Ammo.js, but:
- Is it possible to port Bullet Physics with keeping classes as modules?
- If it is possible: will it keep being asm.js?
I personally would like to have it modular as i have a framework that uses it and usage of Vehicles, Softbodies, etc. could be depending on if developer needs it.
What do you mean by modules here? ES6 modules?
@kripken Yes. Is it possible to compile it as separate files?
@kripken Because current build is about 2-3Mb.
We don't have ES6 module support in that way. It would need to share the heap and other stuff, for example - not sure how would be best.
But if it's build size that concerns you, you can edit the idl file and remove things you don't need, and make a custom build with only the parts you want.
@kripken Yes, i know that. (I even have my own build already). The reason of why i am asking is that i am writing a 3D framework and i want to let users choose parts of physics that they need or not(that will be included in result app), so only imported parts of framework will be used by webpack(or not webpack) in their apps.
Anyway, thanks for reply!
Oh, I see - nice! Yeah, if this modularity were possible after building, it would be great. Perhaps eventually we can do it with wasm modules.
@kripken I see that wasm has modules. Another question is when it will be implemented or what should i start with (if you want to me discover this topic)?
Emscripten doesn't yet support dynamic linking of wasm modules. It might over the next few months. But even so, it would do it using c++ or dlopen style linking, and it might be possible to do something more efficient for your purposes here by using wasm modules directly from JS somehow. So it might be interesting to experiment with that if you want.
@kripken WebAssembly is now in Browser Preview: http://webassembly.org/roadmap/ so it's time to talk about this topic more. By the way, i ported Bullet3 to WhitestormJS / AmmoNext You can check these examples running AmmoNext physics.
It's in preview, but no dynamic linking in the toolchain yet. Hopefully soon though.
Nice about Bullet3. I don't follow Bullet development these days, is 3 a big change over 2?
Your demos don't work for me though, I just see a flat plane but no objects.
@kripken Did you open demos with safari?
@kripken if so - remove "#" from url. For example "https://whs-dev.surge.sh/examples/#basic/helloworld" will become "https://whs-dev.surge.sh/examples/basic/helloworld"
@kripken They made it more stable (I noticed that my example with 320 sticks became smooth and without lags after porting Bullet3)
No, I'm on Firefox.
I tried again. Looks like the console shows an asm.js error, which makes it very slow. Waiting a while, I do see objects fall down, so I think that was the issue (noticeable here as I am now on a quite slow machine).
With what version of emscripten was that compiled?
@kripken seems like tratata.36.13 (or something like that)
@kripken How can i solve that error?
@kripken See https://github.com/WhitestormJS/whitestorm.js - this projects. All examples are from here. It uses AmmoNext
If it's on 1.36.13, then this is likely a bug in emscripten. Maybe you can point me to the build instructions for that file, and I'll try it?
@kripken May I contact you in real-time chat somewhere? You can find me in discord in this chat: https://discordapp.com/invite/frNetGE
I'm usually on the emscripten irc channel (as azakai).
@kripken I can't catch you online there. P.s.: I will play with making wasm builds this time
Hello, guys) What about ammo.js es6 modules? 4 years gone)
For those who came to this thread to enable Ammo as an ES module. Here is the solution: https://discourse.threejs.org/t/how-to-convert-ammo-js-to-es6-module/30633/4
But later I had this problem: Three.js and Ammo-ES. Error: ammo-es.js:37 Uncaught TypeError: ia[J[((J[(a >> 2)] + 8) >> 2)]] is not a function
I solved my problem above. Now Ammo.js works as ES6 module. Playground: Ammo.js as ES6-module. Falling Box
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
html,
body {
overflow: hidden;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#renderCanvas {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<script async src="https://unpkg.com/[email protected]/dist/es-module-shims.js"></script>
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/[email protected]/build/three.module.js",
"collada-loader": "https://unpkg.com/[email protected]/examples/jsm/loaders/ColladaLoader.js",
"orbit-controls": "https://unpkg.com/[email protected]/examples/jsm/controls/OrbitControls.js",
"ammo-es": "https://dl.dropboxusercontent.com/s/1os9vvoo1pa3ajk/ammo-es.js"
}
}
</script>
<!-- https://dl.dropboxusercontent.com/s/1os9vvoo1pa3ajk/ammo-es.js -->
<!-- https://dl.dropboxusercontent.com/s/v9fu59gb5h0st6b/ammo-es6-module.js -->
<script type="module" src="js/main.js"></script>
</body>
</html>
js/main.js
import * as THREE from "three";
import AmmoLib from "ammo-es";
import { OrbitControls } from "orbit-controls";
let Ammo, world, scene;
const rigidBodies = [];
let tmpTrans;
const clock = new THREE.Clock();
let deltaTime;
AmmoLib().then((re) =>
{
Ammo = re;
setupPhysicsWorld();
initScene();
createGround();
createBox({ x: 0, y: 3, z: 0 });
});
function setupPhysicsWorld()
{
const collisionConfiguration = new Ammo.btDefaultCollisionConfiguration();
const dispatcher = new Ammo.btCollisionDispatcher(collisionConfiguration);
const overlappingPairCache = new Ammo.btDbvtBroadphase();
const solver = new Ammo.btSequentialImpulseConstraintSolver();
world = new Ammo.btDiscreteDynamicsWorld(dispatcher, overlappingPairCache, solver, collisionConfiguration);
world.setGravity(new Ammo.btVector3(0, -10, 0));
tmpTrans = new Ammo.btTransform();
}
function createGround()
{
const pos = { x: 0, y: 0, z: 0 };
const scale = { x: 50, y: 2, z: 50 };
const quat = { x: 0, y: 0, z: 0, w: 1 };
const mass = 0;
// Three.js section
const ground = new THREE.Mesh(
new THREE.BoxBufferGeometry(),
new THREE.MeshPhongMaterial({ color: 0xa0afa4 }));
ground.position.set(pos.x, pos.y, pos.z);
ground.scale.set(scale.x, scale.y, scale.z);
scene.add(ground);
// Ammo.js section
const transform = new Ammo.btTransform();
transform.setIdentity();
transform.setOrigin(new Ammo.btVector3(pos.x, pos.y, pos.z));
transform.setRotation(new Ammo.btQuaternion(quat.x, quat.y, quat.z, quat.w));
const motionState = new Ammo.btDefaultMotionState(transform);
const colShape = new Ammo.btBoxShape(new Ammo.btVector3(scale.x / 2, scale.y / 2, scale.z / 2));
colShape.setMargin(0.05);
const localInertia = new Ammo.btVector3(0, 0, 0);
colShape.calculateLocalInertia(mass, localInertia);
const rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, colShape, localInertia);
const body = new Ammo.btRigidBody(rbInfo);
world.addRigidBody(body);
}
function createBox(pos)
{
const scale = { x: 1, y: 1, z: 1 };
const quat = { x: 0, y: 0, z: 0, w: 1 };
const mass = 10;
// Three.js section
const box = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshPhongMaterial({ color: 0x00ff00 }));
scene.add(box);
box.position.set(pos.x, pos.y, pos.z);
box.scale.set(scale.x, scale.y, scale.z);
scene.add(box);
// Ammo.js section
const transform = new Ammo.btTransform();
transform.setIdentity();
transform.setOrigin(new Ammo.btVector3(pos.x, pos.y, pos.z));
transform.setRotation(new Ammo.btQuaternion(quat.x, quat.y, quat.z, quat.w));
const motionState = new Ammo.btDefaultMotionState(transform);
const colShape = new Ammo.btBoxShape(new Ammo.btVector3(scale.x / 2, scale.y / 2, scale.z / 2));
colShape.setMargin(0.05);
const localInertia = new Ammo.btVector3(0, 0, 0);
colShape.calculateLocalInertia(mass, localInertia);
const rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, colShape, localInertia);
const body = new Ammo.btRigidBody(rbInfo);
world.addRigidBody(body);
box.userData.physicsBody = body;
rigidBodies.push(box);
}
function updatePhysics(deltaTime)
{
world.stepSimulation(deltaTime, 10);
for (let i = 0; i < rigidBodies.length; i++)
{
let objThree = rigidBodies[i];
let objAmmo = objThree.userData.physicsBody;
let ms = objAmmo.getMotionState();
if (ms)
{
ms.getWorldTransform(tmpTrans);
const p = tmpTrans.getOrigin();
const q = tmpTrans.getRotation();
objThree.position.set(p.x(), p.y(), p.z());
objThree.quaternion.set(q.x(), q.y(), q.z(), q.w());
}
}
}
function initScene()
{
scene = new THREE.Scene();
const ambientLight = new THREE.AmbientLight(0xffffff, 0.7);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(5, 5.5, 5.8);
scene.add(directionalLight);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.01, 1000);
camera.position.set(0, 3, 7);
const orbitControls = new OrbitControls(camera, renderer.domElement);
orbitControls.target = new THREE.Vector3(0, 0, 0);
(function anim()
{
requestAnimationFrame(anim);
orbitControls.update();
deltaTime = clock.getDelta();
updatePhysics(deltaTime);
renderer.render(scene, camera);
})();
window.onresize =
() =>
{
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
};
}