/// <inheritdoc/> public override Vector3 Intersect(ScaledRay ray) { Vector3 intersection; Intersect(ray, out intersection); return(intersection); }
private void FaceCenterIntersections() { foreach (var face in topology.internalFaces) { var position = facePositions[face]; var normal = surface.GetNormal(position); var ray = new ScaledRay(position + normal, -normal); var foundFace = partitioning.FindFace(ray); Assert.AreEqual(face, foundFace, string.Format("Face center: {0}", facePositions[face])); } }
/// <inheritdoc/> public override bool Intersect(ScaledRay ray, out Vector3 intersection) { if (!isInverted) { return(Geometry.IntersectForwardExternal(new Sphere(Vector3.zero, radius), ray, out intersection)); } else { return(Geometry.IntersectForwardInternal(new Sphere(Vector3.zero, radius), ray, out intersection)); } }
/// <summary> /// Finds the face with which the given ray intersects. /// </summary> /// <param name="ray">The ray to intersect with the manifold to find which face it intersects.</param> /// <returns>The first face which is intersected by the given ray, or an empty face if the ray does not intersect the manifold at all.</returns> public Topology.Face FindFace(ScaledRay ray) { Vector3 intersection; if (_surface.Intersect(ray, out intersection)) { return(FindFace(intersection)); } else { return(new Topology.Face()); } }
private void FaceEdgeMidpointWeightedIntersections() { foreach (var face in topology.internalFaces) { foreach (var edge in face.edges) { var position = (edgeMidpoints[edge] * 4f + facePositions[face]) * 0.2f; var normal = surface.GetNormal(position); var ray = new ScaledRay(position + normal, -normal); var foundFace = partitioning.FindFace(ray); Assert.AreEqual(face, foundFace, string.Format("Face center: {0}, Ray target: {1}, Edge midpoint: {2}", facePositions[face], position, edgeMidpoints[edge])); } } }
/// <inheritdoc/> public override bool Intersect(ScaledRay ray, out Vector3 intersection) { return(Geometry.Intersect(plane, ray, out intersection)); }
/// <inheritdoc/> public override Vector3 Intersect(ScaledRay ray) { return(Geometry.Intersect(plane, ray)); }
protected void GetGhostRegions(Camera camera, float bufferRadius, List <GhostRegion> ghostRegions) { // Get the six planes of the frustum volume, and expand them outward based on the buffer radius. var frustumPlanes = UnityEngine.GeometryUtility.CalculateFrustumPlanes(camera); if (bufferRadius != 0f) { for (int i = 0; i < frustumPlanes.Length; ++i) { frustumPlanes[i] = new Plane(frustumPlanes[i].normal, frustumPlanes[i].distance + bufferRadius); } } // Find the eight corners of the camera view frustum. var corners = Geometry.FindFrustumCorners(camera, frustumPlanes); // Find the maximum ghost region index extents based on these eight corners. IntVector3 min = new IntVector3(int.MaxValue, int.MaxValue, int.MaxValue); IntVector3 max = new IntVector3(int.MinValue, int.MinValue, int.MinValue); for (int i = 0; i < corners.Length; ++i) { ExpandIndexBounds(GetGhostRegionIndex(corners[i]), ref min, ref max); } // If the bounds are limited to a single dimension, then just return a linear array of ghost regions. if (min.y == max.y && min.z == max.z) { int startIndex = 0; for (int x = min.x; x <= max.x; ++x) { if (x == 0 && min.y == 0 && min.z == 0) { continue; // The 0,0,0 region is the real region, not a ghost region, so skip it. } InsertGhostRegion(new IntVector3(x, min.y, min.z), ghostRegions, ref startIndex); } return; } else if (min.x == max.x && min.z == max.z) { int startIndex = 0; for (int y = min.y; y <= max.y; ++y) { if (min.x == 0 && y == 0 && min.z == 0) { continue; // The 0,0,0 region is the real region, not a ghost region, so skip it. } InsertGhostRegion(new IntVector3(min.x, y, min.z), ghostRegions, ref startIndex); } return; } else if (min.x == max.x && min.y == max.y) { int startIndex = 0; for (int z = min.z; z <= max.z; ++z) { if (min.x == 0 && min.y == 0 && z == 0) { continue; // The 0,0,0 region is the real region, not a ghost region, so skip it. } InsertGhostRegion(new IntVector3(min.x, min.y, z), ghostRegions, ref startIndex); } return; } // If we haven't returned yet, then the bounds are not limited to a single dimension, which means that not all // regions in the determined bounds are guaranteed to actually intersect with the frustum, and there's no value // in returning any regions that don't intersect. However, returning such regions shouldn't actually cause any // harm in terms of correctness, only performance, so there's some leeway for doing the rejection. int unwrappedAxis; if (!axis0IsWrapped) { unwrappedAxis = 0; } else if (!axis1IsWrapped) { unwrappedAxis = 1; } else if (!axis2IsWrapped) { unwrappedAxis = 2; } else { unwrappedAxis = -1; } var regionCorners = unwrappedAxis == -1 ? new Vector3[8] : null; var regionLines = unwrappedAxis != -1 ? new ScaledRay[4] : null; if (unwrappedAxis == -1) { int startIndex = 0; for (int z = min.z; z <= max.z; ++z) { for (int y = min.y; y <= max.y; ++y) { for (int x = min.x; x <= max.x; ++x) { if (x == 0 && y == 0 && z == 0) { continue; // The 0,0,0 region is the real region, not a ghost region, so skip it. } regionCorners[0] = _transformedAxis0Vector * x + _transformedAxis1Vector * y + _transformedAxis2Vector * z; regionCorners[1] = regionCorners[0] + _transformedAxis0Vector; regionCorners[2] = regionCorners[0] + _transformedAxis1Vector; regionCorners[3] = regionCorners[0] + _transformedAxis2Vector; regionCorners[4] = regionCorners[1] + _transformedAxis1Vector; regionCorners[5] = regionCorners[2] + _transformedAxis2Vector; regionCorners[6] = regionCorners[3] + _transformedAxis0Vector; regionCorners[7] = regionCorners[4] + _transformedAxis2Vector; bool exclude = false; foreach (var plane in frustumPlanes) { if (Geometry.AllAreBelow(regionCorners, plane)) { exclude = true; break; } } if (!exclude) { InsertGhostRegion(new IntVector3(x, y, z), ghostRegions, ref startIndex); } } } } } else { int startIndex = 0; for (int z = min.z; z <= max.z; ++z) { for (int y = min.y; y <= max.y; ++y) { for (int x = min.x; x <= max.x; ++x) { if (x == 0 && y == 0 && z == 0) { continue; // The 0,0,0 region is the real region, not a ghost region, so skip it. } switch (unwrappedAxis) { case 0: regionLines[0] = new ScaledRay(_transformedAxis1Vector * y + _transformedAxis2Vector * z, _transformedAxis0Vector); regionLines[1] = new ScaledRay(regionLines[0].origin + _transformedAxis1Vector, _transformedAxis0Vector); regionLines[2] = new ScaledRay(regionLines[0].origin + _transformedAxis2Vector, _transformedAxis0Vector); regionLines[3] = new ScaledRay(regionLines[1].origin + _transformedAxis2Vector, _transformedAxis0Vector); break; case 1: regionLines[0] = new ScaledRay(_transformedAxis0Vector * x + _transformedAxis2Vector * z, _transformedAxis1Vector); regionLines[1] = new ScaledRay(regionLines[0].origin + _transformedAxis0Vector, _transformedAxis1Vector); regionLines[2] = new ScaledRay(regionLines[0].origin + _transformedAxis2Vector, _transformedAxis1Vector); regionLines[3] = new ScaledRay(regionLines[1].origin + _transformedAxis2Vector, _transformedAxis1Vector); break; case 2: regionLines[0] = new ScaledRay(_transformedAxis0Vector * x + _transformedAxis1Vector * y, _transformedAxis2Vector); regionLines[1] = new ScaledRay(regionLines[0].origin + _transformedAxis0Vector, _transformedAxis2Vector); regionLines[2] = new ScaledRay(regionLines[0].origin + _transformedAxis1Vector, _transformedAxis2Vector); regionLines[3] = new ScaledRay(regionLines[1].origin + _transformedAxis1Vector, _transformedAxis2Vector); break; default: throw new System.NotImplementedException(); } bool exclude = true; foreach (var plane in frustumPlanes) { var minT = float.NegativeInfinity; var maxT = float.PositiveInfinity; if (Geometry.TruncateLineSegment(regionLines[0], plane, ref minT, ref maxT) <= 0f) { continue; } if (Geometry.TruncateLineSegment(regionLines[1], plane, ref minT, ref maxT) <= 0f) { continue; } if (Geometry.TruncateLineSegment(regionLines[2], plane, ref minT, ref maxT) <= 0f) { continue; } if (Geometry.TruncateLineSegment(regionLines[3], plane, ref minT, ref maxT) <= 0f) { continue; } exclude = false; break; } if (!exclude) { InsertGhostRegion(new IntVector3(x, y, z), ghostRegions, ref startIndex); } } } } } }
/// <inheritdoc/> public abstract bool Intersect(ScaledRay ray, out Vector3 intersection);
/// <inheritdoc/> public abstract Vector3 Intersect(ScaledRay ray);