public void GetEntries(BoundingSphere boundingShape, IList <BroadPhaseEntry> overlaps) { //Create a bounding box based on the bounding sphere. //Compute the min and max of the bounding box. //Loop through the cells and select bounding boxes which overlap the x axis. #if !WINDOWS Vector3f offset = new Vector3f(); #else Vector3f offset; #endif offset.X = boundingShape.Radius; offset.Y = offset.X; offset.Z = offset.Y; BoundingBox box; Vector3f.Add(ref boundingShape.Center, ref offset, out box.Max); Vector3f.Subtract(ref boundingShape.Center, ref offset, out box.Min); Int2 min, max; Grid2DSortAndSweep.ComputeCell(ref box.Min, out min); Grid2DSortAndSweep.ComputeCell(ref box.Max, out max); for (int i = min.Y; i <= max.Y; i++) { for (int j = min.Z; j <= max.Z; j++) { //Grab the cell that we are currently in. Int2 cellIndex; cellIndex.Y = i; cellIndex.Z = j; GridCell2D cell; if (owner.cellSet.TryGetCell(ref cellIndex, out cell)) { //To fully accelerate this, the entries list would need to contain both min and max interval markers. //Since it only contains the sorted min intervals, we can't just start at a point in the middle of the list. //Consider some giant bounding box that spans the entire list. for (int k = 0; k < cell.entries.Count && cell.entries.Elements[k].item.boundingBox.Min.X <= box.Max.X; k++) //TODO: Try additional x axis pruning? A bit of optimization potential due to overlap with AABB test. { bool intersects; var item = cell.entries.Elements[k].item; item.boundingBox.Intersects(ref boundingShape, out intersects); if (intersects && !overlaps.Contains(item)) { overlaps.Add(item); } } } } } }
public bool RayCast(Ray ray, float maximumLength, IList <BroadPhaseEntry> outputIntersections) { if (maximumLength == float.MaxValue) { throw new NotSupportedException("The Grid2DSortAndSweep broad phase cannot accelerate infinite ray casts. Consider specifying a maximum length or using a broad phase which supports infinite ray casts."); } //Use 2d line rasterization. //Compute the exit location in the cell. //Test against each bounding box up until the exit value is reached. float length = 0; Int2 cellIndex; Vector3f currentPosition = ray.Position; Grid2DSortAndSweep.ComputeCell(ref currentPosition, out cellIndex); while (true) { float cellWidth = 1 / Grid2DSortAndSweep.cellSizeInverse; float nextT; //Distance along ray to next boundary. float nextTy; //Distance along ray to next boundary along y axis. float nextTz; //Distance along ray to next boundary along z axis. //Find the next cell. if (ray.Direction.Y > 0) { nextTy = ((cellIndex.Y + 1) * cellWidth - currentPosition.Y) / ray.Direction.Y; } else if (ray.Direction.Y < 0) { nextTy = ((cellIndex.Y) * cellWidth - currentPosition.Y) / ray.Direction.Y; } else { nextTy = 10e10f; } if (ray.Direction.Z > 0) { nextTz = ((cellIndex.Z + 1) * cellWidth - currentPosition.Z) / ray.Direction.Z; } else if (ray.Direction.Z < 0) { nextTz = ((cellIndex.Z) * cellWidth - currentPosition.Z) / ray.Direction.Z; } else { nextTz = 10e10f; } bool yIsMinimum = nextTy < nextTz; nextT = yIsMinimum ? nextTy : nextTz; //Grab the cell that we are currently in. GridCell2D cell; if (owner.cellSet.TryGetCell(ref cellIndex, out cell)) { float endingX; if (ray.Direction.X < 0) { endingX = currentPosition.X; } else { endingX = currentPosition.X + ray.Direction.X * nextT; } //To fully accelerate this, the entries list would need to contain both min and max interval markers. //Since it only contains the sorted min intervals, we can't just start at a point in the middle of the list. //Consider some giant bounding box that spans the entire list. for (int i = 0; i < cell.entries.Count && cell.entries.Elements[i].item.boundingBox.Min.X <= endingX; i++) //TODO: Try additional x axis pruning? { var item = cell.entries.Elements[i].item; float t; if (ray.Intersects(ref item.boundingBox, out t) && t < maximumLength && !outputIntersections.Contains(item)) { outputIntersections.Add(item); } } } //Move the position forward. length += nextT; if (length > maximumLength) //Note that this catches the case in which the ray is pointing right down the middle of a row (resulting in a nextT of 10e10f). { break; } Vector3f offset; Vector3f.Multiply(ref ray.Direction, nextT, out offset); Vector3f.Add(ref offset, ref currentPosition, out currentPosition); if (yIsMinimum) { if (ray.Direction.Y < 0) { cellIndex.Y -= 1; } else { cellIndex.Y += 1; } } else if (ray.Direction.Z < 0) { cellIndex.Z -= 1; } else { cellIndex.Z += 1; } } return(outputIntersections.Count > 0); }
internal void Initialize(BroadPhaseEntry entry) { this.item = entry; Grid2DSortAndSweep.ComputeCell(ref entry.boundingBox.Min, out previousMin); Grid2DSortAndSweep.ComputeCell(ref entry.boundingBox.Max, out previousMax); }