protected bool RecoverFromPenetration(CollisionWorld collisionWorld) { // Here we must refresh the overlapping paircache as the penetrating movement itself or the // previous recovery iteration might have used setWorldTransform and pushed us into an object // that is not in the previous cache contents from the last timestep, as will happen if we // are pushed into a new AABB overlap. Unhandled this means the next convex sweep gets stuck. // // Do this by calling the broadphase's setAabb with the moved AABB, this will update the broadphase // paircache and the ghostobject's internal paircache at the same time. /BW Vector3 minAabb, maxAabb; m_convexShape.GetAabb(m_ghostObject.WorldTransform, out minAabb, out maxAabb); collisionWorld.Broadphase.SetAabbRef(m_ghostObject.BroadphaseHandle, ref minAabb, ref maxAabb, collisionWorld.Dispatcher); bool penetration = false; collisionWorld.Dispatcher.DispatchAllCollisionPairs(m_ghostObject.OverlappingPairCache, collisionWorld.DispatchInfo, collisionWorld.Dispatcher); m_currentPosition = m_ghostObject.WorldTransform.Origin; // btScalar maxPen = btScalar(0.0); for (int i = 0; i < m_ghostObject.OverlappingPairCache.NumOverlappingPairs; i++) { m_manifoldArray.Clear(); BroadphasePair collisionPair = m_ghostObject.OverlappingPairCache.OverlappingPairArray[i]; CollisionObject obj0 = collisionPair.Proxy0.ClientObject as CollisionObject; CollisionObject obj1 = collisionPair.Proxy1.ClientObject as CollisionObject; if ((obj0 != null && !obj0.HasContactResponse) || (obj1 != null && !obj1.HasContactResponse)) { continue; } if (!NeedsCollision(obj0, obj1)) { continue; } if (collisionPair.Algorithm != null) { collisionPair.Algorithm.GetAllContactManifolds(m_manifoldArray); } for (int j = 0; j < m_manifoldArray.Count; j++) { PersistentManifold manifold = m_manifoldArray[j]; float directionSign = manifold.Body0 == m_ghostObject ? -1.0f : 1.0f; for (int p = 0; p < manifold.NumContacts; p++) { ManifoldPoint pt = manifold.GetContactPoint(p); float dist = pt.Distance; if (dist < -m_maxPenetrationDepth) { // to do: cause problems on slopes, not sure if it is needed //if (dist < maxPen) //{ // maxPen = dist; // m_touchingNormal = pt.m_normalWorldOnB * directionSign;//?? //} m_currentPosition += pt.NormalWorldOnB * directionSign * dist * 0.2f; penetration = true; } else { //System.Console.WriteLine("touching " + dist); } } //manifold.ClearManifold(); } } Matrix newTrans = m_ghostObject.WorldTransform; newTrans.Origin = m_currentPosition; m_ghostObject.WorldTransform = newTrans; //System.Console.WriteLine("m_touchingNormal = " + m_touchingNormal); return(penetration); }
protected bool RecoverFromPenetration(CollisionWorld collisionWorld) { Vector3 minAabb, maxAabb; m_convexShape.GetAabb(m_ghostObject.WorldTransform, out minAabb, out maxAabb); collisionWorld.Broadphase.SetAabbRef(m_ghostObject.BroadphaseHandle, ref minAabb, ref maxAabb, collisionWorld.Dispatcher); bool penetration = false; collisionWorld.Dispatcher.DispatchAllCollisionPairs(m_ghostObject.OverlappingPairCache, collisionWorld.DispatchInfo, collisionWorld.Dispatcher); m_currentPosition = m_ghostObject.WorldTransform.Origin; float maxPen = 0f; for (int i = 0; i < m_ghostObject.OverlappingPairCache.NumOverlappingPairs; i++) { m_manifoldArray.Clear(); BroadphasePair collisionPair = m_ghostObject.OverlappingPairCache.OverlappingPairArray[i]; CollisionObject obj0 = collisionPair.Proxy0.ClientObject as CollisionObject; CollisionObject obj1 = collisionPair.Proxy1.ClientObject as CollisionObject; if ((obj0 != null && !obj0.HasContactResponse) || (obj1 != null && !obj1.HasContactResponse)) { continue; } if (collisionPair.Algorithm != null) { collisionPair.Algorithm.GetAllContactManifolds(m_manifoldArray); } for (int j = 0; j < m_manifoldArray.Count; j++) { PersistentManifold manifold = m_manifoldArray[j]; float directionSign = manifold.Body0 == m_ghostObject ? -1f : 1f; for (int p = 0; p < manifold.NumContacts; p++) { ManifoldPoint pt = manifold.GetContactPoint(p); float dist = pt.Distance; if (dist < 0.0f) { if (dist < maxPen) { maxPen = dist; m_touchingNormal = pt.NormalWorldOnB * directionSign;//?? } m_currentPosition += pt.NormalWorldOnB * directionSign * dist * 0.2f; penetration = true; } else { //printf("touching %f\n", dist); } } //manifold.ClearManifold(); } } Matrix newTrans = m_ghostObject.WorldTransform; newTrans.Origin = m_currentPosition; m_ghostObject.WorldTransform = newTrans; // printf("m_touchingNormal = %f,%f,%f\n",m_touchingNormal[0],m_touchingNormal[1],m_touchingNormal[2]); return(penetration); }