I'm not exactly sure where to post fixes to or issues with XNA Bullet so I'll put it here.
My name is Bob Schade and I've been working with Mike Skolones on an XNA game that uses the XNA Bullet SDK. We noticed that compounds were broken in the currently build and figured out what the fix is.
First of all, you can reproduce the problem by having the demo games shoot a compound rather than a box, so in DemoGame.cs, change these lines of code:
Code:
private void shootBox(Vector3 destination)
{
...
CollisionShape boxShape = new BoxShape(Vector3.One);
RigidBody body = CreateRigidBody(mass, startTransform, boxShape);
...
}
to this:
Code:
private void shootBox(Vector3 destination)
{
...
CollisionShape sphereShape = new SphereShape(1);
Vector3 halfExtents = new Vector3(1, 1, 2);
CollisionShape leftBoxShape = new BoxShape(halfExtents);
CompoundShape compoundShape = new CompoundShape();
compoundShape.AddChildShape(Matrix.Identity, sphereShape);
compoundShape.AddChildShape(Matrix.Identity, leftBoxShape);
RigidBody body = CreateRigidBody(mass, startTransform, compoundShape);
...
}
...so the user fires a compound object rather than a simple box. If you run the Constraint Demo and fire the compound object at one of the jointed boxes, you will get an "index out-of-range" in the CompoundCollisionAlgorithm() function in CompoundCollisionAlgorithm.cs.
Code:
public CompoundCollisionAlgorithm(CollisionAlgorithmConstructionInfo collisionAlgorithmConstructionInfo, CollisionObject bodyA,CollisionObject bodyB, bool isSwapped) : base(collisionAlgorithmConstructionInfo)
{
//Begin
_isSwapped = isSwapped;
CollisionObject collisionObject = isSwapped ? bodyB : bodyA;
CollisionObject otherObject = isSwapped ? bodyA : bodyB;
_childCollisionAlgorithms = new List<CollisionAlgorithm>(childrenNumber);
for (index = 0; index < childrenNumber; index++)
{
CollisionShape childShape = compoundShape.GetChildShape(index);
CollisionShape orgShape = collisionObject.CollisionShape;
collisionObject.CollisionShape = childShape;
_childCollisionAlgorithms[index] = collisionAlgorithmConstructionInfo.Dispatcher.FindAlgorithm(collisionObject, otherObject);
collisionObject.CollisionShape = orgShape;
}
}
The index out of range error occurs at this line:
Code:
_childCollisionAlgorithms[index] = collisionAlgorithmConstructionInfo.Dispatcher.FindAlgorithm(collisionObject, otherObject);
You can't add to the List object with an assignment operator, you need to use the List's Add() function, so this line needs to be changed to this:
Code:
_childCollisionAlgorithms.Add(collisionAlgorithmConstructionInfo.Dispatcher.FindAlgorithm(collisionObject, otherObject));
After you make this change, there are other errors in the ProcessCollision() function in CompoundCollisionAlgorithm.cs.
Code:
public override void ProcessCollision(CollisionObject bodyA, CollisionObject bodyB, DispatcherInfo dispatchInfo, ManifoldResult resultOut)
{
//Begin
CollisionObject collisionObject = _isSwapped ? bodyB : bodyB;
CollisionObject otherObject = _isSwapped ? bodyA : bodyB;
...
//Debug.Assert(collisionObject.getCollisionShape().isCompound());
BulletDebug.Assert(collisionObject.CollisionShape.IsCompound);
CompoundShape compoundShape = (CompoundShape)collisionObject.CollisionShape;
int childrenNumber = _childCollisionAlgorithms.Count;
for (int i = 0; i < childrenNumber; i++)
{
CompoundShape childShape = compoundShape.GetChildShape(i) as CompoundShape;
Matrix orgTransform = collisionObject.WorldTransform;
CollisionShape orgShape = collisionObject.CollisionShape;
Matrix childTransform = compoundShape.GetChildTransform(i);
Matrix newChildWorld = orgTransform * childTransform;
collisionObject.WorldTransform = newChildWorld;
collisionObject.CollisionShape = childShape;
_childCollisionAlgorithms[i].ProcessCollision(collisionObject, otherObject, dispatchInfo, resultOut);
collisionObject.CollisionShape = orgShape;
collisionObject.WorldTransform = orgTransform;
}
}
First "collisionObject" needs to be "bodyA" when "otherObject" is "bodyB".
Code:
CollisionObject collisionObject = _isSwapped ? bodyB : bodyA;
Next the "childShape" needs to be a "CollisionShape", rather than a "CompoundShape".
Code:
CollisionShape childShape = compoundShape.GetChildShape(i) as CollisionShape;
So the whole thing should look like this:
Code:
public override void ProcessCollision(CollisionObject bodyA, CollisionObject bodyB,DispatcherInfo dispatchInfo, ManifoldResult resultOut)
{
//Begin
CollisionObject collisionObject = _isSwapped ? bodyB : bodyA;
CollisionObject otherObject = _isSwapped ? bodyA : bodyB;
...
//Debug.Assert(collisionObject.getCollisionShape().isCompound());
BulletDebug.Assert(collisionObject.CollisionShape.IsCompound);
CompoundShape compoundShape = (CompoundShape)collisionObject.CollisionShape;
int childrenNumber = _childCollisionAlgorithms.Count;
for (int i = 0; i < childrenNumber; i++)
{
CollisionShape childShape = compoundShape.GetChildShape(i) as CollisionShape;
Matrix orgTransform = collisionObject.WorldTransform;
CollisionShape orgShape = collisionObject.CollisionShape;
Matrix childTransform = compoundShape.GetChildTransform(i);
Matrix newChildWorld = orgTransform * childTransform;
collisionObject.WorldTransform = newChildWorld;
collisionObject.CollisionShape = childShape;
_childCollisionAlgorithms[i].ProcessCollision(collisionObject, otherObject, dispatchInfo, resultOut);
collisionObject.CollisionShape = orgShape;
collisionObject.WorldTransform = orgTransform;
}
}
This gets compounds working, at least so it doesn't crash. I'll let you know what else we find out about them.
All for now,
Bob