// Returns true if the two AABBs intersect, false otherwise public static bool CheckIntersection(AABB first, AABB second) { for (int dim = 0; dim < 3; dim++) if (first.array[dim][1] < second.array[dim][0] || first.array[dim][0] > second.array[dim][1]) return false; return true; }
public PartitioningGrid(AABB bounds, int max_subdivisions) { this.bounds = bounds; this.max_subdivisions = max_subdivisions; items = new List<int>[2]; for(int i = 0; i < 2; i++) items[i] = new List<int>(); }
// Computes and returns an AABB encompassing the intersection of the two input boxes' volumes // Don't use this value if CheckIntersection failed! public static AABB Intersection(AABB first, AABB second) { AABB result = new AABB { array = EmptyBoundsArray }; for (int dim = 0; dim < 3; dim++) { result.array[dim][0] = Math.Max(first.array[dim][0], second.array[dim][0]); result.array[dim][1] = Math.Min(first.array[dim][1], second.array[dim][1]); } return result; }
// Returns an AABB expanded from the input AABB as necessary in order to include the specified point public static AABB ExpandedToFit(AABB input, Vec3 point) { AABB result = new AABB { array = EmptyBoundsArray }; double[] point_array = new double[] { point.x, point.y, point.z }; for (int dim = 0; dim < 3; dim++) { result.array[dim][0] = Math.Min(input.array[dim][0], point_array[dim]); result.array[dim][1] = Math.Max(input.array[dim][1], point_array[dim]); } return result; }
// Inserts an item into the category-th list (possibly of children, based on the item's bounding box) public void InsertItem(int category, int item, AABB box) { if(AABB.CheckIntersection(box, bounds)) { items[category].Add(item); if (children == null && max_subdivisions > 0) Subdivide(); if (children != null) foreach (PartitioningGrid grid in children) grid.InsertItem(category, item, box); } max_encountered_item[category] = Math.Max(max_encountered_item[category], item); }
// Utility function to figure out how well a subdivision point splits stuff public int[,,] CheckSubdivision(Vec3 split) { int[, ,] results = new int[2, 2, 2]; double[][] array = new double[][] { new double[] { bounds.array[0][0], split.x, bounds.array[0][1] }, new double[] { bounds.array[1][0], split.y, bounds.array[1][1] }, new double[] { bounds.array[2][0], split.z, bounds.array[2][1] } }; for (int i = 0; i < 2; i++) for (int j = 0; j < 2; j++) for (int k = 0; k < 2; k++) { AABB subregion = new AABB { array = new double[][] { new double[] { array[0][i], array[0][i + 1] }, new double[] { array[1][j], array[1][j + 1] }, new double[] { array[2][k], array[2][k + 1] } } }; foreach (Item item in items) if (AABB.CheckIntersection(item.aabb, subregion)) results[i, j, k]++; } return results; }
public Octree(AABB bounds) { this.bounds = bounds; items = new List<Item>(); }
// Function defining how to subdivide an Octree // Return values should generally be the same type as the subtype of Octree protected virtual Octree Subdivision(AABB aabb) { return new Octree(aabb); }
// Boring constructor // Just calls BoundsInit with the same arguments you gave the constructor public ModelIntersectTree(AABB bounds, int max_subdivisions) { BoundsInit(bounds, max_subdivisions); }
protected virtual void BoundsInit(AABB bounds, int max_subdivisions) { this.bounds = bounds; this.max_subdivisions = max_subdivisions; items = new List<Octree.Item>[2]; for (int i = 0; i < 2; i++) items[i] = new List<Octree.Item>(); }