Contains ray hit data.
Exemplo n.º 1
0
        /// <summary>
        /// Determines the intersection between a ray and a triangle.
        /// </summary>
        /// <param name="ray">Ray to test.</param>
        /// <param name="maximumLength">Maximum length to travel in units of the direction's length.</param>
        /// <param name="a">First vertex of the triangle.</param>
        /// <param name="b">Second vertex of the triangle.</param>
        /// <param name="c">Third vertex of the triangle.</param>
        /// <param name="hitClockwise">True if the the triangle was hit on the clockwise face, false otherwise.</param>
        /// <param name="hit">Hit data of the ray, if any</param>
        /// <returns>Whether or not the ray and triangle intersect.</returns>
        public static bool FindRayTriangleIntersection(ref Ray ray, float maximumLength, ref Vector3 a, ref Vector3 b, ref Vector3 c, out bool hitClockwise, out RayHit hit)
        {
            hitClockwise = false;
            hit = new RayHit();
            Vector3 ab = b - a;
            Vector3 ac = c - a;

            Vector3x.Cross(ref ab, ref ac, out hit.Normal);
            if (hit.Normal.LengthSquared() < Epsilon)
                return false; //Degenerate triangle!

            float d = -Vector3.Dot(ray.Direction, hit.Normal);

            hitClockwise = d >= 0;

            Vector3 ap = ray.Position - a;

            hit.T = Vector3.Dot(ap, hit.Normal);
            hit.T /= d;
            if (hit.T < 0 || hit.T > maximumLength)
                return false;//Hit is behind origin, or too far away.

            hit.Location = ray.Position + hit.T * ray.Direction;

            // Compute barycentric coordinates
            ap = hit.Location - a;
            float ABdotAB, ABdotAC, ABdotAP;
            float ACdotAC, ACdotAP;
            ABdotAB = Vector3.Dot(ab, ab);
            ABdotAC = Vector3.Dot(ab, ac);
            ABdotAP = Vector3.Dot(ab, ap);
            ACdotAC = Vector3.Dot(ac, ac);
            ACdotAP = Vector3.Dot(ac, ap);

            float denom = 1 / (ABdotAB * ACdotAC - ABdotAC * ABdotAC);
            float u = (ACdotAC * ABdotAP - ABdotAC * ACdotAP) * denom;
            float v = (ABdotAB * ACdotAP - ABdotAC * ABdotAP) * denom;

            return (u >= -Toolbox.BigEpsilon) && (v >= -Toolbox.BigEpsilon) && (u + v <= 1 + Toolbox.BigEpsilon);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Determines the intersection between a ray and a triangle.
        /// </summary>
        /// <param name="ray">Ray to test.</param>
        /// <param name="maximumLength">Maximum length to travel in units of the direction's length.</param>
        /// <param name="sidedness">Sidedness of the triangle to test.</param>
        /// <param name="a">First vertex of the triangle.</param>
        /// <param name="b">Second vertex of the triangle.</param>
        /// <param name="c">Third vertex of the triangle.</param>
        /// <param name="hit">Hit data of the ray, if any</param>
        /// <returns>Whether or not the ray and triangle intersect.</returns>
        public static bool FindRayTriangleIntersection(ref Ray ray, float maximumLength, TriangleSidedness sidedness, ref Vector3 a, ref Vector3 b, ref Vector3 c, out RayHit hit)
        {
            hit = new RayHit();
            Vector3 ab = b - a;
            Vector3 ac = c - a;
            Vector3x.Cross(ref ab, ref ac, out hit.Normal);
            if (hit.Normal.LengthSquared() < Epsilon)
                return false; //Degenerate triangle!

            float d = -Vector3.Dot(ray.Direction, hit.Normal);
            switch (sidedness)
            {
                case TriangleSidedness.DoubleSided:
                    if (d <= 0) //Pointing the wrong way.  Flip the normal.
                    {
                        hit.Normal = -hit.Normal;
                        d = -d;
                    }
                    break;
                case TriangleSidedness.Clockwise:
                    if (d <= 0) //Pointing the wrong way.  Can't hit.
                        return false;

                    break;
                case TriangleSidedness.Counterclockwise:
                    if (d >= 0) //Pointing the wrong way.  Can't hit.
                        return false;

                    hit.Normal = -hit.Normal;
                    d = -d;
                    break;
            }

            Vector3 ap = ray.Position - a;

            hit.T = Vector3.Dot(ap, hit.Normal);
            hit.T /= d;
            if (hit.T < 0 || hit.T > maximumLength)
                return false;//Hit is behind origin, or too far away.

            hit.Location = ray.Position + hit.T * ray.Direction;

            // Compute barycentric coordinates
            ap = hit.Location - a;
            float ABdotAB, ABdotAC, ABdotAP;
            float ACdotAC, ACdotAP;
            ABdotAB = Vector3.Dot(ab, ab);
            ABdotAC = Vector3.Dot(ab, ac);
            ABdotAP = Vector3.Dot(ab, ap);
            ACdotAC = Vector3.Dot(ac, ac);
            ACdotAP = Vector3.Dot(ac, ap);

            float denom = 1 / (ABdotAB * ACdotAC - ABdotAC * ABdotAC);
            float u = (ACdotAC * ABdotAP - ABdotAC * ACdotAP) * denom;
            float v = (ABdotAB * ACdotAP - ABdotAC * ABdotAP) * denom;

            return (u >= -Toolbox.BigEpsilon) && (v >= -Toolbox.BigEpsilon) && (u + v <= 1 + Toolbox.BigEpsilon);
        }