/// calculated new worldspace coordinates and depth, and reject points that exceed the collision margin public void RefreshContactPoints(ref IndexedMatrix trA, ref IndexedMatrix trB) { if (BulletGlobals.g_streamWriter != null && BulletGlobals.debugPersistentManifold) { MathUtil.PrintVector3(BulletGlobals.g_streamWriter, "refreshContactPoints trA", trA._origin); MathUtil.PrintVector3(BulletGlobals.g_streamWriter, "refreshContactPoints trB", trB._origin); } /// first refresh worldspace positions and distance int numContacts = GetNumContacts() - 1; for (int i = numContacts; i >= 0; i--) { ManifoldPoint manifoldPoint = m_pointCache[i]; IndexedVector3 pointA = trA * manifoldPoint.GetLocalPointA(); IndexedVector3 pointB = trB * manifoldPoint.GetLocalPointB(); manifoldPoint.SetPositionWorldOnA(ref pointA); manifoldPoint.SetPositionWorldOnB(ref pointB); manifoldPoint.SetDistance(IndexedVector3.Dot((manifoldPoint.GetPositionWorldOnA() - manifoldPoint.GetPositionWorldOnB()), manifoldPoint.GetNormalWorldOnB())); manifoldPoint.SetLifeTime(manifoldPoint.GetLifeTime() + 1); m_pointCache[i] = manifoldPoint; } /// then float distance2d; IndexedVector3 projectedDifference, projectedPoint; for (int i = numContacts; i >= 0; i--) { ManifoldPoint manifoldPoint = m_pointCache[i]; //contact becomes invalid when signed distance exceeds margin (projected on contactnormal direction) if (!ValidContactDistance(manifoldPoint)) { RemoveContactPoint(i); } else { //contact also becomes invalid when relative movement orthogonal to normal exceeds margin projectedPoint = manifoldPoint.GetPositionWorldOnA() - manifoldPoint.GetNormalWorldOnB() * manifoldPoint.GetDistance(); projectedDifference = manifoldPoint.GetPositionWorldOnB() - projectedPoint; distance2d = IndexedVector3.Dot(projectedDifference, projectedDifference); if (distance2d > GetContactBreakingThreshold() * GetContactBreakingThreshold()) { RemoveContactPoint(i); } else { //contact point processed callback if (gContactProcessedCallback != null) { gContactProcessedCallback.Callback(manifoldPoint, m_body0, m_body1); } } } } DebugPersistency(); }
public virtual void AddContactPoint(ref IndexedVector3 normalOnBInWorld, ref IndexedVector3 pointInWorld, float depth) { Debug.Assert(m_manifoldPtr != null); //order in manifold needs to match #if DEBUG if (BulletGlobals.g_streamWriter != null && BulletGlobals.debugManifoldResult) { BulletGlobals.g_streamWriter.WriteLine("AddContactPoint depth[{0}]", depth); MathUtil.PrintVector3(BulletGlobals.g_streamWriter, "normalOnBInWorld", normalOnBInWorld); MathUtil.PrintVector3(BulletGlobals.g_streamWriter, "pointInWorld", pointInWorld); } #endif //if (depth > m_manifoldPtr.GetContactProcessingThreshold()) if (depth > m_manifoldPtr.GetContactBreakingThreshold()) { return; } bool isSwapped = m_manifoldPtr.GetBody0() != m_body0; IndexedVector3 pointA = pointInWorld + normalOnBInWorld * depth; IndexedVector3 localA; IndexedVector3 localB; if (isSwapped) { MathUtil.InverseTransform(ref m_rootTransB, ref pointA, out localA); MathUtil.InverseTransform(ref m_rootTransA, ref pointInWorld, out localB); } else { MathUtil.InverseTransform(ref m_rootTransA, ref pointA, out localA); MathUtil.InverseTransform(ref m_rootTransB, ref pointInWorld, out localB); } ManifoldPoint newPt = BulletGlobals.ManifoldPointPool.Get(); newPt.Initialise(ref localA, ref localB, ref normalOnBInWorld, depth); newPt.SetPositionWorldOnA(ref pointA); newPt.SetPositionWorldOnB(ref pointInWorld); int insertIndex = m_manifoldPtr.GetCacheEntry(newPt); newPt.SetCombinedFriction(CalculateCombinedFriction(m_body0, m_body1)); newPt.SetCombinedRestitution(CalculateCombinedRestitution(m_body0, m_body1)); //BP mod, store contact triangles. if (isSwapped) { newPt.m_partId0 = m_partId1; newPt.m_partId1 = m_partId0; newPt.m_index0 = m_index1; newPt.m_index1 = m_index0; } else { newPt.m_partId0 = m_partId0; newPt.m_partId1 = m_partId1; newPt.m_index0 = m_index0; newPt.m_index1 = m_index1; } #if DEBUG if (BulletGlobals.g_streamWriter != null && BulletGlobals.debugManifoldResult) { MathUtil.PrintContactPoint(BulletGlobals.g_streamWriter, newPt); } #endif //printf("depth=%f\n",depth); ///@todo, check this for any side effects if (insertIndex >= 0) { //const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex); m_manifoldPtr.ReplaceContactPoint(newPt, insertIndex); } else { insertIndex = m_manifoldPtr.AddManifoldPoint(newPt); } //User can override friction and/or restitution if (BulletGlobals.gContactAddedCallback != null && //and if either of the two bodies requires custom material ((m_body0.GetCollisionFlags() & CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK) != 0 || (m_body1.GetCollisionFlags() & CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK) != 0)) { //experimental feature info, for per-triangle material etc. CollisionObject obj0 = isSwapped ? m_body1 : m_body0; CollisionObject obj1 = isSwapped ? m_body0 : m_body1; //gContactAddedCallback.callback(m_manifoldPtr.getContactPoint(insertIndex),obj0,m_partId0,m_index0,obj1,m_partId1,m_index1); ManifoldPoint point = m_manifoldPtr.GetContactPoint(insertIndex); BulletGlobals.gContactAddedCallback.Callback(ref point, obj0, newPt.m_partId0, newPt.m_index0, obj1, newPt.m_partId1, newPt.m_index1); } }