Not detecting any collisions

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
martin
Posts: 11
Joined: Fri Jan 13, 2012 3:30 pm
Location: Worcester, UK
Contact:

Not detecting any collisions

Post by martin »

Hi, I'm just trying out BEPU physics for the first time. The engine looks pretty awesome but I can't get it to detect any collisions in my test scene - I suspect I'm simply doing something stupid...

First some background, the scene I'm making is using BSP trees (built from Constructive Solid Geometry operations) to supply the geometry. I've implemented a StaticBsp and MobileBsp like so:

Code: Select all

private class MobileBsp<V>
    : MobileMesh, IBspMesh<V>
{
    public V[] Vertices { get; private set; }
    public int[] Indices { get; private set; }

    private MobileBsp(V[] vertices, Func<V, Vector3> positionExtractor, int[] indices, BSP bsp)
        :base(vertices.Select(v => positionExtractor(v)).ToArray(), indices, AffineTransform.Identity, MobileMeshSolidity.Solid, 1)
    {
        Vertices = vertices;
        Indices = indices;
    }

    public static MobileBsp<V> Create(BSP bsp, Func<Vector3, Vector3, V> positionNormalToVertex, Func<V, Vector3> vertexToPosition)
    {
        List<V> vertices = new List<V>();
        List<int> indices = new List<int>();

        bsp.ToTriangleList<V, int>(positionNormalToVertex,
            v =>
            {
                vertices.Add(v);
                return vertices.Count - 1;
            },
            (x, y, z) =>
            {
                indices.Add(x);
                indices.Add(y);
                indices.Add(z);
            });

        return new MobileBsp<V>(vertices.ToArray(), vertexToPosition, indices.ToArray(), bsp);
    }

    public new Matrix WorldTransform
    {
        get { return base.WorldTransform; }
    }
}
StaticBsp is almost exactly the same, except it's based on StaticMesh instead of MobileMesh.

So using these classes, I create a scene with a single static floor, and a load of mobile boxes. The boxes should fall onto the floor and stack up:

Code: Select all

Space = new BEPUphysics.Space();
Space.ForceUpdater.Gravity = new Vector3(0, -1f, 0f);

var floor = StaticBsp<VertexPositionNormalTexture>.Create(
    new Xna.Csg.Primitives.Cube().Transform(Matrix.CreateScale(10, 1, 10)),
    (p, n) => new VertexPositionNormalTexture(p, n, Vector2.Zero),
    v => v.Position
);
objects.Add(floor);
Space.Add(floor);

int count = 5;
for (int x = 0; x < count; x++)
{
    for (int y = 0; y < count; y++)
    {
        for (int z = 0; z < count; z++)
        {
            var e = MobileBsp<VertexPositionNormalTexture>.Create(
                new Xna.Csg.Primitives.Cube(),
                (p, n) => new VertexPositionNormalTexture(p, n, Vector2.Zero),
                v => v.Position
            );
            objects.Add(e);

            e.Position = new Vector3(x * 2 - count, y * 2 + 1, z * 2 - count);
            Space.Add(e);
        }
    }
}
But this doesn't work! The floating boxes fall down, straight through the floor, and keep falling forever.

So what stupid thing have I done wrong? :roll:
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Not detecting any collisions

Post by Norbo »

Grabbing the BEPUphysicsDrawer from the main source download and ensuring the collision shapes are where they are expected would be a good diagnostic.

Other than that, verify the triangle windings to make sure the boxes aren't passing through the backside of the static mesh or something. Try changing the StaticMesh's Sidedness, and possibly also try other values for the mobile mesh too. Using Solid for the mobile mesh should automatically calculate the correct sidedness, but it's possible for it to get confused with certain models.

By the way, MobileMeshes are much, much slower than primitives. If at all possible, use a simple convex shape or a combination of simple convex shapes in a compound body to represent objects. A Box entity will be more robust and about an order of magnitude more efficient than a cubic MobileMesh.
martin
Posts: 11
Joined: Fri Jan 13, 2012 3:30 pm
Location: Worcester, UK
Contact:

Re: Not detecting any collisions

Post by martin »

Thanks for the fast reply :D

I added in the BEPUphysicsDrawer which shows bounding boxes around the mobile meshes and no bounds around the static mesh - so I guess that's the problem.

I noticed that when I call Space.Add for my static object, Space.Entities.Count does not go up, is this the intended behaviour? I assume not, since BoundingBoxDrawer loops through everything in Space.Entities, and if the static object is not added to that collection then it can't possibly have its bounds drawn!

For reference, here is my implementation of StaticBsp:

Code: Select all

private class StaticBsp<V>
    : StaticMesh, IBspMesh<V>
{
    public V[] Vertices { get; private set; }
    public int[] Indices { get; private set; }

    private StaticBsp(V[] vertices, Func<V, Vector3> positionExtractor, int[] indices, BSP bsp)
        :base(vertices.Select(v => positionExtractor(v)).ToArray(), indices)
    {
        Vertices = vertices;
        Indices = indices;

        base.Sidedness = BEPUphysics.CollisionShapes.ConvexShapes.TriangleSidedness.DoubleSided;
    }

    public static StaticBsp<V> Create(BSP bsp, Func<Vector3, Vector3, V> positionNormalToVertex, Func<V, Vector3> vertexToPosition)
    {
        List<V> vertices = new List<V>();
        List<int> indices = new List<int>();

        //Fill vertices and indices with geometry data

        return new StaticBsp<V>(vertices.ToArray(), vertexToPosition, indices.ToArray(), bsp);
    }

    public new Matrix WorldTransform
    {
        get { return base.WorldTransform.Matrix; }
    }
}
}
Also, I won't be using Mobile meshes everywhere in the final game - most of the scene will be static meshes with vehicles and raycasts. Thanks for the warning though.
martindevans.appspot.com/blog
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Not detecting any collisions

Post by Norbo »

A StaticMesh is not an Entity, so the Space.Entities should not include it. That Entities collection is just a convenience property that references the set of physical Entity objects, not every object managed by the space (not every object managed by the space is stored in a way which can be conveniently iterated, or they are directly available in the relevant substages and aren't frequently referenced enough to warrant a more convenient placement, and the overarching type of ISpaceObject isn't particularly informative).

Some background: A StaticMesh is a Collidable like the Entity.CollisionInformation. The Entity object itself is not a Collidable- its most direct purpose is to manage movement and related physical properties. The Collidable returned by the Entity.CollisionInformation property is the entity's collision proxy that actually goes into collision detection pairs and contact generation systems. Collidables are BroadPhaseEntry objects and exist in the BroadPhase, looking for other BroadPhaseEntry objects to create pairs with.

I would recommend using the InstancedModelDrawer to draw the objects in the simulation so that you can see exactly what the collision shape looks like and where it is. That can identify issues that bounding boxes alone cannot.
martin
Posts: 11
Joined: Fri Jan 13, 2012 3:30 pm
Location: Worcester, UK
Contact:

Re: Not detecting any collisions

Post by martin »

Aha, I think I'm on the track to finding my problem :D

I tried to add the StaticBsp to the InstancedModelDrawer directly, and it didn't work. I tracked this down to this line:

Code: Select all

if (displayTypes.TryGetValue(objectToDisplay.GetType(), out displayType))
Now of course the type I've passed in is not directly a known type. Really, you need to check if every type in the inheritance chain of the unknown type is known (possibly that also requires a split if it implements interfaces and if you care about interfaces). e.g. This is some code taken from my game engine which is performing almost exactly the same function (it does not consider interfaces):

Code: Select all

var fooType = typeof(foo);
while (fooType.IsAssignableFrom(behaviourType))
{
    if ( /* is this some known type? */ )
        return /* The method for handling this known type */

    //it's not known, keep hunting
    fooType = fooType.BaseType;
}
Given this hint, I replaced all instances of StaticBsp with StaticMesh in my simulation, suddenly it works! So, I suspect somewhere internal to the engine you're using this same reflection methodology and it's throwing away my StaticBsp as an unknown type. Unfortunately, I can't track down where exactly inside Space.Add it's going wrong, it may not even be in there!

Anyway, thanks for your help, now that I know this I can restructure my system a little to hand in vanilla StaticMesh instances instead of subclassing StaticMesh.
martindevans.appspot.com/blog
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Not detecting any collisions

Post by Norbo »

Sorry, I wasn't reading close enough to notice the inheritance earlier :)

Space.Add does not use specific types. It checks to see if an object implements various interfaces or inherits from some class and sends it to relevant systems. The narrow phase, on the other hand, relies on specific type pairs and will not understand the subclass type without prompting. Simplicity is key for this system due to its frequency of use, and the type pair model more closely matches the intended use of collision pair handlers.

Technically, the relevant type pairs could be added to the NarrowPhaseHelper listings, but I generally advise against subclassing physics types except in a few advanced usage scenarios (such as when physical behavior actually changes). It is generally more work than it's worth to subclass physics engine types as it can add in extra initialization confusion and usually breaks the separation between physics objects and other logic.
martin
Posts: 11
Joined: Fri Jan 13, 2012 3:30 pm
Location: Worcester, UK
Contact:

Re: Not detecting any collisions

Post by martin »

No worries :)

With hindsight subclassing the meshes was a pretty weird choice which is easy enough to fix. Thanks for your fast help Norbo.
martindevans.appspot.com/blog
Post Reply