Optimizing Block Based Multi-Body Vehicle

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
Socram
Posts: 20
Joined: Sat Sep 24, 2011 4:33 am

Optimizing Block Based Multi-Body Vehicle

Post by Socram »

So I'm creating a game that involves designing and building vehicles from block based components, each block existing as it's own body and needing to interact with the world. The video demonstrates this:

http://www.youtube.com/watch?v=hh96ayBm ... r_embedded

Currently I weld all the blocks in the vehicle to a single parent block that the vehicle is built around. I have removed collisions between blocks on the vehicle. This creates a very unstable and shaky car that likely will not hold up to rough terrain very well and just in general looks kind of silly. I'm trying to figure out a better method for constructing the car and simulating it, that is both stable and allows me to remove individual blocks dynamically if I need to.

Things I'm Considering:

1) More welds between more blocks. I have a feeling this will create a more stable vehicle that is less shaky, but maybe be too expensive or freak out in high energy collisions? (Tried this now, seemed very stable at first then this is eventual result: http://screencast.com/t/uGwAZrct9u. Multiple welds definitely started out much more stable and solid, but even at extremely low Spring Constant and Damping Constant the set of blocks begins to shake after receiving large force which eventually degrades into an extremely unstable simulation, with blocks flying all over the place. I also played with mass to make sure the vehicle wasn't too heavy for the wheels.) Any other ideas?

2) Creating a compound body that matches the shape of the vehicle. Can I utilize this and still make it possible for individual blocks to break off or be removed and interact with environment?

3) Something you suggest Norbo. :)

Thanks for your time, I hope this all makes sense.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Optimizing Block Based Multi-Body Vehicle

Post by Norbo »

The problem with the first version was indeed the all-welds-on-one-box construction method. The involved lever arms would be quite long, requiring more iterations to get stable.

1) More welds will help, but only if they are put in the right place. More welds in the wrong spots can cause instability, as you noticed :)

Using just the grid itself to do the connections will work quite well:

Code: Select all

            var boxes = new Box[10, 10];
            CollisionGroup group = new CollisionGroup();
            CollisionGroup.DefineCollisionRule(group, group, CollisionRule.NoBroadPhase);
            for (int i = 0; i < boxes.GetLength(0); i++)
            {
                for (int j = 0; j < boxes.GetLength(1); j++)
                {
                    boxes[i, j] = new Box(new Vector3(i, 200, j), 1, 1f, 1, 1);
                    boxes[i, j].CollisionInformation.CollisionRules.Group = group;
                    Space.Add(boxes[i, j]);
                }
            }
            for (int i = 0; i < boxes.GetLength(0); i++)
            {
                for (int j = 0; j < boxes.GetLength(1); j++)
                {
                    if (i + 1 < boxes.GetLength(0))
                    {
                        var weld = new WeldJoint(boxes[i, j], boxes[i + 1, j]);
                        weld.BallSocketJoint.SpringSettings.StiffnessConstant = 10000;
                        weld.BallSocketJoint.SpringSettings.DampingConstant = 2000;
                        weld.NoRotationJoint.SpringSettings.StiffnessConstant = 10000;
                        weld.NoRotationJoint.SpringSettings.DampingConstant = 2000;
                        Space.Add(weld);
                    }
                    if (j + 1 < boxes.GetLength(1))
                    {
                        var weld = new WeldJoint(boxes[i, j], boxes[i, j + 1]);
                        weld.BallSocketJoint.SpringSettings.StiffnessConstant = 10000;
                        weld.BallSocketJoint.SpringSettings.DampingConstant = 2000;
                        weld.NoRotationJoint.SpringSettings.StiffnessConstant = 10000;
                        weld.NoRotationJoint.SpringSettings.DampingConstant = 2000;
                        Space.Add(weld);
                    }
                }
            }
One caveat, though! It turns out the NoRotationJoint had a long-hidden flipped negative sign that makes soft instances extremely unstable. You could replace it with an AngularMotor in servo mode; it accomplishes basically the same thing at a slightly higher cost. Or, you can download the latest development version which fixes this problem:
http://bepuphysics.codeplex.com/SourceC ... evelopment

2) Using a CompoundBody would certainly make the structure rigid. Splitting a compound efficiently is quite easy with the CompoundHelper's methods. The CompoundHelper was implemented to deal with splitting huge compound bodies during prototype fracture simulations. It doesn't explicitly support putting stuff back together, though; that would require creating a new compound body at this point (or fiddling around with the CompoundHelper's inner workings to add a reconstruction method). A CompoundBody would also be 'faster' overall, but it doesn't quite have the same effect as a constrained system with its slight springiness.

3) Instability can be reduced by increasing the Space.Solver.IterationLimit and decreasing the Space.TimeStepSettings.TimeStepDuration. These both cost more computation, but they're easy to change if you end up getting close to what you want and just want to tune it a bit.
Socram
Posts: 20
Joined: Sat Sep 24, 2011 4:33 am

Re: Optimizing Block Based Multi-Body Vehicle

Post by Socram »

Okay well... I've implemented it into my program and it starts out fairly stable, and then proceeds to freak out per usual, if anything more violently than before. Just my luck ha. Here's my code:

Code: Select all

public void WeldVehicle()
        {
            for (int i = 0; i < VehicleMaxDim; i++)
            {
                for (int j = 0; j < VehicleMaxDim; j++)
                {
                    for (int k = 0; k < VehicleMaxDim; k++)
                    {
                        var curEnt = EntityArray[i, j, k];
                        if (EntityArray[i, j, k] != null)
                        {
                            //Block Above Exists? Then Weld.
                            if (HasNeighbor(Vector3.Up, new Vector3(i, j, k)))
                            {
                                var weld = new WeldJoint(EntityArray[i,j,k].GetBody(), EntityArray[i, j+1, k].GetBody());
                                weld.BallSocketJoint.SpringSettings.StiffnessConstant = 10000;
                                weld.BallSocketJoint.SpringSettings.DampingConstant = 2000;
                                weld.NoRotationJoint.SpringSettings.StiffnessConstant = 10000;
                                weld.NoRotationJoint.SpringSettings.DampingConstant = 2000;
                                Game1.Space.Add(weld);
                            }
                            //Block Right Exists? Then Weld.
                            if (HasNeighbor(Vector3.Right, new Vector3(i, j, k)))
                            {
                                var weld = new WeldJoint(EntityArray[i, j, k].GetBody(), EntityArray[i+1, j, k].GetBody());
                                weld.BallSocketJoint.SpringSettings.StiffnessConstant = 10000;
                                weld.BallSocketJoint.SpringSettings.DampingConstant = 2000;
                                weld.NoRotationJoint.SpringSettings.StiffnessConstant = 10000;
                                weld.NoRotationJoint.SpringSettings.DampingConstant = 2000;
                                Game1.Space.Add(weld);
                            }
                            //Block Backward Exists? Then Weld.
                            if (HasNeighbor(Vector3.Backward, new Vector3(i, j, k)))
                            {
                                var weld = new WeldJoint(EntityArray[i, j, k].GetBody(), EntityArray[i, j, k+1].GetBody());
                                weld.BallSocketJoint.SpringSettings.StiffnessConstant = 10000;
                                weld.BallSocketJoint.SpringSettings.DampingConstant = 2000;
                                weld.NoRotationJoint.SpringSettings.StiffnessConstant = 10000;
                                weld.NoRotationJoint.SpringSettings.DampingConstant = 2000;
                                Game1.Space.Add(weld);
                            }
                        }
                    }
                }

            }
        }
It works (or at least it is supposed to work) exactly as yours does. It iterates through the 3D array, and then checks if each block has a neighbor to the front, up, and right. If it finds a neighbor it makes a weld. If not, nothing happens. Let me know if you see any issues. I even lowered all the constants to 2000 but things still blow out of control.

Oh and I took care of removing intergroup collisions elsewhere which is why you don't see it in the code. The average vehicle creates about 20 or so welds.
Socram
Posts: 20
Joined: Sat Sep 24, 2011 4:33 am

Re: Optimizing Block Based Multi-Body Vehicle

Post by Socram »

Well on a whim (and going against your advice) I set both constants to 200,000. This yields so far extremely stable vehicles, even with many parts and after twisting the vehicle around and applying much force to it. I'm going to stick with this value for the time being and do some more testing.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Optimizing Block Based Multi-Body Vehicle

Post by Norbo »

Was that test with the new development version? From the previous post:
One caveat, though! It turns out the NoRotationJoint had a long-hidden flipped negative sign that makes soft instances extremely unstable. You could replace it with an AngularMotor in servo mode; it accomplishes basically the same thing at a slightly higher cost. Or, you can download the latest development version which fixes this problem:
http://bepuphysics.codeplex.com/SourceC ... evelopment
Making things softer should never result in greater instability, just greater... softness. :)
Socram
Posts: 20
Joined: Sat Sep 24, 2011 4:33 am

Re: Optimizing Block Based Multi-Body Vehicle

Post by Socram »

Yes I *think* I've upgraded to the latest version. Is there an easy way to verify? I'm a little new to compiling libraries and such so maybe I messed something up, and somehow left the old library behind?

Lots of testing have so far shown that the low values were super unstable, and these new really high values are crazy stable. I'm flipping vehicles all over the place and it's staying together magnitudes better than any other values.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Optimizing Block Based Multi-Body Vehicle

Post by Norbo »

The development version is a source-only download, in its own fork. If you downloaded off the main downloads section or the primary source section, then you have the standard v1.0.0 release, not the development version.

The latest development changeset id is 2ba6404ede4a. Edit: Using TortoiseHG to pull down updates would be the easiest method of keeping up with source changes.
Socram
Posts: 20
Joined: Sat Sep 24, 2011 4:33 am

Re: Optimizing Block Based Multi-Body Vehicle

Post by Socram »

I think I compiled a .DLL with the given source code and am using that, but knowing my luck I messed something up with that. I'll hook it up with TortoiseHg and verify that I have the latest revision and let you know if it fixes the low constant instability. But like I said, I've been doing a lot of testing with the high values and have had no issues with instability. It's working really well so far, I'm excited! This was a rather annoying roadblock for the game ha.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Optimizing Block Based Multi-Body Vehicle

Post by Norbo »

It's good that you have something that works, but if you were seeing instability with softer values, it just means the instability bug is still hiding and will probably crop up later :) I haven't reproduced any instability with the latest version, so I'm hoping that'll be it.
Socram
Posts: 20
Joined: Sat Sep 24, 2011 4:33 am

Re: Optimizing Block Based Multi-Body Vehicle

Post by Socram »

So I feel dumb asking such a general question here, but I can't seem to find help on this any where else or figure it out on my own.

How do I use the latest revision? Like integrate it like the .DLL was? I can't seem to figure this out for the life of me...
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Optimizing Block Based Multi-Body Vehicle

Post by Norbo »

Once you have the source, you can compile it in release/x86 or whatever you need and grab the .dll it spits out. It'll be in the (solution directory)\BEPUphysics\bin\(platform)\Release folder. You want the BEPUphysics.xml and BEPUphysics.dll file. You can copy them somewhere and then reference them in your project like the precompiled download.

You could also pull the BEPUphysics project itself over into your solution and reference the project. This would require a little more fiddling, but may be easier in some cases.
Post Reply