I solved this problem. It was here:
const rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, colShape, localInertia);
const body = new Ammo.btRigidBody();
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);
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/es-module-shims@1.5.5/dist/es-module-shims.js"></script>
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.141.0/build/three.module.js",
"collada-loader": "https://unpkg.com/three@0.141.0/examples/jsm/loaders/ColladaLoader.js",
"orbit-controls": "https://unpkg.com/three@0.141.0/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);
};
}