Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

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.

share|improve this question

3 Answers 3

While I appreciate Kevin Reid's answer, it was at a level that was higher than what my question was asking. Understandably with out knowledge of Bullet Physics, it'd be hard to answer this question. I got this working and have an answer that is specific to Bullet Physics.

Along with extending the RigidBody class like I mentioned in my question. I also needed to extend the CollisionAlgorithm class. This is mostly to override the processCollision() function. Inside the processCollision() function (which takes the two colliding bodies as arguments), I was able to create a cube shape and appropriate Transform for the cube that my entity was currently colliding with. Then just let the default collision happen based on the entity and the specific cube/cubes it's colliding with. In order to use the newly extended CollisionAlgorithm, I needed to register the algorithm to deal with the shapes I want it to handle. In this case that's pretty much the terrain type against everything else. For that I used registerCollisionCreateFunc() with my CollisionDispatcher.

So for those following along in the future:

  1. Extend RigidBody to have a basic collision check with your terrain.
  2. Create a instance of your RigidBody class and add it to your DynamicsWorld or whatever PhysicsProccesor you're using.
  3. Extend CollisionAlgorithm, specifically processCollision() to create Bullet Physics shapes and Transforms that match with your collision location.
  4. Register your version of CollisionAlgorithm with your CollisionDispatcher using registerCollisionCreateFunc(). (This registration is done multiple times, once for each pair of shapes you want to collide.)

EDIT

Here's a video of it in action if anyone is interested.

Detecting the initial collision

For my initial collision checks, my extended rigidBody overrides the checkCollideWith function described in my question. I have a function for my terrain that can check if the world is solid at a specific point. Basically, I test my terrain against the object being passed in by the checkCollideWith function, seeing if my terrain is solid anywhere within the bounds of that object.

Now, there's also the next step in Bullet, finding the contact points. This takes place in the processCollision() function I mentioned above. Here, I've made a boxShape the size of a terrain cube, then when I detect a collision in the checkCollideWith function, I place that terrain cube sized boxShape at the collision location, and let Bullet use all it's default algorithms for detecting collision points there.

So basically, if a physics objects bounds touch solid material. I'll place my temporary physics body to that location and tell Bullet to check collisions against that temporary cube, as if it were always there. This is sort of like super optimizing placing a boxShape for every cube in my terrain. Instead of millions of boxShapes, I only need to have one that teleports around when a collision is detected.

share|improve this answer
    
Can you expand more on how you detected collisions in the first place? –  timoxley Mar 7 '13 at 8:34
1  
@timoxley I've updated the answer a bit. –  Byte56 Mar 7 '13 at 14:42
    
How would you then handle a single item that collides at multiple points, e.g. a ladder leaning on ground and on a wall? –  timoxley Mar 7 '13 at 18:31
    
The temporary cube is moved around for all the places where an object contacts the terrain. It's just used for the fine detection to get contact points and respond appropriately. –  Byte56 Mar 7 '13 at 19:09

I'm not familiar with Bullet Physics, but I've used ODE. There, after the yes-or-no collision test, there is a more detailed shape-shape collision test which generates a set of contact points.

In your case, your world is a collection of boxes, so you could do this:

  1. Take the AABB of the moving entity.
  2. Iterate over the terrain voxels in the volume that intersects it.
  3. For each voxel of the terrain which is solid, construct a matching box and compute (preferably using the physics engine's provided routines) the collision of that box with the moving entity.
  4. Return the collection of all of the resulting contact points.

This is not redefining the collision response; this is a layer before that. The collision response is determined fully by the contact points calculated from the collision.

As I said, I'm not familiar with Bullet Physics, so I don't know whether its architecture is amenable to this.

share|improve this answer
    
Thanks. I would think the collision response is tied into the shape collision test as well. It must use that information to decide which way to move them apart and how far to move them apart right? I'd be fine with the current collision response if it was responding to the shape of my terrain. –  Byte56 Apr 15 '12 at 15:04
    
Yes; I meant that you do not redefine the collision response algorithm but rather redefine the generation of contact points which are the inputs to that algorithm. –  Kevin Reid Apr 15 '12 at 15:06
up vote 2 down vote accepted

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.

enter image description here

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.