public virtual void ProcessTriangle(ObjectArray<Vector3> triangle, int partId, int triangleIndex) { TriangleShape triangleShape = new TriangleShape(triangle[0], triangle[1], triangle[2]); triangleShape.Margin = m_triangleCollisionMargin; VoronoiSimplexSolver simplexSolver = new VoronoiSimplexSolver(); 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 = new ContinuousConvexCollision(m_convexShape,triangleShape,simplexSolver,gjkEpaPenetrationSolver); #endif //#USE_SUBSIMPLEX_CONVEX_CAST CastResult castResult = new CastResult(); 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); } } } }
/// objectQuerySingle performs a collision detection query and calls the resultCallback. It is used internally by rayTest. public static void ObjectQuerySingle(ConvexShape castShape,ref Matrix convexFromTrans,ref Matrix convexToTrans, CollisionObject collisionObject,CollisionShape collisionShape, ref Matrix colObjWorldTransform, ConvexResultCallback resultCallback, float allowedPenetration) { if (collisionShape.IsConvex()) { //BT_PROFILE("convexSweepConvex"); CastResult castResult = new CastResult(); castResult.m_allowedPenetration = allowedPenetration; castResult.m_fraction = resultCallback.m_closestHitFraction;//float(1.);//?? ConvexShape convexShape = (ConvexShape) collisionShape; VoronoiSimplexSolver simplexSolver = new VoronoiSimplexSolver(); GjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver = new GjkEpaPenetrationDepthSolver(); ContinuousConvexCollision convexCaster1 = new ContinuousConvexCollision(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, ref castResult.m_normal, ref castResult.m_hitPoint, castResult.m_fraction ); bool normalInWorldSpace = true; resultCallback.AddSingleResult(localConvexResult, normalInWorldSpace); } } } } else { if (collisionShape.IsConcave()) { if (collisionShape.ShapeType==BroadphaseNativeTypes.TRIANGLE_MESH_SHAPE_PROXYTYPE) { //BT_PROFILE("convexSweepbtBvhTriangleMesh"); BvhTriangleMeshShape triangleMesh = (BvhTriangleMeshShape)collisionShape; Matrix worldTocollisionObject = Matrix.Invert(colObjWorldTransform); Vector3 convexFromLocal = Vector3.Transform(convexFromTrans.Translation,worldTocollisionObject); Vector3 convexToLocal = Vector3.Transform(convexToTrans.Translation,worldTocollisionObject); // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation Matrix rotationXform = MathUtil.BasisMatrix(ref worldTocollisionObject) * MathUtil.BasisMatrix(ref convexToTrans); BridgeTriangleConvexcastCallback tccb = new BridgeTriangleConvexcastCallback(castShape, ref convexFromTrans,ref convexToTrans,resultCallback,collisionObject,triangleMesh, ref colObjWorldTransform); tccb.m_hitFraction = resultCallback.m_closestHitFraction; Vector3 boxMinLocal = new Vector3(); Vector3 boxMaxLocal = new Vector3(); castShape.GetAabb(ref rotationXform, ref boxMinLocal, ref boxMaxLocal); triangleMesh.PerformConvexCast(tccb,ref convexFromLocal,ref convexToLocal,ref boxMinLocal, ref boxMaxLocal); } else { //BT_PROFILE("convexSweepConcave"); ConcaveShape concaveShape = (ConcaveShape)collisionShape; Matrix worldTocollisionObject = Matrix.Invert(colObjWorldTransform); Vector3 convexFromLocal = Vector3.Transform(convexFromTrans.Translation,worldTocollisionObject); Vector3 convexToLocal = Vector3.Transform(convexToTrans.Translation,worldTocollisionObject); // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation Matrix rotationXform = MathUtil.BasisMatrix(ref worldTocollisionObject) * MathUtil.BasisMatrix(ref convexToTrans); BridgeTriangleConvexcastCallback2 tccb = new BridgeTriangleConvexcastCallback2(castShape, ref convexFromTrans, ref convexToTrans, resultCallback, collisionObject, concaveShape, ref colObjWorldTransform); tccb.m_hitFraction = resultCallback.m_closestHitFraction; Vector3 boxMinLocal = new Vector3(); Vector3 boxMaxLocal = new Vector3(); castShape.GetAabb(ref rotationXform, ref boxMinLocal, ref boxMaxLocal); Vector3 rayAabbMinLocal = convexFromLocal; MathUtil.VectorMin(ref convexToLocal,ref rayAabbMinLocal); //rayAabbMinLocal.setMin(convexToLocal); Vector3 rayAabbMaxLocal = convexFromLocal; //rayAabbMaxLocal.setMax(convexToLocal); MathUtil.VectorMax(ref convexToLocal,ref rayAabbMaxLocal); rayAabbMinLocal += boxMinLocal; rayAabbMaxLocal += boxMaxLocal; concaveShape.ProcessAllTriangles(tccb,ref rayAabbMinLocal,ref rayAabbMaxLocal); } } else { ///@todo : use AABB tree or other BVH acceleration structure! if (collisionShape.IsCompound()) { //BT_PROFILE("convexSweepCompound"); CompoundShape compoundShape = (CompoundShape)collisionShape; for (int i=0;i<compoundShape.GetNumChildShapes();i++) { Matrix childTrans = compoundShape.GetChildTransform(i); CollisionShape childCollisionShape = compoundShape.GetChildShape(i); Matrix childWorldTrans = MathUtil.BulletMatrixMultiply(colObjWorldTransform,childTrans); // replace collision shape so that callback can determine the triangle CollisionShape saveCollisionShape = collisionObject.GetCollisionShape(); collisionObject.InternalSetTemporaryCollisionShape((CollisionShape)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); } } } } }