private OctreeNode <T> ResizeAndAdd(OctreeItem <T> octreeItem) { OctreeNode <T> oldRoot = this; Vector3 oldRootCenter = Bounds.GetCenter(); Vector3 oldRootHalfExtents = Bounds.GetDimensions() * 0.5f; Vector3 expandDirection = Vector3.Normalize(octreeItem.Bounds.GetCenter() - oldRootCenter); Vector3 newCenter = oldRootCenter; if (expandDirection.X >= 0) // oldRoot = Left { newCenter.X += oldRootHalfExtents.X; } else { newCenter.X -= oldRootHalfExtents.X; } if (expandDirection.Y >= 0) // oldRoot = Bottom { newCenter.Y += oldRootHalfExtents.Y; } else { newCenter.Y -= oldRootHalfExtents.Y; } if (expandDirection.Z >= 0) // oldRoot = Far { newCenter.Z += oldRootHalfExtents.Z; } else { newCenter.Z -= oldRootHalfExtents.Z; } BoundingBox newRootBounds = new BoundingBox(newCenter - oldRootHalfExtents * 2f, newCenter + oldRootHalfExtents * 2f); OctreeNode <T> newRoot = _nodeCache.GetNode(ref newRootBounds); OctreeNode <T> fittingNode = newRoot.SplitChildren(ref octreeItem.Bounds, oldRoot); if (fittingNode != null) { bool succeeded = fittingNode.CoreAddItem(octreeItem); Debug.Assert(succeeded, "Octree node returned from SplitChildren must fit the item given to it."); return(newRoot); } else { return(newRoot.CoreAddRootItem(octreeItem)); } }
private bool CoreAddItem(OctreeItem <T> item) { if (Bounds.Contains(ref item.Bounds) != ContainmentType.Contains) { return(false); } if (_items.Count >= MaxChildren && Children.Length == 0) { OctreeNode <T> newNode = SplitChildren(ref item.Bounds, null); if (newNode != null) { bool succeeded = newNode.CoreAddItem(item); Debug.Assert(succeeded, "Octree node returned from SplitChildren must fit the item given to it."); return(true); } } else if (Children.Length > 0) { foreach (var child in Children) { if (child.CoreAddItem(item)) { return(true); } } } // Couldn't fit in any children. #if DEBUG foreach (var child in Children) { Debug.Assert(child.Bounds.Contains(ref item.Bounds) != ContainmentType.Contains); } #endif _items.Add(item); item.Container = this; return(true); }