public virtual void ProcessTriangle(IndexedVector3[] triangle, int partId, int triangleIndex) { TriangleShape triangleShape = new TriangleShape(ref triangle[0], ref triangle[1], ref triangle[2]); triangleShape.SetMargin(m_triangleCollisionMargin); VoronoiSimplexSolver simplexSolver = BulletGlobals.VoronoiSimplexSolverPool.Get(); GjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver = new GjkEpaPenetrationDepthSolver(); //#define USE_SUBSIMPLEX_CONVEX_CAST 1 //if you reenable USE_SUBSIMPLEX_CONVEX_CAST see commented ref code below #if USE_SUBSIMPLEX_CONVEX_CAST SubsimplexConvexCast convexCaster = new SubsimplexConvexCast(m_convexShape, triangleShape, simplexSolver); #else //btGjkConvexCast convexCaster(m_convexShape,&triangleShape,&simplexSolver); ContinuousConvexCollision convexCaster = BulletGlobals.ContinuousConvexCollisionPool.Get(); convexCaster.Initialize(m_convexShape, triangleShape, simplexSolver, gjkEpaPenetrationSolver); #endif //#USE_SUBSIMPLEX_CONVEX_CAST CastResult castResult = BulletGlobals.CastResultPool.Get(); castResult.m_fraction = 1f; if (convexCaster.CalcTimeOfImpact(ref m_convexShapeFrom, ref m_convexShapeTo, ref m_triangleToWorld, ref m_triangleToWorld, castResult)) { //add hit if (castResult.m_normal.LengthSquared() > 0.0001f) { if (castResult.m_fraction < m_hitFraction) { /* btContinuousConvexCast's normal is already in world space */ /* #ifdef USE_SUBSIMPLEX_CONVEX_CAST * //rotate normal into worldspace * castResult.m_normal = m_convexShapeFrom.getBasis() * castResult.m_normal; #endif //USE_SUBSIMPLEX_CONVEX_CAST */ castResult.m_normal.Normalize(); ReportHit(ref castResult.m_normal, ref castResult.m_hitPoint, castResult.m_fraction, partId, triangleIndex); } } } BulletGlobals.ContinuousConvexCollisionPool.Free(convexCaster); BulletGlobals.VoronoiSimplexSolverPool.Free(simplexSolver); castResult.Cleanup(); }
/// objectQuerySingle performs a collision detection query and calls the resultCallback. It is used internally by rayTest. public static void ObjectQuerySingle(ConvexShape castShape, ref IndexedMatrix convexFromTrans, ref IndexedMatrix convexToTrans, CollisionObject collisionObject, CollisionShape collisionShape, ref IndexedMatrix colObjWorldTransform, ConvexResultCallback resultCallback, float allowedPenetration) { if (collisionShape.IsConvex()) { BulletGlobals.StartProfile("convexSweepConvex"); CastResult castResult = BulletGlobals.CastResultPool.Get(); castResult.m_allowedPenetration = allowedPenetration; castResult.m_fraction = resultCallback.m_closestHitFraction;//float(1.);//?? ConvexShape convexShape = collisionShape as ConvexShape; VoronoiSimplexSolver simplexSolver = BulletGlobals.VoronoiSimplexSolverPool.Get(); GjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver = BulletGlobals.GjkEpaPenetrationDepthSolverPool.Get(); ContinuousConvexCollision convexCaster1 = BulletGlobals.ContinuousConvexCollisionPool.Get(); convexCaster1.Initialize(castShape, convexShape, simplexSolver, gjkEpaPenetrationSolver); //btGjkConvexCast convexCaster2(castShape,convexShape,&simplexSolver); //btSubsimplexConvexCast convexCaster3(castShape,convexShape,&simplexSolver); IConvexCast castPtr = convexCaster1; if (castPtr.CalcTimeOfImpact(ref convexFromTrans, ref convexToTrans, ref colObjWorldTransform, ref colObjWorldTransform, castResult)) { //add hit if (castResult.m_normal.LengthSquared() > 0.0001f) { if (castResult.m_fraction < resultCallback.m_closestHitFraction) { castResult.m_normal.Normalize(); LocalConvexResult localConvexResult = new LocalConvexResult ( collisionObject, //null, // updated to allow different ctor on struct ref castResult.m_normal, ref castResult.m_hitPoint, castResult.m_fraction ); bool normalInWorldSpace = true; resultCallback.AddSingleResult(ref localConvexResult, normalInWorldSpace); } } } BulletGlobals.ContinuousConvexCollisionPool.Free(convexCaster1); BulletGlobals.GjkEpaPenetrationDepthSolverPool.Free(gjkEpaPenetrationSolver); BulletGlobals.VoronoiSimplexSolverPool.Free(simplexSolver); castResult.Cleanup(); BulletGlobals.StopProfile(); } else { if (collisionShape.IsConcave()) { if (collisionShape.GetShapeType() == BroadphaseNativeTypes.TRIANGLE_MESH_SHAPE_PROXYTYPE) { BulletGlobals.StartProfile("convexSweepbtBvhTriangleMesh"); BvhTriangleMeshShape triangleMesh = (BvhTriangleMeshShape)collisionShape; IndexedMatrix worldTocollisionObject = colObjWorldTransform.Inverse(); IndexedVector3 convexFromLocal = worldTocollisionObject * convexFromTrans._origin; IndexedVector3 convexToLocal = worldTocollisionObject * convexToTrans._origin; // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation IndexedMatrix rotationXform = new IndexedMatrix(worldTocollisionObject._basis * convexToTrans._basis,new IndexedVector3(0)); using (BridgeTriangleConvexcastCallback tccb = BulletGlobals.BridgeTriangleConvexcastCallbackPool.Get()) { tccb.Initialize(castShape, ref convexFromTrans, ref convexToTrans, resultCallback, collisionObject, triangleMesh, ref colObjWorldTransform); tccb.m_hitFraction = resultCallback.m_closestHitFraction; tccb.m_allowedPenetration = allowedPenetration; IndexedVector3 boxMinLocal; IndexedVector3 boxMaxLocal; castShape.GetAabb(ref rotationXform, out boxMinLocal, out boxMaxLocal); triangleMesh.PerformConvexCast(tccb, ref convexFromLocal, ref convexToLocal, ref boxMinLocal, ref boxMaxLocal); } BulletGlobals.StopProfile(); } else { if (collisionShape.GetShapeType() == BroadphaseNativeTypes.STATIC_PLANE_PROXYTYPE) { CastResult castResult = BulletGlobals.CastResultPool.Get(); castResult.m_allowedPenetration = allowedPenetration; castResult.m_fraction = resultCallback.m_closestHitFraction; StaticPlaneShape planeShape = collisionShape as StaticPlaneShape; ContinuousConvexCollision convexCaster1 = new ContinuousConvexCollision(castShape, planeShape); if (convexCaster1.CalcTimeOfImpact(ref convexFromTrans, ref convexToTrans, ref colObjWorldTransform, ref colObjWorldTransform, castResult)) { //add hit if (castResult.m_normal.LengthSquared() > 0.0001f) { if (castResult.m_fraction < resultCallback.m_closestHitFraction) { castResult.m_normal.Normalize(); LocalConvexResult localConvexResult = new LocalConvexResult ( collisionObject, //null, // updated to allow different ctor on struct ref castResult.m_normal, ref castResult.m_hitPoint, castResult.m_fraction ); bool normalInWorldSpace = true; resultCallback.AddSingleResult(ref localConvexResult, normalInWorldSpace); } } } castResult.Cleanup(); } else { BulletGlobals.StartProfile("convexSweepConcave"); ConcaveShape concaveShape = (ConcaveShape)collisionShape; IndexedMatrix worldTocollisionObject = colObjWorldTransform.Inverse(); IndexedVector3 convexFromLocal = worldTocollisionObject * convexFromTrans._origin; IndexedVector3 convexToLocal = worldTocollisionObject * convexToTrans._origin; // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation IndexedMatrix rotationXform = new IndexedMatrix(worldTocollisionObject._basis * convexToTrans._basis, new IndexedVector3(0)); using (BridgeTriangleConvexcastCallback tccb = BulletGlobals.BridgeTriangleConvexcastCallbackPool.Get()) { tccb.Initialize(castShape, ref convexFromTrans, ref convexToTrans, resultCallback, collisionObject, concaveShape, ref colObjWorldTransform); tccb.m_hitFraction = resultCallback.m_closestHitFraction; tccb.m_allowedPenetration = allowedPenetration; IndexedVector3 boxMinLocal; IndexedVector3 boxMaxLocal; castShape.GetAabb(ref rotationXform, out boxMinLocal, out boxMaxLocal); IndexedVector3 rayAabbMinLocal = convexFromLocal; MathUtil.VectorMin(ref convexToLocal, ref rayAabbMinLocal); //rayAabbMinLocal.setMin(convexToLocal); IndexedVector3 rayAabbMaxLocal = convexFromLocal; //rayAabbMaxLocal.setMax(convexToLocal); MathUtil.VectorMax(ref convexToLocal, ref rayAabbMaxLocal); rayAabbMinLocal += boxMinLocal; rayAabbMaxLocal += boxMaxLocal; concaveShape.ProcessAllTriangles(tccb, ref rayAabbMinLocal, ref rayAabbMaxLocal); BulletGlobals.StopProfile(); } } } } else { ///@todo : use AABB tree or other BVH acceleration structure! if (collisionShape.IsCompound()) { BulletGlobals.StartProfile("convexSweepCompound"); CompoundShape compoundShape = (CompoundShape)collisionShape; for (int i = 0; i < compoundShape.GetNumChildShapes(); i++) { IndexedMatrix childTrans = compoundShape.GetChildTransform(i); CollisionShape childCollisionShape = compoundShape.GetChildShape(i); IndexedMatrix childWorldTrans = colObjWorldTransform * childTrans; // replace collision shape so that callback can determine the triangle CollisionShape saveCollisionShape = collisionObject.GetCollisionShape(); collisionObject.InternalSetTemporaryCollisionShape(childCollisionShape); LocalInfoAdder my_cb = new LocalInfoAdder(i, resultCallback); my_cb.m_closestHitFraction = resultCallback.m_closestHitFraction; ObjectQuerySingle(castShape, ref convexFromTrans, ref convexToTrans, collisionObject, childCollisionShape, ref childWorldTrans, my_cb, allowedPenetration); // restore collisionObject.InternalSetTemporaryCollisionShape(saveCollisionShape); } BulletGlobals.StopProfile(); } } } }