Beispiel #1
0
        /// <summary>
        /// Test whether an object collides with the tester
        /// </summary>
        /// <param name="collisionTester">A mesh collider located at the origin used to test the object in it's local space</param>
        /// <param name="obj">The object to test collision on</param>
        /// <param name="tester">The tester object</param>
        /// <param name="collisionPoint">The point of collision between the tester and the surface of the object</param>
        /// <returns>The result of whether the tester is in intersection with or located within the object</returns>
        public static bool TestObject(MeshCollider collisionTester, Renderer obj, IntersectionTester tester,
                                      out Vector3 collisionPoint)
        {
            var transform = obj.transform;

            SetupCollisionTester(collisionTester, transform);

            // Try a simple test with specific rays located at vertices
            for (var j = 0; j < tester.rays.Length; j++)
            {
                var ray = tester.rays[j];

                //Transform rays to world space, then to object's local space
                var testerTransform = tester.transform;
                var objectTransform = obj.transform;
                ray.origin    = objectTransform.InverseTransformPoint(testerTransform.TransformPoint(ray.origin));
                ray.direction = objectTransform.InverseTransformDirection(testerTransform.TransformDirection(ray.direction));

                RaycastHit hit;
                if (TestRay(collisionTester, transform, ray, out hit))
                {
                    collisionPoint = hit.point;
                    return(true);
                }
            }

            // Try a more robust version with all edges
            return(TestEdges(collisionTester, transform, tester, out collisionPoint));
        }
        /// <summary>
        /// Test whether an object collides with the tester
        /// </summary>
        /// <param name="collisionTester">A mesh collider located at the origin used to test the object in it's local space</param>
        /// <param name="obj">The object to test collision on</param>
        /// <param name="tester">The tester object</param>
        /// <returns>The result of whether the tester is in intersection with or located within the object</returns>
        public static bool TestObject(MeshCollider collisionTester, Renderer obj, IntersectionTester tester)
        {
            var transform = obj.transform;

            SetupCollisionTester(collisionTester, transform);

            // Try a simple test with specific rays located at vertices
            for (var j = 0; j < tester.rays.Length; j++)
            {
                var ray = tester.rays[j];

                //Transform rays to world space
                var testerTransform = tester.transform;
                ray.origin    = testerTransform.TransformPoint(ray.origin);
                ray.direction = testerTransform.TransformDirection(ray.direction);

                if (TestRay(collisionTester, transform, ray))
                {
                    return(true);
                }
            }

            // Try a more robust version with all edges
            return(TestEdges(collisionTester, transform, tester));
        }
    void OnSceneGUI()
    {
        IntersectionTester tester = (IntersectionTester)target;

        float handleSize = HandleUtility.GetHandleSize((Vector3)tester.v0) / 8.0f;

        tester.v0 = Handles.Slider2D(tester.v0, Vector3.up, Vector3.right, Vector3.forward, handleSize, Handles.SphereCap, new Vector2(0.1f, 0.1f));
        tester.v1 = Handles.Slider2D(tester.v1, Vector3.up, Vector3.right, Vector3.forward, handleSize, Handles.SphereCap, new Vector2(0.1f, 0.1f));
        tester.v2 = Handles.Slider2D(tester.v2, Vector3.up, Vector3.right, Vector3.forward, handleSize, Handles.SphereCap, new Vector2(0.1f, 0.1f));
        tester.v3 = Handles.Slider2D(tester.v3, Vector3.up, Vector3.right, Vector3.forward, handleSize, Handles.SphereCap, new Vector2(0.1f, 0.1f));
        tester.v4 = Handles.Slider2D(tester.v4, Vector3.up, Vector3.right, Vector3.forward, handleSize, Handles.SphereCap, new Vector2(0.1f, 0.1f));

        Vector2 altV0 = new Vector2(tester.v0.x, tester.v0.z);
        Vector2 altV1 = new Vector2(tester.v1.x, tester.v1.z);
        Vector2 altV2 = new Vector2(tester.v2.x, tester.v2.z);
        Vector2 altV3 = new Vector2(tester.v3.x, tester.v3.z);
        Vector2 altV4 = new Vector2(tester.v4.x, tester.v4.z);

        Vector2 i0, i1;

        bool intersection = MathsHelper.LineTriIntersect(altV0, altV1, altV2, altV3, altV4, out i0, out i1);

        intersection |= MathsHelper.LineInTri(altV0, altV1, altV2, altV3, altV4);

        Handles.color = intersection ? Color.red : Color.green;

        Handles.DrawLine(tester.v0, tester.v1);

        Handles.DrawLine(tester.v2, tester.v3);
        Handles.DrawLine(tester.v4, tester.v3);
        Handles.DrawLine(tester.v4, tester.v2);
    }
Beispiel #4
0
        public Raytracer(Scene scene)
        {
            this.scene         = scene;
            IntersectionTester = new IntersectionTester(scene);

            const float aspectRatio = 16.0f / 9.0f;

            this.viewPlaneHeight = (float)Math.Tan(scene.fieldOfView) * Math.Abs(scene.cameraDistance) * 2;
            this.viewPlaneWidth  = aspectRatio * viewPlaneHeight;
        }
Beispiel #5
0
        public bool GetOverlappedChunks(BoundingBox box, Point3 min, Point3 max)
        {
            // make sure the given box actually intersects with the map in the first place
            var bounds = _bounds;

            if (!IntersectionTester.Test(ref bounds, ref box))
            {
                return(false);
            }

            // convert to tile coords. this is in "tilemap space" which is how we want it
            // HACK: ceil() calls and "-1"'s keep us from picking up too many/too few
            // blocks. these were arrived at through observation
            int minX = (int)box.Min.X;
            int minY = (int)box.Min.Y;
            int minZ = (int)box.Min.Z;
            int maxX = (int)Math.Ceiling(box.Max.X);
            int maxY = (int)Math.Ceiling(box.Max.Y - 1.0f);
            int maxZ = (int)Math.Ceiling(box.Max.Z);

            // now convert to chunk coords
            int minChunkX = minX / ChunkWidth;
            int minChunkY = minY / ChunkHeight;
            int minChunkZ = minZ / ChunkDepth;
            int maxChunkX = maxX / ChunkWidth;
            int maxChunkY = maxY / ChunkHeight;
            int maxChunkZ = maxZ / ChunkDepth;

            // trim off the excess bounds so that we end up with a min-to-max area
            // that is completely within the chunk bounds of the map
            // HACK: "-1"'s keep us from picking up too many chunks. these were arrived
            // at through observation
            minChunkX = MathHelpers.Clamp(minChunkX, 0, WidthInChunks);
            minChunkY = MathHelpers.Clamp(minChunkY, 0, (HeightInChunks - 1));
            minChunkZ = MathHelpers.Clamp(minChunkZ, 0, DepthInChunks);
            maxChunkX = MathHelpers.Clamp(maxChunkX, 0, WidthInChunks);
            maxChunkY = MathHelpers.Clamp(maxChunkY, 0, (HeightInChunks - 1));
            maxChunkZ = MathHelpers.Clamp(maxChunkZ, 0, DepthInChunks);

            // return the leftover area
            min.X = minChunkX;
            min.Y = minChunkY;
            min.Z = minChunkZ;
            max.X = maxChunkX;
            max.Y = maxChunkY;
            max.Z = maxChunkZ;

            return(true);
        }
        /// <summary>
        /// Test the edges of the tester's collider against another mesh collider for intersection of being contained within
        /// </summary>
        /// <param name="collisionTester">A mesh collider located at the origin used to test the object in it's local space</param>
        /// <param name="obj">The object to test collision on</param>
        /// <param name="tester">The tester object</param>
        /// <returns>The result of whether the point/ray is intersection with or located within the object</returns>
        public static bool TestEdges(MeshCollider collisionTester, Transform obj, IntersectionTester tester)
        {
            var boundsMagnitude = collisionTester.bounds.size.magnitude;

            var triangles = tester.triangles;
            var vertices  = tester.vertices;

            var testerTransform = tester.transform;

            for (var i = 0; i < triangles.Length; i += 3)
            {
                k_TriangleVertices[0] = vertices[triangles[i]];
                k_TriangleVertices[1] = vertices[triangles[i + 1]];
                k_TriangleVertices[2] = vertices[triangles[i + 2]];

                for (var j = 0; j < 3; j++)
                {
                    RaycastHit hitInfo;

                    var start       = obj.InverseTransformPoint(testerTransform.TransformPoint(k_TriangleVertices[j]));
                    var end         = obj.InverseTransformPoint(testerTransform.TransformPoint(k_TriangleVertices[(j + 1) % 3]));
                    var edge        = end - start;
                    var maxDistance = Mathf.Max(edge.magnitude, boundsMagnitude);
                    var direction   = edge.normalized;

                    // Handle degenerate triangles
                    if (Mathf.Approximately(direction.magnitude, 0f))
                    {
                        continue;
                    }

                    // Shoot a ray from outside the object (due to face normals) in the direction of the ray to see if it is inside
                    var forwardRay = new Ray(start, direction);
                    forwardRay.origin = forwardRay.GetPoint(-maxDistance);

                    Vector3 forwardHit;

                    if (collisionTester.Raycast(forwardRay, out hitInfo, maxDistance * 2f))
                    {
                        forwardHit = hitInfo.point;
                    }
                    else
                    {
                        continue;
                    }

                    // Shoot a ray in the other direction, too, from outside the object (due to face normals)
                    Vector3 behindHit;
                    var     behindRay = new Ray(end, -direction);
                    behindRay.origin = behindRay.GetPoint(-maxDistance);
                    if (collisionTester.Raycast(behindRay, out hitInfo, maxDistance * 2f))
                    {
                        behindHit = hitInfo.point;
                    }
                    else
                    {
                        continue;
                    }

                    // Check whether the triangle edge is contained or intersects with the object
                    var A = forwardHit;
                    var B = behindHit;
                    var C = start;
                    var D = end;
                    if (OnSegment(A, C, B) ||
                        OnSegment(A, D, B) ||
                        OnSegment(C, A, D) ||
                        OnSegment(C, B, D))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
 public MiniWorldRay(Transform originalRayOrigin, IMiniWorld miniWorld, IProxy proxy, Node node, IntersectionTester tester)
 {
     this.originalRayOrigin = originalRayOrigin;
     this.miniWorld         = miniWorld;
     this.proxy             = proxy;
     this.node   = node;
     this.tester = tester;
 }
Beispiel #8
0
 public MiniWorldRay(Transform originalRayOrigin, IMiniWorld miniWorld, IProxy proxy, Node node, ActionMapInput directSelectInput, IntersectionTester tester)
 {
     this.originalRayOrigin = originalRayOrigin;
     this.miniWorld         = miniWorld;
     this.proxy             = proxy;
     this.node = node;
     this.directSelectInput = directSelectInput;
     this.tester            = tester;
 }