Compound Bodies

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

Compound Bodies

Post by sfxman »

Hello Norbo,

First of, thanks again for this awesome library! I still can't believe this is in C# and so efficient :)

I had asked a question about this a while ago, and I'm still very confused about the mass/transforms implications in CompoundBodies.

What I'm trying to do is have a vehicle that has weights unevenly placed on its chassis, kind of like a tank with a heavy plate in the back side.

I modified the vehicle in the demos to show what I want to achieve:
http://i.imgur.com/RrQDk.png

In this example, the top box's mass is still set to the default of 1.0 while the bottom box is at 60 like in the demo.

Now, I'd like to make the top box so it weights a lot more, about 60 as well. Unfortunately, when I do this, here is what is looks like:
http://i.imgur.com/6L8FM.png

Reading the doc and other forum posts, this behavior is expected, but I'm not sure how to make it so the car wheels are still in the correct position in relation to the boxes.
How would you modify the sample so it would look like my 1st screenshot (wheels correctly placed), but with the back side suspension being more compressed due to the weight of the second box.

Just in case, here's the code I have for the modified demo vehicle:

Code: Select all

var bodies = new List<CompoundShapeEntry>()
{
      new CompoundShapeEntry(new BoxShape(2.5f, .75f, 4.5f), new Vector3(0, 0, 0), 60),
      new CompoundShapeEntry(new BoxShape(2.5f, .3f, 2f), new Vector3(0, .75f / 2 + .3f / 2, 3.5f), 60)
};
var body = new CompoundBody(bodies, 120);
Thanks!
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Compound Bodies

Post by Norbo »

The center of a compound shape can be computed as:
(shape1Center * shape1Weight + shape2Center * shape2Weight + ... + shapeNCenter * shapeNWeight) / (shape1Weight + shape2Weight + ... + shapeNWeight)

So, using the default bodies:

Code: Select all

            var bodies = new List<CompoundShapeEntry>
            {
                new CompoundShapeEntry(new BoxShape(2.5f, .75f, 4.5f), new Vector3(0, 0, 0), 60),
                new CompoundShapeEntry(new BoxShape(2.5f, .3f, 2f), new Vector3(0, .75f / 2 + .3f / 2, .5f), 1)
            };
The center position is ((0,0,0) * 60 + (0, .75f / 2 + .3f / 2, .5f) * 1) / (60 + 1) = (0, 0.008606557f, 0.008196721f)

This can be verified by checking the body.Position immediately after creation (the compound shape is recentered around zero; the recentering offset is used as the entity position so that the shape is in the same spot in world space).

Using the same approach for the modified body:

Code: Select all

            var bodies = new List<CompoundShapeEntry>
            {
                  new CompoundShapeEntry(new BoxShape(2.5f, .75f, 4.5f), new Vector3(0, 0, 0), 60),
                  new CompoundShapeEntry(new BoxShape(2.5f, .3f, 2f), new Vector3(0, .75f / 2 + .3f / 2, 3.5f), 60)
            };
The center position is ((0,0,0) * 60 + (0, .75f / 2 + .3f / 2, 3.5f) * 60) / (60 + 60) = (0, 0.2625f, 1.75f)

Once again, this can be verified by checking the body.Position after construction.

The positions of wheels are specified relative to the center of the entity. So, to put the wheels in the same spot relative to the bottom box of the compound shape as they are in the unmodified shape, they must be scooted using the offset oldCenter - newCenter.

Here's the complete modified initialization. Note that this uses the in-development version; the CylinderCastWheelShape does not exist in the main branch.

Code: Select all

            var bodies = new List<CompoundShapeEntry>
            {
                  new CompoundShapeEntry(new BoxShape(2.5f, .75f, 4.5f), new Vector3(0, 0, 0), 60),
                  new CompoundShapeEntry(new BoxShape(2.5f, .3f, 2f), new Vector3(0, .75f / 2 + .3f / 2, 3.5f), 60)
            };

            var body = new CompoundBody(bodies, 120);
            var originalCenter = new Vector3(0, 0.008606557f, 0.008196721f);
            var modifiedCenter = body.Position;
            var wheelOffset = originalCenter - modifiedCenter;

            body.CollisionInformation.LocalPosition = new Vector3(0, .5f, 0);
            body.Position = position; //At first, just keep it out of the way.
            Vehicle = new Vehicle(body);

            var localWheelRotation = Quaternion.CreateFromAxisAngle(new Vector3(0, 0, 1), MathHelper.PiOver2);

            //The wheel model used is not aligned initially with how a wheel would normally look, so rotate them.
            Matrix wheelGraphicRotation = Matrix.CreateFromAxisAngle(Vector3.Forward, MathHelper.PiOver2);
            Vehicle.AddWheel(new Wheel(
                                 new CylinderCastWheelShape(.375f, 0.2f, localWheelRotation, wheelGraphicRotation, false),
                                 new WheelSuspension(2000, 100f, Vector3.Down, .8f - .375f, new Vector3(-1.1f, 0, 1.8f) + wheelOffset),
                                 new WheelDrivingMotor(2.5f, 30000, 10000),
                                 new WheelBrake(1.5f, 2, .02f),
                                 new WheelSlidingFriction(4, 5)));
            Vehicle.AddWheel(new Wheel(
                                 new CylinderCastWheelShape(.375f, 0.2f, localWheelRotation, wheelGraphicRotation, false),
                                 new WheelSuspension(2000, 100f, Vector3.Down, .8f - .375f, new Vector3(-1.1f, 0, -1.8f) + wheelOffset),
                                 new WheelDrivingMotor(2.5f, 30000, 10000),
                                 new WheelBrake(1.5f, 2, .02f),
                                 new WheelSlidingFriction(4, 5)));
            Vehicle.AddWheel(new Wheel(
                                 new CylinderCastWheelShape(.375f, 0.2f, localWheelRotation, wheelGraphicRotation, false),
                                 new WheelSuspension(2000, 100f, Vector3.Down, .8f - .375f, new Vector3(1.1f, 0, 1.8f) + wheelOffset),
                                 new WheelDrivingMotor(2.5f, 30000, 10000),
                                 new WheelBrake(1.5f, 2, .02f),
                                 new WheelSlidingFriction(4, 5)));
            Vehicle.AddWheel(new Wheel(
                                 new CylinderCastWheelShape(.375f, 0.2f, localWheelRotation, wheelGraphicRotation, false),
                                 new WheelSuspension(2000, 100f, Vector3.Down, .8f - .375f, new Vector3(1.1f, 0, -1.8f) + wheelOffset),
                                 new WheelDrivingMotor(2.5f, 30000, 10000),
                                 new WheelBrake(1.5f, 2, .02f),
                                 new WheelSlidingFriction(4, 5)));
sfxman
Posts: 15
Joined: Sat Sep 18, 2010 1:28 am

Re: Compound Bodies

Post by sfxman »

Thanks! You're awesome :)

I'll try this as soon as I wake up tomorrow and will report back here :)
sfxman
Posts: 15
Joined: Sat Sep 18, 2010 1:28 am

Re: Compound Bodies

Post by sfxman »

It works perfectly!

I adapted it to our engine, had to tweak the rendering and other parts of the code that relied on the body transform to make them match the new offset.

You're the best, thanks again for this awesome library!
Post Reply