Compound Body Problems

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
sfxman
Posts: 15
Joined: Sat Sep 18, 2010 1:28 am

Compound Body Problems

Post by sfxman »

Hi,

I'm trying to solve a problem I've had for a while with compound bodies...

My setup has a compound body that I create from a list of CompoundShapeEntries that all have various positions, masses and dimensions.
The main body is the heaviest, and the other bodies are lighter and used for collision purposes (scattered around the main shape).

The issue is that the position of the shapes that are rendered by the model drawer are not matching the ones that I render myself, so things touch the ground when they shouldn't be...
I looked at the code that creates the shapes inside the compound body and it seems to move things around a center of mass.
It probably explains why moving the heavy body around moves all the smaller shapes around...

There must be something I don't quite understand with this :)
How can I make sure that the position of the compound shape children match what I have set in the CompoundShapeEntries?

Thanks
Matt
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Compound Body Problems

Post by Norbo »

How can I make sure that the position of the compound shape children match what I have set in the CompoundShapeEntries?
If you're creating a prefab-type CompoundBody, the final location of the compound children should be at the same locations as the compound shape entries defined. However, in the compound shape, the entries get recentered. This means their local positions are relative to the center of mass. The center of mass computed between all the shapes is then used to position the entity, so that everything is in the right place.

Here's an example out of the CompoundBodiesDemo:

Code: Select all

            var bodies = new List<CompoundShapeEntry>() 
            {
                new CompoundShapeEntry(new SphereShape(.5f), new Vector3(0, 5, 0), 1),
                new CompoundShapeEntry(new ConeShape(2, .5f), new Vector3(1, 5, 0), 1),
                new CompoundShapeEntry(new SphereShape(.5f), new Vector3(-1, 5, 0), 1)
            };
            var cb1 = new CompoundBody(bodies, 45);
Checking cb1.CollisionInformation.Children[0].Entry.LocalTransform.Position gives (0,0,0). Children[1] is at (1,0,0), and Children[2] is at (-1,0,0). The Position of the cb1 entity is (0, 5, 0). If the entity's position is added to the local entry transforms, the original positions are found.

When not using the prefab CompoundBody entity type, you can retrieve the world space center of mass of the compound by using a CompoundShape or CompoundCollidable constructor which outputs the center. That's what the CompoundBody uses internally to position itself.

The remaining trick is to figure out where to put your graphics. If the models aren't aligned in the same way (centered on centers of mass), then the model will appear offset. To fix this, that offset needs to be computed. There's a few ways to do this. One way is to figure out where the center of mass is on the physical shape (as done above), and compare it to where the origin is on the model. Apply that offset as a local transformation before rendering.

You can use the BEPUphysicsDrawer to test and verify the results.
sfxman
Posts: 15
Joined: Sat Sep 18, 2010 1:28 am

Re: Compound Body Problems

Post by sfxman »

Thanks for your reply :)
Checking cb1.CollisionInformation.Children[0].Entry.LocalTransform.Position gives (0,0,0). Children[1] is at (1,0,0), and Children[2] is at (-1,0,0). The Position of the cb1 entity is (0, 5, 0). If the entity's position is added to the local entry transforms, the original positions are found.
I'm confused... is everything based of the 1st shape you add? If the local transformation of Child[0] is (0,0,0) is appears to be the case, is that correct?

The position of cb1 being (0,5,0) is because the 1st shape there? What if you inverse the order of the shape creation is the outcome going to be different?

Here's what my setup looks like:

Code: Select all

var bodies = new List<CompoundShapeEntry>() 
{
     new CompoundShapeEntry(new BoxShape(5,5,25), new Vector3(0, 0, 0), 1000), //main heavy body
     new CompoundShapeEntry(new BoxShape(1,1,3), new Vector3(10, 0, 0), 100), // lighter side body
     new CompoundShapeEntry(new BoxShape(1,1,2), new Vector3(-10, 0, 0), 100) // other lighter side body
};

var cb1 = new CompoundBody(bodies, 1200);
I put this body in a vehicle onto which I have set up wheels. When I set the shapes to where they should be (matching my model in the 3D design tool) they end up too low to the ground and consequently, the wheels don't touch the ground anymore... Is this because I set weights to the CompoundShapeEntries? (your example has 1 for all of them)
What's odd is that when I move the heavy body up (change its Y value) it stays at the same location, but the two side bodies move up... is that expected from what you explained? (I used BEPUphysicsDrawer to verify this)
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Compound Body Problems

Post by Norbo »

is everything based of the 1st shape you add?
Nope, it's based on the center of mass. It just so happens that the first shape's position also aligned with the center of mass. Since the positions specified are the centers of mass of the constituent shapes, and they have equal weight, the center of mass of that compound was just the average of the three points.

Here's another example. It's almost the same, but the weight of the last shape has been increased a huge amount.
var bodies = new List<CompoundShapeEntry>()
{
new CompoundShapeEntry(new SphereShape(.5f), new Vector3(0, 5, 0), 1),
new CompoundShapeEntry(new ConeShape(2, .5f), new Vector3(1, 5, 0), 1),
new CompoundShapeEntry(new SphereShape(.5f), new Vector3(-1, 5, 0), 1000)
};
var cb1 = new CompoundBody(bodies, 45);
This demonstrates how the weighted average works. cb1.Position is {X:-0.997006 Y:5 Z:0}. The local offsets are:
[0]: {X:0.997006 Y:0 Z:0}
[1]: {X:1.997006 Y:0 Z:0}
[2]: {X:-0.002994001 Y:0 Z:0}

Adding everything up still comes out to the correct world space positions. However, now that the weight is so high for the last entry, the center of mass is almost aligned with the last shape! This is also reflected in the calculation of the inertia tensor, which puts 1000/1002 of the mass on the last sphere, and 1/1002 for the other two shapes.

The order of entries isn't considered when computing the center of mass or anything else.
What's odd is that when I move the heavy body up (change its Y value) it stays at the same location, but the two side bodies move up... is that expected from what you explained?
The final world space positions will all be in the expected locations. However, the local space positions are based around the compound body's center of mass. Moving the heavy middle object upward moves the center of mass upward almost as much as the heavy object moves, since it's such a significant part of the total weight. Relative to the center of mass, the two light objects are lower now in local space.

It may help to visualize this situation in the extreme case- imagine the middle object had very nearly 100% of the total weight, so that shape's center was also the compound's center. If you move the heavy object up but keep the light objects stationary, it's equivalent to moving the two nearly weightless shapes down (in local space).
Post Reply