8
\$\begingroup\$

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.

\$\endgroup\$

3 Answers 3

8
\$\begingroup\$

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.

\$\endgroup\$
4
  • \$\begingroup\$ Can you expand more on how you detected collisions in the first place? \$\endgroup\$
    – timoxley
    Commented Mar 7, 2013 at 8:34
  • 1
    \$\begingroup\$ @timoxley I've updated the answer a bit. \$\endgroup\$
    – House
    Commented Mar 7, 2013 at 14:42
  • \$\begingroup\$ How would you then handle a single item that collides at multiple points, e.g. a ladder leaning on ground and on a wall? \$\endgroup\$
    – timoxley
    Commented Mar 7, 2013 at 18:31
  • \$\begingroup\$ 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. \$\endgroup\$
    – House
    Commented Mar 7, 2013 at 19:09
3
\$\begingroup\$

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

\$\endgroup\$
1
  • \$\begingroup\$ I'll note to anyone reading this that, at least in my testing, JBullet is VERY slow at cooking meshes (i.e. preprocessing them before they can be used for physics), at least compared to the time it takes for me to convert a chunk into a mesh via marching cubes. We're talking orders of magnitude slower. So, I'm going to look into PhysX and see how much better I can get it performing. If anyone has info on this, I'd love to hear it. \$\endgroup\$ Commented Jun 23, 2016 at 16:51
2
\$\begingroup\$

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.

\$\endgroup\$
2
  • \$\begingroup\$ 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. \$\endgroup\$
    – House
    Commented Apr 15, 2012 at 15:04
  • \$\begingroup\$ 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. \$\endgroup\$
    – Kevin Reid
    Commented Apr 15, 2012 at 15:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .