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; } }
public override float CalculateTimeOfImpact(CollisionObject bodyA, CollisionObject bodyB, DispatcherInfo dispatchInfo, ManifoldResult resultOut) { CollisionObject collisionObject = _isSwapped ? bodyB : bodyA; CollisionObject otherObject = _isSwapped ? bodyA : bodyB; BulletDebug.Assert(collisionObject.CollisionShape.IsCompound); CompoundShape compoundShape = (CompoundShape)collisionObject.CollisionShape; float hitFraction = 1.0f; for (int i = 0; i < _childCollisionAlgorithms.Count; i++) { CollisionShape childShape = compoundShape.GetChildShape(i); Matrix orgTransform = collisionObject.WorldTransform; CollisionShape orgShape = collisionObject.CollisionShape; Matrix childTransform = compoundShape.GetChildTransform(i); Matrix newChildWorld = orgTransform * childTransform; collisionObject.WorldTransform = newChildWorld; collisionObject.CollisionShape = childShape; float frac = _childCollisionAlgorithms[i].CalculateTimeOfImpact( collisionObject, otherObject, dispatchInfo, resultOut ); if (frac < hitFraction) { hitFraction = frac; } collisionObject.CollisionShape = orgShape; collisionObject.WorldTransform = orgTransform; } return(hitFraction); }
// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest. // In a future implementation, we consider moving the ray test as a virtual method in CollisionShape. // This allows more customization. public static void RayTestSingle(Matrix rayFromTrans, Matrix rayToTrans, CollisionObject collisionObject, CollisionShape collisionShape, Matrix colObjWorldTransform, RayResultCallback resultCallback) { SphereShape pointShape = new SphereShape(0.0f); if (collisionShape.IsConvex) { CastResult castResult = new CastResult(); castResult.Fraction = 1f; //?? ConvexShape convexShape = collisionShape as ConvexShape; VoronoiSimplexSolver simplexSolver = new VoronoiSimplexSolver(); SubsimplexConvexCast convexCaster = new SubsimplexConvexCast(pointShape, convexShape, simplexSolver); //GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver); //ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0); if (convexCaster.CalcTimeOfImpact(rayFromTrans, rayToTrans, colObjWorldTransform, colObjWorldTransform, castResult)) { //add hit if (castResult.Normal.LengthSquared() > 0.0001f) { castResult.Normal.Normalize(); if (castResult.Fraction < resultCallback.ClosestHitFraction) { CollisionWorld.LocalRayResult localRayResult = new LocalRayResult ( collisionObject, new LocalShapeInfo(), castResult.Normal, castResult.Fraction ); resultCallback.AddSingleResult(localRayResult); } } } else { if (collisionShape.IsConcave) { TriangleMeshShape triangleMesh = collisionShape as TriangleMeshShape; Matrix worldTocollisionObject = MathHelper.InvertMatrix(colObjWorldTransform); Vector3 rayFromLocal = Vector3.TransformNormal(rayFromTrans.Translation, worldTocollisionObject); Vector3 rayToLocal = Vector3.TransformNormal(rayToTrans.Translation, worldTocollisionObject); BridgeTriangleRaycastCallback rcb = new BridgeTriangleRaycastCallback(rayFromLocal, rayToLocal, resultCallback, collisionObject, triangleMesh); rcb.HitFraction = resultCallback.ClosestHitFraction; Vector3 rayAabbMinLocal = rayFromLocal; MathHelper.SetMin(ref rayAabbMinLocal, rayToLocal); Vector3 rayAabbMaxLocal = rayFromLocal; MathHelper.SetMax(ref rayAabbMaxLocal, rayToLocal); triangleMesh.ProcessAllTriangles(rcb, rayAabbMinLocal, rayAabbMaxLocal); } else { //todo: use AABB tree or other BVH acceleration structure! if (collisionShape.IsCompound) { CompoundShape compoundShape = collisionShape as CompoundShape; for (int i = 0; i < compoundShape.ChildShapeCount; i++) { Matrix childTrans = compoundShape.GetChildTransform(i); CollisionShape childCollisionShape = compoundShape.GetChildShape(i); Matrix childWorldTrans = colObjWorldTransform * childTrans; RayTestSingle(rayFromTrans, rayToTrans, collisionObject, childCollisionShape, childWorldTrans, resultCallback); } } } } } }