I've successfully integrated the Bullet Physics library into my entity/component system. Entities can collide with each other. Now I need to enable them to collide with the terrain, which is finite and cube-like (think InfiniMiner or it's clone Minecraft). I only started using the Bullet Physics library yesterday, so perhaps I'm missing something obvious.
So far I've extended the RigidBody
class to override the checkCollisionWith(CollisionObject co)
function. At the moment it's just a simple check of the origin, not using the other shape. I'll iterate on that later. For now it looks like this:
@Override
public boolean checkCollideWith(CollisionObject co) {
Transform t = new Transform();
co.getWorldTransform(t);
if(COLONY.SolidAtPoint(t.origin.x, t.origin.y,t.origin.z)){
return true;
}
return false;
}
This works great, as far as detecting when collisions happen. However, this doesn't handle the collision response. It seems that the default collision response is to move the colliding objects outside of each others shapes, possibly their AABBs.
At the moment the shape of the terrain is just a box the size of the world. This means the entities that collide with the terrain just shoot away to outside that world size box. So it's clear that I either need to modify the collision response or I need to create a shape that conforms directly to the shape of the terrain. So which option is best and how do I go about implementing it? Perhaps there's an option I'm not thinking of?
It should be noted that the terrain is dynamic and frequently modified by the player.
Answer
I was having some troubles with the strategy implemented in my other answer. Contact points would sometimes stick around, it was kind of hacky to do shapes other than cubes and it would sometimes allow objects to slip through the terrain.
So instead of modifying or overriding any of the Bullet classes, there is an alternative option of using a built in Bullet collision object that will represent the terrain. The BvhTriangleMeshShape
(doc) is a built in shape that is represented by a triangle mesh.
This mesh can be generated at the same time as the mesh for visualizing the world. This means that the physics object can match the rendered object exactly.
I create a RigidBody
for each chunk in my terrain. That body has its shape set to a BvhTriangleMeshShape
. When the terrain is modified, at the same time I'm rebuilding the visual representation of the chunk, I'm also rebuilding the physics shape. Then, when it comes time to buffer the visual shape, I also swap out the physics shapes like so:
dynamicsWorld.removeRigidBody(chunk.getRigidBody());
chunk.getRigidBody().setCollisionShape(newShape);
dynamicsWorld.addRigidBody(chunk.getRigidBody());
This ensures that the body is properly removed, cleaning up the contact points. Then it's shape is changed and it's re-added.
In order to generate the BvhTriangleMeshShape
each chunk must maintain a TriangleIndexVertexArray
(doc). This is essentially two byte buffers. One with the positions of the triangle vertices and the other with the indices for constructing those triangles. This vertex array must be maintained as the BvhTriangleMeshShape
does not make a copy of the data.
Using all the built in Bullet physics classes is likely faster than anything I could write, and it does indeed run very fast. I haven't see any slow downs after implementing this new strategy.
No comments:
Post a Comment