Esempio n. 1
0
        public static CollisionResult CollidesWith(this BoundingSphereD sphere, Triangle triangle, Vector3D velocity)
        {
            CollisionResult collisionResult = CollisionResult.NoCollision;

            /*if (!triangle.Plane.IsFrontFacingTo(velocity.Normalized()))
             * {
             *  return CollisionResult.NoCollision;
             * }*/

            if (velocity.IsParallelTo(triangle.Plane))
            {
                if (!sphere.EmbeddedIn(triangle.Plane))
                {
                    return(CollisionResult.NoCollision);
                }
            }
            else
            {
                #region CollisionInsideTriangle
                //Some precalculated variables we'll be using
                double signedDistToTrianglePlane = triangle.Plane.SignedDistanceTo(sphere.Center);
                double normalDotVelocity         = triangle.Plane.DotNormal(velocity);

                //parameters representing relative points along the velocity vector,
                //therefor ranging from 0 (current position)
                //to 1 (position after current velocity has been applied)
                //Calculate intersection values along the velocity vector
                double t0 = (-sphere.Radius - signedDistToTrianglePlane) / normalDotVelocity;
                double t1 = (sphere.Radius - signedDistToTrianglePlane) / normalDotVelocity;
                //Make sure t0 < t1
                MathExtensions.MinMax(ref t0, ref t1);
                //t1 is "less than or equal to" to prevent from being stuck when touching an object
                if (t0 > 1.0d || t1 <= 0.0d)
                {
                    //If t0-t1 is outside the range (0-1) there is no collision along the velocity vector
                    return(CollisionResult.NoCollision);
                }
                //Clamps t0 and t1 to the range (0-1), as we only care about the current frame
                //in which the values represent relative points along the current velocity vector.
                t0 = MathHelper.Clamp(t0, 0, 1);
                t1 = MathHelper.Clamp(t1, 0, 1);

                Vector3D planeIntersectionPoint =
                    sphere.Center - triangle.Plane.Normal * sphere.Radius + velocity * t0;

                //If the intersection point is in the triangle, we have a collision.
                //Since a collision with the "inside" of the triangle takes place before
                //any collision with its vertices or edges, this is the closest collision,
                //so we can safely return
                if (triangle.ContainsPoint(planeIntersectionPoint))
                {
                    collisionResult.FoundCollision    = true;
                    collisionResult.IntersectionTime  = t0;
                    collisionResult.IntersectionPoint = planeIntersectionPoint;
                    return(collisionResult);
                }
                #endregion
            }

            foreach (Vector3D vertex in triangle.Vertices)
            {
                CollisionResult vertexCollisionResult = sphere.CollidesWith(vertex, velocity);
                if (vertexCollisionResult.FoundCollision &&
                    vertexCollisionResult.IntersectionTime < collisionResult.IntersectionTime)
                {
                    collisionResult = vertexCollisionResult;
                }
            }

            foreach (Edge edge in triangle.Edges)
            {
                CollisionResult edgeCollisionResult = sphere.CollidesWith(edge, velocity);
                if (edgeCollisionResult.FoundCollision &&
                    edgeCollisionResult.IntersectionTime < collisionResult.IntersectionTime)
                {
                    collisionResult = edgeCollisionResult;
                }
            }

            return(collisionResult);
        }