Page 1 of 2
Compound B can't hold entities as angular velocity increases
Posted: Wed Nov 24, 2010 6:45 pm
by Spankenstein
I've created a spherical compound body from a series of triangles that will keep entities inside itself when motionless.
I then apply a steady increase in angular velocity to the compound body each frame:
The velocity depends on the delta time for the frame.
As the velocity increases the contained bodies will escape out of the container, even at relatively low velocities.
Why is this happening?
Re: Compound B can't hold entities as angular velocity increases
Posted: Wed Nov 24, 2010 11:00 pm
by Norbo
If I'm understanding the situation correctly, it's because the frame displacement of each object is high enough such that it can tunnel outside of the thin triangulated shell during a single frame. It doesn't need to be able to get all the way through; if it makes it out a little past halfway, it will be pushed out. This would require some pretty hefty piecewise linear velocity on the contained spheres though (at least 30 units per second for a 1 unit diameter sphere, probably higher).
If velocities are the issue, you have a few options. First, try enabling continuous collision detection by setting Space.SimulationSettings.CollisionDetection.CollisionDetectionType to LinearContinuous instead of MPRGJK. This will prevent spheres inside from being integrated beyond a possible collision. Note that if the problem is not velocity based, this won't help a whole lot.
Another option is decreasing the time step duration by setting the Space.SimulationSettings.TimeStep.TimeStepDuration to something lower than 1/60f. That will make each step taken by the Update method smaller, improving simulation stability overall at the cost of a nearly proportional performance hit. You'll also need to update the engine more often in order to keep it running at real time if you shrink the time step. If you set it to 1/120, updating it twice per fixed update will do the trick. If it's not an easy multiple, you could also set Space.SimulationSettings.TimeStep.UseInternalTimeStepping to true. The engine will take however many steps are necessary to keep up with real time.
Finally, if the issue is solver-based due to a difficult simulation, you can try increasing the number of iterations to improve stability. You can find that setting at Space.SimulationSettings.CollisionResponse.Iterations. It defaults to 10; try increasing it to 15 or 20 and see what happens.
Re: Compound B can't hold entities as angular velocity increases
Posted: Wed Nov 24, 2010 11:57 pm
by Spankenstein
Currently I am using:
Code: Select all
space.SimulationSettings.TimeStep.UseInternalTimeStepping = true;
The update is called in the Update() method depending on the frame rate (which is around 500FPS). Do I need to change the TimeStepDuration in this case?
Unfortunately continuous collision detection and a higher number of collision response iterations have made no difference to the stability in this scenario.
I can post a video to YouTube if that helps?
My CompoundBody is created as follows:
Code: Select all
public CompoundBodyObject(Game1 game, ModelData modelData, float scale, Vector3 position)
{
this.game = game;
this.modelData = modelData;
this.scale = scale;
int numTriangles = modelData.Triangles.Count;
List<Entity> triangles = new List<Entity>(numTriangles);
Matrix m = Matrix.CreateScale(scale);
for (int i = 0; i < numTriangles; ++i)
{
triangles.Add(new Triangle(
Vector3.Transform(modelData.Triangles[i].A, m),
Vector3.Transform(modelData.Triangles[i].B, m),
Vector3.Transform(modelData.Triangles[i].C, m),
1
));
}
body = new CompoundBody(triangles);
Matrix worldTransform = Matrix.Identity;
worldTransform.M41 = position.X;
worldTransform.M42 = position.Y;
worldTransform.M43 = position.Z;
body.WorldTransform = worldTransform;
// Setup function for handling collision detection (do last)
body.EventManager.InitialCollisionDetected += HandleCollision;
game.Space.Add(body);
}
EDIT: Setting the TimeStepDuration to a smaller value doesn't make any difference in this scenario either.

Re: Compound B can't hold entities as angular velocity increases
Posted: Thu Nov 25, 2010 12:17 am
by Norbo
I'm surprised changing the time step duration didn't help. It's the sledgehammer of stability solutions, so if it doesn't help the behavior, there's probably something goofy going on. A video would indeed help me understand the behavior better.
Re: Compound B can't hold entities as angular velocity increases
Posted: Thu Nov 25, 2010 12:18 am
by RyanGadz
i am using:
space.SimulationSettings.TimeStep.TimeStepDuration = 1 / 120f;
and
space.SimulationSettings.TimeStep.UseInternalTimeStepping = true;
...is that redundant? i played with the settings a lot here and that seems to work best for me.. shrug.
Re: Compound B can't hold entities as angular velocity increases
Posted: Thu Nov 25, 2010 12:21 am
by Norbo
They are not redundant; the time step duration is the length of a single time step. A time step integrates the simulation forward by the time step duration.
Internal time stepping means the engine will take as many time steps are necessary to catch up with real time, as defined by the 'since last frame' time you pass into the Space.Update method. If it was off, the simulation's speed would vary based on the update rate of the game.
Re: Compound B can't hold entities as angular velocity increases
Posted: Thu Nov 25, 2010 1:51 am
by Spankenstein
A video showing what is going on can be found at
http://www.youtube.com/watch?v=m9iPZIeUXUw
If that doesn't help then I can send a concise version of the code?
Re: Compound B can't hold entities as angular velocity increases
Posted: Thu Nov 25, 2010 1:59 am
by RyanGadz
i encountered a similar problem where it was a balance between the speed and time step duration.
yours has a lot more going on and faster so increasing the time step to something really really high might limit your performance
something you could try would be to reset an object if it goes too far from the center. or "transport" it to the last safe or believable position.
Re: Compound B can't hold entities as angular velocity increases
Posted: Thu Nov 25, 2010 2:45 am
by Norbo
The process goes something like this:
-The object is in contact with the sphere triangles. CCD cannot help much because the objects are already in contact.
-The speed increases. Entities are integrated each frame with a displacement on a surface tangent of the sphere. This means their distance from the sphere's center increases each frame.
-At a certain speed, the penetration recovery system cannot pull the objects back into the sphere fast enough.
-After a few frames at this speed, the objects tunnel halfway through the triangle and can then escape.
The sledgehammer approach of changing the timestep can fix this, though it must be decreased more and more to support higher speeds. If 1/60 works for 1 radian/second, you might have to use 1/300 for 5 radians/second.
It's possible to increase the rate at which the engine will correct penetrations. Try increasing the Space.SimulationSettings.CollisionResponse penetration recovery stiffness (defaults to .2f, max is 1, wouldn't recommend going close to 1) and maximum correction speed (starts at 2, might try making it unlimited).
You could also create a DistanceLimit between the center of the sphere and the center of objects. Pick some radius a little smaller than the sphere that still allows the objects to collide with the sphere. This might help a little, but if the objects still escape, they'll be stuck on the outside of the sphere with the constraint trying to pull them through the triangles. v0.15.0's option of one-sided triangles will make this solution more useful.
Re: Compound B can't hold entities as angular velocity increases
Posted: Thu Nov 25, 2010 12:54 pm
by Spankenstein
One sided triangles and a swept test would probably be the answer then. I read the Version Roadmap to v0.15, is this going to be available fairly soon? It looks pretty exciting from a developer point of view.
If I decrease the TimeStepDuration beyond 1 / 180f then the programme becomes unusable (< 24 FPS) but the objects stay inside the sphere.
Setting the PenetrationRecoveryStiffness around 0.5f and MaximumPositionCorrectionSpeed to float.Max didn't make any discernible difference to the simulation.
You could also create a DistanceLimit between the center of the sphere and the center of objects.
If I removed the triangles completely would this give the effect of spherical containment? Very much like a swept sphere test but checking if the contained shapes are outside the sphere's radius?
Re: Compound B can't hold entities as angular velocity increases
Posted: Thu Nov 25, 2010 8:10 pm
by Norbo
Swept tests are already included (continuous collision detection), but they don't help much if things are in constant contact. Once they are in a colliding state it's up to the other systems to handle it.
I read the Version Roadmap to v0.15, is this going to be available fairly soon?
Yes, fairly soon, but still no exact date.
If I removed the triangles completely would this give the effect of spherical containment?
With just a constraint, the attached points on the contained objects would be stuck in the sphere, yes. However, they will not collide with the implicit surface- boxes will freely rotate. With just spheres, it won't really be noticeable.
The best solution, disregarding difficulty, is a custom hollow sphere shape. You could give it thickness, preventing this problem almost entirely. The collision detection gets a bit more complicated if you're using shapes other than spheres, though.
Re: Compound B can't hold entities as angular velocity increases
Posted: Thu Nov 25, 2010 8:32 pm
by Spankenstein
The best solution, disregarding difficulty, is a custom hollow sphere shape. You could give it thickness, preventing this problem almost entirely. The collision detection gets a bit more complicated if you're using shapes other than spheres, though.
Is this option available in the current version?
As for one sided triangles, does the collision test involve testing against the triangle plane?
Re: Compound B can't hold entities as angular velocity increases
Posted: Thu Nov 25, 2010 9:02 pm
by Norbo
It is 'available' in the current version, though it is harder. The engine supports custom entity types and custom collision handling delegates so it could be done.
As for one sided triangles, does the collision test involve testing against the triangle plane?
At some points, yes. The sidedness is determined by winding. You can choose a "cull mode" for a mesh; 'culled' faces can be passed through.
Re: Compound B can't hold entities as angular velocity increases
Posted: Thu Nov 25, 2010 11:09 pm
by Spankenstein
If I am dealing with a mesh but as a list of entities:
Code: Select all
List<Entity> triangles = new List<Entity>(numTriangles);
Matrix m = Matrix.CreateScale(scale);
for (int i = 0; i < numTriangles; ++i)
{
triangles.Add(new Triangle(
Vector3.Transform(modelData.Triangles[i].A, m),
Vector3.Transform(modelData.Triangles[i].B, m),
Vector3.Transform(modelData.Triangles[i].C, m),
1
));
}
How would I change the cull mode for a triangle?
If that isn't possible then I guess a custom entity type is the only way forwards. I've created the class:
Code: Select all
class CustomHollowSphere : Entity
{
public CustomHollowSphere()
{
}
protected override void Initialize(bool physicallySimulated)
{
throw new NotImplementedException();
}
public override void GetExtremePoint(ref Microsoft.Xna.Framework.Vector3 d, ref Microsoft.Xna.Framework.Vector3 positionToUse, ref Microsoft.Xna.Framework.Quaternion orientationToUse, float margin, out Microsoft.Xna.Framework.Vector3 extremePoint)
{
throw new NotImplementedException();
}
public override void GetExtremePoints(ref Microsoft.Xna.Framework.Vector3 d, out Microsoft.Xna.Framework.Vector3 min, out Microsoft.Xna.Framework.Vector3 max, float margin)
{
throw new NotImplementedException();
}
public override void GetExtremePoints(ref Microsoft.Xna.Framework.Vector3 d, ref Microsoft.Xna.Framework.Vector3 positionToUse, ref Microsoft.Xna.Framework.Quaternion orientationToUse, out Microsoft.Xna.Framework.Vector3 min, out Microsoft.Xna.Framework.Vector3 max, float margin)
{
throw new NotImplementedException();
}
}
Could you please tell me how I can add custom collision handling delegates? Will this also require my own custom collision algorithms?
Re: Compound B can't hold entities as angular velocity increases
Posted: Thu Nov 25, 2010 11:38 pm
by Norbo
The one sided triangles and cullmodes are a v0.15.0 feature, so you can't change them now. In v0.15.0, meshes and individual triangle entities will have a TriangleCullMode property.
You can find the special case handlers dictionary at Space.SimulationSettings.CollisionDetection.SpecialCaseCollisionDetectionHandlers. You will need to create a handler for every entity type pair that you will be using (e.g. hollow-sphere, hollow-box, etc.).
For simplicity, let's assume that your shape can only be kinematic. That way, we don't have to worry about inertia tensor calculations. Put this in your initialize method:
Code: Select all
ForceBoundingBoxRefit(0);
InitializeNonDynamicData();
maximumRadiusFromCenterPosition = outerRadius;
maximumRadius = maximumRadiusFromCenterPosition + centerOfMassOffset.Length();
For the get extreme points methods, normalize the direction and multiply it by the radius + margin. Add the positionToUse to that. The extreme point method won't be used for any of the collision algorithms since you will be using a special case for all of them to support concavity.
Create a collision handling delegate for the desired entity types. You can access the collision pair's Contacts list to see what's already in it. Do not add/remove contacts directly from the Contacts list; use the AddContact and RemoveContact overloads instead.
You will need to develop the algorithms to handle the pairs yourself unfortunately; I don't have time to write them up at the moment. Your hollow sphere will have an inner and outer radius. Testing other normal spheres against it will be pretty simple since it comes down to radius comparisons. You can assume that the hollow sphere and a normal sphere would only have 1 contact. Boxes will be trickier.