/// <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); }
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; }
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; }
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; }