Beispiel #1
0
        public const float Epsilon = 1E-5f; //for numerical imprecision
        
        /// <summary>
        /// Checks whether a ray intersects a triangle
        /// </summary>
        /// <returns>closest intersection point</returns>
        public static float? RayIntersectTriangle(Ray ray, Vector3[] vertices, 
                                                Matrix transform, out Triangle triangle)
        {
            triangle.v1 = triangle.v2 = triangle.v3 = Vector3.Zero;

            // Keep track of the closest triangle we found so far,
            // so we can always return the closest one.
            float? closestIntersection = null;

            Vector3 v1 = Vector3.Zero;
            Vector3 v2 = Vector3.Zero;
            Vector3 v3 = Vector3.Zero;

            // Loop over the vertex data, 3 at a time (3 vertices = 1 triangle).
            for (int i = 0; i < vertices.Length; i += 3)
            {
                // Perform a ray to triangle intersection test.
                float? intersection;

                // Transform the three vertex positions into world space
                v1 = Vector3.Transform(vertices[i], transform);
                v2 = Vector3.Transform(vertices[i + 1], transform);
                v3 = Vector3.Transform(vertices[i + 2], transform);

                RayIntersectsTriangle(ray, v1, v2, v3, out intersection);

                // Does the ray intersect this triangle?
                if (intersection != null)
                {
                    // If so, is it closer than any other previous triangle?
                    if ((closestIntersection == null) ||
                        (intersection < closestIntersection))
                    {
                        // Store the distance to this triangle.
                        closestIntersection = intersection;

                        // Store the three vertex positions into the vertex parameters.
                        triangle.v1 = v1;
                        triangle.v2 = v2;
                        triangle.v3 = v3;
                    }
                }
            }

            return closestIntersection;
        }
Beispiel #2
0
        /// <summary>
        /// It checks for the collision between a collision ray and a collision model.
        /// </summary>
        protected bool TestRayintersectModel(Ray ray, Vector3[] vertices,
                                            Matrix transform,
                                            out Vector3 intersect,
                                            out Vector3 normal,
                                            out float distance)
        {
            Triangle outTriangle = new Triangle(Vector3.Zero, Vector3.Zero, 
                Vector3.Zero);
            distance = 0.0f;
            intersect = Vector3.Zero;
            normal = Vector3.Zero;

            totalCollidingCount += vertices.Length;

            // Test ray with the model
            float? checkDistance = Helper3D.RayIntersectTriangle(ray, vertices, 
                transform, out outTriangle);

            if (checkDistance != null)
            {
                // Retry test for intersect point and normal
                return Helper3D.PointIntersect(ray.Position, ray.Direction, outTriangle,
                                    out distance, out intersect, out normal);
            }

            return false;
        }
Beispiel #3
0
        /// <summary>
        /// ray intersect face and return intersection distance, point and normal.
        /// </summary>
        public static bool PointIntersect(Vector3 rayOrigin, Vector3 rayDirection,
                            Triangle triangle, out float intersectDistance,
                            out Vector3 intersectPosition, out Vector3 intersectNormal)
        {
            intersectDistance = 0.0f;
            intersectPosition = rayOrigin;
            intersectNormal = Vector3.Zero;

            Vector3 uvt = Vector3.Zero;

            if (RayTriangleIntersect(rayOrigin, rayDirection,
                                    triangle.v1, triangle.v2, triangle.v3, 
                                    out uvt.Z, out uvt.X, out uvt.Y))
            {
                intersectDistance = uvt.Z;
                intersectPosition = (1.0f - uvt.X - uvt.Y) * triangle.v1 + uvt.X *
                                    triangle.v2 + uvt.Y * triangle.v3;
                intersectNormal = Vector3.Normalize(
                    Vector3.Cross(triangle.v3 - triangle.v1, triangle.v2 - triangle.v1));

                return true;
            }

            return false;
        }
Beispiel #4
0
        /// <summary>
        /// Checks whether a ray intersects a model. This method needs to access
        /// the model vertex data, 
        /// Returns the distance along the ray to the point of intersection, or null
        /// if there is no intersection.
        /// </summary>
        /// <returns>closest intersection point</returns> 
        public static float? RayIntersectModel(Ray ray, Model model, 
            Matrix worldTransform, out bool insideBoundingSphere, out Triangle triangle)
        {
            triangle.v1 = triangle.v2 = triangle.v3 = Vector3.Zero;

            // Look up our custom collision data from the Tag property of the model.
            Dictionary<string, object> tagData = (Dictionary<string, object>)model.Tag;

            if (tagData == null)
            {
                throw new InvalidOperationException(
                    "Model.Tag is not set correctly. Make sure your model " +
                    "was built using the custom CollideProcessor.");
            }

            // Start off with a fast bounding sphere test.
            BoundingSphere boundingSphere = (BoundingSphere)tagData["BoundingSphere"];

            if (boundingSphere.Intersects(ray) == null)
            {
                // If the ray does not intersect the bounding sphere, we cannot
                // possibly have picked this model, so there is no need to even
                // bother looking at the individual triangle data.
                insideBoundingSphere = false;

                return null;
            }
            else
            {
                // The bounding sphere test passed, so we need to do a full
                // triangle picking test.
                insideBoundingSphere = true;

                // Keep track of the closest triangle we found so far,
                // so we can always return the closest one.
                float? closestIntersection = null;

                // Loop over the vertex data, 3 at a time (3 vertices = 1 triangle).
                Vector3[] vertices = (Vector3[])tagData["Vertices"];

                for (int i = 0; i < vertices.Length; i += 3)
                {
                    // Perform a ray to triangle intersection test.
                    float? intersection;

                    RayIntersectsTriangle(ray,
                                          vertices[i],
                                          vertices[i + 1],
                                          vertices[i + 2],
                                          out intersection);

                    // Does the ray intersect this triangle?
                    if (intersection != null)
                    {
                        // If so, is it closer than any other previous triangle?
                        if ((closestIntersection == null) ||
                            (intersection < closestIntersection))
                        {
                            // Store the distance to this triangle.
                            closestIntersection = intersection;

                            // Transform the three vertex positions into world space,
                            // and store them into the output vertex parameters.
                            triangle.v1 
                                = Vector3.Transform(vertices[i], worldTransform);

                            triangle.v2 
                                = Vector3.Transform(vertices[i + 1], worldTransform);

                            triangle.v3 
                                = Vector3.Transform(vertices[i + 2], worldTransform);
                        }
                    }
                }

                return closestIntersection;
            }
        }