Colorfully Monochrome
Colorfully Monochrome

Reputation: 1114

Bullet Physics Convex hulls with cubes

I'm developing a game engine in c# and am using BulletSharp for physics. It's working well except with cubes:

https://i.sstatic.net/EPfrw.png

(The Axis-Aligned Bounding box is the transparent red, the model is the white)

At rest, the stand on their edges. Because I'm loading from Collada models, I am creating a ConvexHullShape() and adding the data as a vector cloud. While using BoxShape() would be more efficient (and work correctly), I cannot as it is not guaranteed that all models are cubes. I cannot figure out why they rest on vertices and not on the flat edges. Is my implementation of ConvexHullShape wrong or do I need to use a different type of shape (for the physics to work correctly)?

public RigidBody AddDynamicGeometry(ColladaGeometry geometry, Matrix4 transform)
        {
            List<Vector3> points = new List<Vector3>();
            foreach (Triangle tri in geometry.triangles)
            {
                points.Add(tri.vertices[0]);
                points.Add(tri.vertices[1]);
                points.Add(tri.vertices[2]);
            }
            CollisionShape shape = new ConvexHullShape(points);



            shape.UserObject = geometry;

            collisionShapes.Add(shape);

            RigidBody body = CreateRigidBody(geometry.triangles.Count * 10, transform, shape);

            return body;
        }

        public RigidBody CreateRigidBody(float mass, Matrix4 startTransform, CollisionShape shape)
        {
            bool isDynamic = (mass != 0.0f);

            Vector3 localInertia = Vector3.Zero;
            if (isDynamic)
                shape.CalculateLocalInertia(mass, out localInertia);

            DefaultMotionState myMotionState = new DefaultMotionState(startTransform);

            RigidBodyConstructionInfo rbInfo = new RigidBodyConstructionInfo(mass, myMotionState, shape, localInertia);
            RigidBody body = new RigidBody(rbInfo);

            physics_world.AddRigidBody(body);

            return body;
        }

Upvotes: 0

Views: 986

Answers (1)

Andres Traks
Andres Traks

Reputation: 171

ConvexHullShape expects the center of mass (COM) to be (0,0,0), but the cube is offset from the center, making it tilt towards the corner.

You can find the correct COM with ConvexTriangleMeshShape.CalculatePrincipalAxisTransform. Then you could subtract the COM from each vertex to bring the COM back to 0. However, it's easier to create a CompoundShape with a local center for the cube.

// Create a ConvexTriangleMeshShape from the points
const int indexStride = 3 * sizeof(int);
const int vertexStride = 12;
int vertexCount = points.Count;
int indexCount = vertexCount / 3;

TriangleIndexVertexArray vertexArray = new TriangleIndexVertexArray();
IndexedMesh mesh = new IndexedMesh();
mesh.Allocate(vertexCount, vertexStride, indexCount, indexStride);
Vector3Array vdata = mesh.Vertices;
IntArray idata = mesh.TriangleIndices;
for (int i = 0; i < vertexCount; i++)
{
    vdata[i] = points[i];
    idata[i] = i;
}
vertexArray.AddIndexedMesh(mesh);
ConvexTriangleMeshShape shape = new ConvexTriangleMeshShape(vertexArray, true);

// Calculate center of mass
Matrix center = Matrix.Identity;
Vector3 inertia;
float volume;
shape.CalculatePrincipalAxisTransform(ref center, out inertia, out volume);

// Create a CompoundShape with COM offset
CompoundShape compound = new CompoundShape();
compound.AddChildShape(Matrix.Invert(center), shape);

Note: ConvexTriangleMeshShape.CalculatePrincipalAxisTransform works in SVN trunk, but not in BulletSharp 2.82. There will be a bugfix release soon.

Upvotes: 1

Related Questions