public PSI_Plane[] GetFacePlanes() { // Generating a returning the box faces as planes. var facePlanes = new PSI_Plane[6]; facePlanes[0] = new PSI_Plane(pPosition - transform.right * pSize.x * 0.5f, this.transform.rotation * Quaternion.Euler(0, 0, 90), new Vector2(pSize.y, pSize.z)); facePlanes[1] = new PSI_Plane(pPosition - transform.up * pSize.y * 0.5f, this.transform.rotation * Quaternion.Euler(0, 0, 180), new Vector2(pSize.x, pSize.z)); facePlanes[2] = new PSI_Plane(pPosition + transform.right * pSize.x * 0.5f, this.transform.rotation * Quaternion.Euler(0, 0, -90), new Vector2(pSize.y, pSize.z)); facePlanes[3] = new PSI_Plane(pPosition + transform.up * pSize.y * 0.5f, this.transform.rotation * Quaternion.Euler(0, 0, 0), new Vector2(pSize.x, pSize.z)); facePlanes[4] = new PSI_Plane(pPosition + transform.forward * pSize.z * 0.5f, this.transform.rotation * Quaternion.Euler(90, 0, 0), new Vector2(pSize.x, pSize.y)); facePlanes[5] = new PSI_Plane(pPosition - transform.forward * pSize.z * 0.5f, this.transform.rotation * Quaternion.Euler(-90, 0, 0), new Vector2(pSize.x, pSize.y)); return(facePlanes); }
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); }