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);
    }