I'm using bulletsharp (C# wrapper of bullet physics) to do some collision detection. Everything went fine until i tried to change the collision shape of an existing rigid body from box to compound at runtime. I'm doing this to simulate the collision again with a higher accuracy. The problem is: collision of compound shapes is not detected.
Scenario:
DicreteDynamicsWorld
containing some RigidBody
with BoxShape
RigidBody
with BoxShape
happens (and is detected)RigidBody
to CompoundShape
using the HACD algorithm for convex decompositionRigidBody
from DicreteDynamicsWorld
RigidBody.CollisionShape
= CompoundShape
RigidBody.MotionState.WorldTransform
RigidBody
to DicreteDynamicsWorld
Remarks:
CollisionShape
from BoxShape
to CompoundShape
was successful (correct CollisionShape
and correct position)DicreteDynamicsWorld.Dispatcher.NumManifolds > 0
after a DicreteDynamicsWorld.StepSimulation(...)
Some code snippets as requested:
If you need something particular, please tell me. My solution is too big and too complexe to post the complete code...
RigidBody creation:
// Create rigid body
MotionState motionState = new DefaultMotionState(startTransform);
RigidBodyConstructionInfo rbInfo = new RigidBodyConstructionInfo(0.0f, motionState, collisionShape);
RigidBody rigidBody = new RigidBody(rbInfo);
rbInfo.Dispose();
// Kinematic body: mass=0 -> static/kinematic -> use flag
bool isKinematicBody = (compModel.Children[i].Type ==...) || ... ;
rigidBody.CollisionFlags = isKinematicBody ? CollisionFlags.KinematicObject : CollisionFlags.StaticObject;
rigidBody.ActivationState = ActivationState.DisableDeactivation;
Basic steps:
// Get old collision data
if (compModel.Children[i].Container.TryGetValue(ContainerType.Collision, out container))
collisionData = ((ContainerCollision) container).CollisionData;
// Get geometry
if (compModel.Children[i].Container.TryGetValue(ContainerType.Geometry, out container))
{
verticesGeo = ((ContainerGeometry) container).GeometryData.Vertices;
trianglesGeo = ((ContainerGeometry) container).GeometryData.Triangles;
}
// Remove rigid body from world
_world.RemoveRigidBody(collisionData.RigidBody);
// Create new shape
List<Vector3> vertices = Utility.ToBulletVector3List(verticesGeo);
List<int> indices = Utility.ListIntArrayToListInt(trianglesGeo);
CompoundShape collisionShape = ConvexDecomposition(compModel.Children[i].Id, vertices, indices);
// Set collision shape
collisionData.RigidBody.CollisionShape = collisionShape;
// Set position
collisionData.RigidBody.MotionState.WorldTransform *= collisionData.PositionDifference;
// Add rigid body to world
_world.AddRigidBody(collisionData.RigidBody, collisionData.CollisionGroup, collisionData.CollisionMask);
CollisionContainer:
public interface IContainer
{
ContainerType Type { get; }
}
public struct ContainerCollision : IContainer
{
public ContainerType Type
{
get { return ContainerType.Collision; }
}
public CollisionData CollisionData;
}
Structure CollisionData:
public struct CollisionData
{
public BulletSharp.RigidBody RigidBody;
public BulletSharp.Matrix PositionDifference;
public BulletSharp.Vector3 ZeroPosition;
public short CollisionGroup;
public short CollisionMask;
}
Any ideas, what i'm doing wrong?
Thanks.
Assuming that all your change in shape is happening here
CompoundShape collisionShape = ConvexDecomposition(compModel.Children[i].Id, vertices, indices);
// Set collision shape
collisionData.RigidBody.CollisionShape = collisionShape;
// Set position
collisionData.RigidBody.MotionState.WorldTransform *= collisionData.PositionDifference;
// Add rigid body to world
_world.AddRigidBody(collisionData.RigidBody, collisionData.CollisionGroup, collisionData.CollisionMask);
Probably you will have to recalculate the entire RigidBody from start, I have no clue how you do that in the first place so I will show you an example how I do it.
public virtual RigidBody LocalCreateRigidBody(float mass, Matrix startTransform, CollisionShape shape)
{
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.0f);
Vector3 localInertia = Vector3.Zero;
if (isDynamic)
shape.CalculateLocalInertia(mass, out localInertia);
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
DefaultMotionState myMotionState = new DefaultMotionState(startTransform);
RigidBodyConstructionInfo rbInfo = new RigidBodyConstructionInfo(mass, myMotionState, shape, localInertia);
RigidBody body = new RigidBody(rbInfo);
rbInfo.Dispose();
return body;
}
With that being said, take a note at your "collisionData" (Which I guess its a class?) and the naming of RigidBody (it might have a conflict with the BulletSharp class?)
Best reguards with your progress and feel free to contact me if you have any questions!