Ammo.js 与球体的自定义网格碰撞
Ammo.js custom mesh collision with sphere
我正在尝试为每个 object/mesh 生成碰撞。它们都是静态的,应该与动态的 ball/sphere 发生碰撞。
我的代码如下所示:
const transform = new Ammo.btTransform();
transform.setIdentity();
transform.setOrigin(new Ammo.btVector3(-1.1726552248001099, 2.6692488193511963, 0));
transform.setRotation(new Ammo.btQuaternion(0.5, -0.5, 0.5, 0.4999999701976776));
const motionState = new Ammo.btDefaultMotionState(transform);
// Vertices and indices are parsed by GLTF parser by loaders.gl
const vertices = Entity.vertices;
const indices = Entity.indices;
const scale = [0.15933185815811157, 1.1706310510635376, 0.15933185815811157];
// btConvexHullShape or btBvhTriangleMeshShape, see below.
const localInertia = new Ammo.btVector3(0, 0, 0);
const rbInfo = new Ammo.btRigidBodyConstructionInfo(0, motionState, shape, localInertia);
const object = new Ammo.btRigidBody(rbInfo);
this._physicsWorld.addRigidBody(object);
我尝试了两种方法:btConvexHullShape 和 btBvhTriangleMeshShape,但均无效。
- btConvexHullShape
const shape = new Ammo.btConvexHullShape();
for (let i = 0; i < vertices.length / 3; i++) {
shape.addPoint(new Ammo.btVector3(vertices[i * 3] * scale[0], vertices[i * 3 + 1] * scale[1], vertices[i * 3 + 2] * scale[2]));
}
使用btConvexHullShape的球体路径是这样的(它不进入洞):
我猜 Ammo.js 连接了最高点?如何根据索引控制连接哪些点?似乎这种方法很慢(30k 顶点需要一些时间),所以我尝试了:
- btBvhTriangleMeshShape
const mesh = new Ammo.btTriangleMesh(true, true);
for (let i = 0; i * 3 < indices.length; i++) {
mesh.addTriangle(
new Ammo.btVector3(vertices[indices[i * 3]] * scale[0], vertices[indices[i * 3] + 1] * scale[1], vertices[indices[i * 3] + 2] * scale[2]),
new Ammo.btVector3(vertices[indices[i * 3 + 1]] * scale[0], vertices[indices[i * 3 + 1] + 1] * scale[1], vertices[indices[i * 3 + 1] + 2] * scale[2]),
new Ammo.btVector3(vertices[indices[i * 3 + 2]] * scale[0], vertices[indices[i * 3 + 2] + 1] * scale[1], vertices[indices[i * 3 + 2] + 2] * scale[2]),
false
);
}
const shape = new Ammo.btBvhTriangleMeshShape(mesh, true, true);
这个方法好一点,但是球体弹跳一次就穿过了物体(弹开圆圈,穿过物体(红圈)):
btConvexHullShape 没有工作的原因(尽管它周围的碰撞确实有效)是因为它不适用于凹形。
至于 btBvhTriangleMeshShape,我输入顶点的方式不对。我必须将索引乘以 3(因为每个顶点有 3 个分量)。
这是完整的工作代码:
const transform = new Ammo.btTransform();
transform.setIdentity();
transform.setOrigin(new Ammo.btVector3(-1.1726552248001099, 2.6692488193511963, 0));
transform.setRotation(new Ammo.btQuaternion(0.5, -0.5, 0.5, 0.4999999701976776));
const motionState = new Ammo.btDefaultMotionState(transform);
// Vertices and indices are parsed by GLTF parser by loaders.gl
const vertices = Entity.vertices;
const indices = Entity.indices;
const scale = [0.15933185815811157, 1.1706310510635376, 0.15933185815811157];
const mesh = new Ammo.btTriangleMesh(true, true);
mesh.setScaling(new Ammo.btVector3(scale[0], scale[1], scale[2]));
for (let i = 0; i * 3 < indices.length; i++) {
mesh.addTriangle(
new Ammo.btVector3(vertices[indices[i * 3] * 3], vertices[indices[i * 3] * 3 + 1], vertices[indices[i * 3] * 3 + 2]),
new Ammo.btVector3(vertices[indices[i * 3 + 1] * 3], vertices[indices[i * 3 + 1] * 3 + 1], vertices[indices[i * 3 + 1] * 3 + 2]),
new Ammo.btVector3(vertices[indices[i * 3 + 2] * 3], vertices[indices[i * 3 + 2] * 3 + 1], vertices[indices[i * 3 + 2] * 3 + 2]),
false
);
}
const shape = new Ammo.btBvhTriangleMeshShape(mesh, true, true);
const localInertia = new Ammo.btVector3(0, 0, 0);
const rbInfo = new Ammo.btRigidBodyConstructionInfo(0, motionState, shape, localInertia);
const object = new Ammo.btRigidBody(rbInfo);
this._physicsWorld.addRigidBody(object);
我正在尝试为每个 object/mesh 生成碰撞。它们都是静态的,应该与动态的 ball/sphere 发生碰撞。
我的代码如下所示:
const transform = new Ammo.btTransform();
transform.setIdentity();
transform.setOrigin(new Ammo.btVector3(-1.1726552248001099, 2.6692488193511963, 0));
transform.setRotation(new Ammo.btQuaternion(0.5, -0.5, 0.5, 0.4999999701976776));
const motionState = new Ammo.btDefaultMotionState(transform);
// Vertices and indices are parsed by GLTF parser by loaders.gl
const vertices = Entity.vertices;
const indices = Entity.indices;
const scale = [0.15933185815811157, 1.1706310510635376, 0.15933185815811157];
// btConvexHullShape or btBvhTriangleMeshShape, see below.
const localInertia = new Ammo.btVector3(0, 0, 0);
const rbInfo = new Ammo.btRigidBodyConstructionInfo(0, motionState, shape, localInertia);
const object = new Ammo.btRigidBody(rbInfo);
this._physicsWorld.addRigidBody(object);
我尝试了两种方法:btConvexHullShape 和 btBvhTriangleMeshShape,但均无效。
- btConvexHullShape
const shape = new Ammo.btConvexHullShape();
for (let i = 0; i < vertices.length / 3; i++) {
shape.addPoint(new Ammo.btVector3(vertices[i * 3] * scale[0], vertices[i * 3 + 1] * scale[1], vertices[i * 3 + 2] * scale[2]));
}
使用btConvexHullShape的球体路径是这样的(它不进入洞):
我猜 Ammo.js 连接了最高点?如何根据索引控制连接哪些点?似乎这种方法很慢(30k 顶点需要一些时间),所以我尝试了:
- btBvhTriangleMeshShape
const mesh = new Ammo.btTriangleMesh(true, true);
for (let i = 0; i * 3 < indices.length; i++) {
mesh.addTriangle(
new Ammo.btVector3(vertices[indices[i * 3]] * scale[0], vertices[indices[i * 3] + 1] * scale[1], vertices[indices[i * 3] + 2] * scale[2]),
new Ammo.btVector3(vertices[indices[i * 3 + 1]] * scale[0], vertices[indices[i * 3 + 1] + 1] * scale[1], vertices[indices[i * 3 + 1] + 2] * scale[2]),
new Ammo.btVector3(vertices[indices[i * 3 + 2]] * scale[0], vertices[indices[i * 3 + 2] + 1] * scale[1], vertices[indices[i * 3 + 2] + 2] * scale[2]),
false
);
}
const shape = new Ammo.btBvhTriangleMeshShape(mesh, true, true);
这个方法好一点,但是球体弹跳一次就穿过了物体(弹开圆圈,穿过物体(红圈)):
btConvexHullShape 没有工作的原因(尽管它周围的碰撞确实有效)是因为它不适用于凹形。
至于 btBvhTriangleMeshShape,我输入顶点的方式不对。我必须将索引乘以 3(因为每个顶点有 3 个分量)。
这是完整的工作代码:
const transform = new Ammo.btTransform();
transform.setIdentity();
transform.setOrigin(new Ammo.btVector3(-1.1726552248001099, 2.6692488193511963, 0));
transform.setRotation(new Ammo.btQuaternion(0.5, -0.5, 0.5, 0.4999999701976776));
const motionState = new Ammo.btDefaultMotionState(transform);
// Vertices and indices are parsed by GLTF parser by loaders.gl
const vertices = Entity.vertices;
const indices = Entity.indices;
const scale = [0.15933185815811157, 1.1706310510635376, 0.15933185815811157];
const mesh = new Ammo.btTriangleMesh(true, true);
mesh.setScaling(new Ammo.btVector3(scale[0], scale[1], scale[2]));
for (let i = 0; i * 3 < indices.length; i++) {
mesh.addTriangle(
new Ammo.btVector3(vertices[indices[i * 3] * 3], vertices[indices[i * 3] * 3 + 1], vertices[indices[i * 3] * 3 + 2]),
new Ammo.btVector3(vertices[indices[i * 3 + 1] * 3], vertices[indices[i * 3 + 1] * 3 + 1], vertices[indices[i * 3 + 1] * 3 + 2]),
new Ammo.btVector3(vertices[indices[i * 3 + 2] * 3], vertices[indices[i * 3 + 2] * 3 + 1], vertices[indices[i * 3 + 2] * 3 + 2]),
false
);
}
const shape = new Ammo.btBvhTriangleMeshShape(mesh, true, true);
const localInertia = new Ammo.btVector3(0, 0, 0);
const rbInfo = new Ammo.btRigidBodyConstructionInfo(0, motionState, shape, localInertia);
const object = new Ammo.btRigidBody(rbInfo);
this._physicsWorld.addRigidBody(object);