public static bool SpherePlaneCollisionOccured(PSI_Collider_Sphere sphereCol, PSI_Collider_Plane planeCol, out Vector3 point) { // Determine the signed distance to from the sphere to its projected point on the plane. float distToProjectedPoint = Vector3.Dot(planeCol.pNormal, (sphereCol.pPosition - planeCol.pPosition)); // Determine the spheres projected point on the plane. point = sphereCol.pPosition - distToProjectedPoint * planeCol.pNormal; // Generate 4 triangles between the corners of the plane and the projected point. var planeVerts = planeCol.GetVertices(); var triangles = new Vector3[4, 3]; for (int i = 0; i < 4; i++) { triangles[i, 0] = point; triangles[i, 1] = planeVerts[i]; triangles[i, 2] = planeVerts[(i == 3) ? 0 : i + 1]; } // Sum the area of the traingles. float totalTriArea = 0.0f; for (int i = 0; i < 4; i++) { float a = Vector3.Distance(triangles[i, 0], triangles[i, 1]); float b = Vector3.Distance(triangles[i, 1], triangles[i, 2]); float c = Vector3.Distance(triangles[i, 2], triangles[i, 0]); float s = (a + b + c) / 2; totalTriArea += Mathf.Sqrt(s * (s - a) * (s - b) * (s - c)); } // Determine if a collision occured by checking if the sphere is overlapping with the plane and the projected point // is within the extents of the plane by checking the sum area of the triangles is equal to the size of the plane. bool isColliding = Mathf.Abs(totalTriArea - planeCol.pArea) < 0.01f && Mathf.Abs(distToProjectedPoint) <= sphereCol.pRadius; if (isColliding) { // Resolve any overlap between the sphere and the plane. var collisionAxis = CorrectCollisionAxisDirection(planeCol.pPosition, sphereCol.pPosition, point - sphereCol.pPosition); var overlap = collisionAxis.magnitude - sphereCol.pRadius; ResolveCollisionOverlaps(sphereCol, planeCol, collisionAxis, overlap); // Calculate and apply the collision impulse to the sphere. ApplyImpulses(sphereCol, planeCol, collisionAxis, point); // Apply friction to the sphere. ApplyFriction(sphereCol, planeCol, point); return(true); } return(false); }
//----------------------------------------Public Functions--------------------------------------- public static bool SphereSphereCollisionCheck(PSI_Collider_Sphere col1, PSI_Collider_Sphere col2, out Vector3 point) { // Determine if the sphere are colliding by doing a distance check. var collisionVector = col2.pPosition - col1.pPosition; point = col1.pPosition + collisionVector / 2f; bool isColliding = collisionVector.magnitude <= Mathf.Abs(col1.pRadius) + Mathf.Abs(col2.pRadius); if (isColliding) { // Resolve any overlap between the spheres. var collisionAxis = CorrectCollisionAxisDirection(col1.pPosition, col2.pPosition, collisionVector); var overlap = collisionAxis.magnitude - (col1.pRadius + col2.pRadius); ResolveCollisionOverlaps(col1, col2, collisionVector, overlap); // Calculate and apply the collision impulse to the spheres. ApplyImpulses(col1, col2, collisionVector, point); return(true); } return(false); }
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); } }