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);
    }
Beispiel #2
0
    //------------------------------------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);
    }