public static bool SphereBoxCollisionOccured(PSI_Collider_Sphere sphereCol, PSI_Collider_Box boxCol, out Vector3 point) { // Get the closest point on the surface of the box to the sphere. point = boxCol.GetClosestPointOnBox(sphereCol.pPosition); // Do a distance check to see if the sphere and box are colliding. var collisionVector = point - sphereCol.pPosition; bool isColliding = collisionVector.magnitude <= Mathf.Abs(sphereCol.pRadius); if (isColliding) { // Resolve any overlap between the sphere and the box. var collisionAxis = CorrectCollisionAxisDirection(boxCol.pPosition, sphereCol.pPosition, collisionVector); float overlap = collisionVector.magnitude - sphereCol.pRadius; ResolveCollisionOverlaps(sphereCol, boxCol, collisionAxis, overlap); // Calculate and apply the collision impulse to the sphere and the box. ApplyImpulses(sphereCol, boxCol, collisionAxis, point); return(true); } return(false); }
//------------------------------------Private Functions------------------------------------- private void CheckForCollision(PSI_Collider col1, PSI_Collider col2) { bool collisionOccurred = false; PSI_Collision collision = new PSI_Collision(); collision.col1 = col1; collision.col2 = col2; // Sphere on sphere. if (col1.pType == ColliderType.Sphere && col2.pType == ColliderType.Sphere) { collisionOccurred = PSI_PhysicsUtils.SphereSphereCollisionCheck((PSI_Collider_Sphere)col1, (PSI_Collider_Sphere)col2, out collision.point); } // Sphere on plane. if ((col1.pType == ColliderType.Sphere && col2.pType == ColliderType.Plane) || (col1.pType == ColliderType.Plane && col2.pType == ColliderType.Sphere)) { PSI_Collider_Sphere sphere = (PSI_Collider_Sphere)((col1.pType == ColliderType.Sphere) ? col1 : col2); PSI_Collider_Plane plane = (PSI_Collider_Plane)((col1.pType == ColliderType.Sphere) ? col2 : col1); if (PSI_PhysicsUtils.SpherePlaneCollisionOccured(sphere, plane, out collision.point)) { collisionOccurred = true; } } // Sphere on box. if ((col1.pType == ColliderType.Sphere && col2.pType == ColliderType.Box) || (col1.pType == ColliderType.Box && col2.pType == ColliderType.Sphere)) { PSI_Collider_Sphere sphere = (PSI_Collider_Sphere)((col1.pType == ColliderType.Sphere) ? col1 : col2); PSI_Collider_Box box = (PSI_Collider_Box)((col1.pType == ColliderType.Sphere) ? col2 : col1); if (PSI_PhysicsUtils.SphereBoxCollisionOccured(sphere, box, out collision.point)) { collisionOccurred = true; } } // Box on box. if ((col1.pType == ColliderType.Box && col2.pType == ColliderType.Box)) { if (PSI_PhysicsUtils.BoxBoxCollisionOccured((PSI_Collider_Box)col1, (PSI_Collider_Box)col2, out collision.point)) { collisionOccurred = true; } } // Box on plane. if ((col1.pType == ColliderType.Box && col2.pType == ColliderType.Plane) || (col1.pType == ColliderType.Plane && col2.pType == ColliderType.Box)) { PSI_Collider_Box box = (PSI_Collider_Box)((col1.pType == ColliderType.Box) ? col1 : col2); PSI_Collider_Plane plane = (PSI_Collider_Plane)((col1.pType == ColliderType.Box) ? col2 : col1); if (PSI_PhysicsUtils.BoxPlaneCollisionOccured(box, plane, out collision.point)) { collisionOccurred = true; } } if (collisionOccurred) { mCollisionData.Add(collision); } }
public static bool BoxPlaneCollisionOccured(PSI_Collider_Box boxCol, PSI_Collider_Plane planeCol, out Vector3 point) { // Projecting the box vertices onto the plane. If a the vertex that is closest // to the plane intersects it then the box and plane are colliding. var boxVerts = boxCol.GetVertices(); float overlap = float.PositiveInfinity; bool collisionOccured = false; point = Vector3.zero; for (int i = 0; i < boxVerts.Length; i++) { float distanceToPlane; if (!planeCol.PosIsWithinPlaneBounds(boxVerts[i], out distanceToPlane)) { continue; } if (distanceToPlane <= 0f && Mathf.Abs(distanceToPlane) < boxCol.pSize.magnitude) { collisionOccured = true; if (distanceToPlane < overlap) { overlap = distanceToPlane; } } } if (collisionOccured) { // Resolve any overlap between the box and the plane. ResolveCollisionOverlaps(boxCol, planeCol, -planeCol.pNormal.normalized, overlap); // Getting the collision point by averaging the closest box verts to the plane. boxVerts = boxCol.GetVertices(); int touchingVertexCount = 0; for (int i = 0; i < boxVerts.Length; i++) { float distanceToPlane; if (!planeCol.PosIsWithinPlaneBounds(boxVerts[i], out distanceToPlane)) { continue; } if (distanceToPlane <= 0.01f) { point += boxVerts[i]; touchingVertexCount++; } } point /= (float)touchingVertexCount; // Calculate and apply the collision impulse to the box. ApplyImpulses(boxCol, planeCol, -planeCol.pNormal.normalized, point); // Apply friction to the box. ApplyFriction(boxCol, planeCol, point); return(true); } return(false); }
public static bool BoxBoxCollisionOccured(PSI_Collider_Box col1, PSI_Collider_Box col2, out Vector3 point) { point = Vector3.zero; // Determine the axis to check during SAT. var col1Axes = col1.GetAxes(); var col2Axes = col2.GetAxes(); var axesToCheck = new Vector3[] { col1Axes[0], col1Axes[1], col1Axes[2], col2Axes[0], col2Axes[1], col2Axes[2], Vector3.Cross(col1Axes[0], col2Axes[0]), Vector3.Cross(col1Axes[0], col2Axes[1]), Vector3.Cross(col1Axes[0], col2Axes[2]), Vector3.Cross(col1Axes[1], col2Axes[0]), Vector3.Cross(col1Axes[1], col2Axes[1]), Vector3.Cross(col1Axes[1], col2Axes[2]), Vector3.Cross(col1Axes[2], col2Axes[0]), Vector3.Cross(col1Axes[2], col2Axes[1]), Vector3.Cross(col1Axes[2], col2Axes[2]) }; // Determine the verts to check during SAT. var col1Verts = col1.GetVertices(); var col2Verts = col2.GetVertices(); // Determine if the boxes are colliding using SAT. Vector3 minOverlapAxis = Vector3.zero; float minOverlap = 0f; bool isColliding = CheckForOverlapUsingSAT(axesToCheck, col2Verts, col1Verts, out minOverlapAxis, out minOverlap) || CheckForOverlapUsingSAT(axesToCheck, col1Verts, col2Verts, out minOverlapAxis, out minOverlap); if (isColliding) { // Estimate the collision point by converting the box faces to planes and projecting the vertices of the other // box onto them. The projection points with the smallest distance are averaged to give the collision point. var facePlanes = new PSI_Plane[][] { col1.GetFacePlanes(), col2.GetFacePlanes() }; var verts = new Vector3[][] { col1Verts, col2Verts }; var contactPoints = new List <Vector3>(); float contactPointDist = float.PositiveInfinity; for (int i = 0; i < 2; i++) { foreach (var plane in facePlanes[i]) { foreach (var vert in verts[1 - i]) { float projectionDist = float.PositiveInfinity; if (plane.PointProjectsOntoPlane(vert, out projectionDist)) { projectionDist = Mathf.Abs(projectionDist); if (Mathf.Abs(projectionDist - contactPointDist) < float.Epsilon) { contactPoints.Add(vert); } else if (projectionDist < contactPointDist) { contactPoints.Clear(); contactPoints.Add(vert); contactPointDist = projectionDist; } } } } } point = Vector3.zero; foreach (var contactPoint in contactPoints) { point += contactPoint; } point /= contactPoints.Count; // Resolve any overlap between the boxes. var collisionAxis = CorrectCollisionAxisDirection(col2.pPosition, col1.pPosition, minOverlapAxis); ResolveCollisionOverlaps(col1, col2, collisionAxis, minOverlap); // Calculate and apply the collision impulse to the boxes. ApplyImpulses(col1, col2, collisionAxis, point); return(true); } return(false); }