/// <summary> /// Try to add an object, starting at this node /// </summary> public bool TryAddObj(OctreeObject <T> newObj, bool updateCount) { OctreeNode childNode = this;//Start here int index; while (true) { if (!childNode.ContainsBounds(ref newObj.boundsMin, ref newObj.boundsMax)) { //Doesn't fit in this node. Put it in the parent node. if (childNode.childIndex == -1) { return(false); } childNode.parent.PutObjectInNode(newObj, updateCount); return(true); } index = childNode.BestFitChild(ref newObj.boundsCenter); if (childNode.isLeaf && childNode.localItemCount >= numObjectsAllowed && childNode.ContainsBounds(ref newObj.doubleBoundsMin, ref newObj.doubleBoundsMax)) { childNode.Split();//We hit the limit and we can split. We only split if the object will fit in the new bounds } if (!childNode.isLeaf) { //Drop down another level if we have children childNode = childNode.children[index]; } else { //Place it here. We have no children and we're under the limit childNode.PutObjectInNode(newObj, updateCount); return(true); } } }
static void Main(string[] args) { var bounds = new CubeBounds(Vector.Zero, 2); var octree = new Octree <string>(bounds); //for (int i = 0; i < 100; i++) //{ // octree.AddValue(Vector.Random(), "beer"); //} //octree.PrintTree(); var point = Vector.Zero; OctreeNode <string> node = new OctreeNode <string>(bounds, 0); node.Split(); foreach (var child in node.Children) { Console.Write(child.Index + " "); Console.WriteLine(child.Bounds.Contains(point)); } Console.WriteLine(node.GetChildContainingPoint(point).Index); Console.ReadKey(); }
// Returns whether the node is changed. private bool RemoveInternal(IntBox area, OctreeNode <T> node, int level, IntVector3 corner) { IntBox nodeArea = new IntBox(corner, corner + ((1 << level) - 1) * IntVector3.one); if (area.Contains(nodeArea)) { if (!node.isEmpty) { node.obj = default(T); node.objCount = 0; node.RemoveChildren(); return(true); } else { return(false); } } else if (!node.obj.Equals(default(T))) { node.Split(); } int childSize = 1 << (level - 1); IntVector3 childIndexMin = IntVector3.Max((area.min - corner) / childSize, IntVector3.zero); IntVector3 childIndexMax = IntVector3.Min((area.max - corner) / childSize, IntVector3.one); bool changed = false; for (int x = childIndexMin.x; x <= childIndexMax.x; x++) { for (int y = childIndexMin.y; y <= childIndexMax.y; y++) { for (int z = childIndexMin.z; z <= childIndexMax.z; z++) { IntVector3 childIndex = new IntVector3(x, y, z); var childNode = node.GetChild(childIndex); if (childNode != null) { long oldChildObjCount = childNode.objCount; bool childChanged = RemoveInternal(area, childNode, level - 1, corner + childIndex * childSize); if (childChanged) { changed = true; node.objCount += childNode.objCount - oldChildObjCount; if (childNode.isEmpty) { node.RemoveChild(childIndex); } } } } } } return(changed); }
// Returns whether the node is changed. private bool SetInternal(IntBox area, T obj, OctreeNode <T> node, int level, IntVector3 corner) { IntBox nodeArea = new IntBox(corner, corner + ((1 << level) - 1) * IntVector3.one); if (node.obj.Equals(obj)) { return(false); } else if (area.Contains(nodeArea)) { node.obj = obj; node.objCount = 1 << level; node.RemoveChildren(); return(true); } else if (node.isFilled) { node.Split(); } int childSize = 1 << (level - 1); IntVector3 childIndexMin = IntVector3.Max((area.min - corner) / childSize, IntVector3.zero); IntVector3 childIndexMax = IntVector3.Min((area.max - corner) / childSize, IntVector3.one); bool changed = false; for (int x = childIndexMin.x; x <= childIndexMax.x; x++) { for (int y = childIndexMin.y; y <= childIndexMax.y; y++) { for (int z = childIndexMin.z; z <= childIndexMax.z; z++) { IntVector3 childIndex = new IntVector3(x, y, z); var childNode = node.GetChild(childIndex); if (childNode == null) { childNode = node.CreateChild(childIndex); } long oldChildObjCount = childNode.objCount; bool childChanged = SetInternal(area, obj, childNode, level - 1, corner + childIndex * childSize); if (childChanged) { changed = true; node.objCount += childNode.objCount - oldChildObjCount; if (childNode.isFilled) { node.MergeIfPossible(obj); } } } } } return(changed); }
// Returns whether the node is changed. private bool RemoveInternal(IntVector3 coords, OctreeNode <T> node, int level, IntVector3 corner) { if (level == 0) { if (!node.isEmpty) { node.obj = default(T); node.objCount = 0; return(true); } else { return(false); } } else if (!node.obj.Equals(default(T))) { node.Split(); } int childSize = 1 << (level - 1); IntVector3 childIndex = (coords - corner) / childSize; var childNode = node.GetChild(childIndex); if (childNode == null) { return(false); } long oldChildObjCount = childNode.objCount; bool changed = RemoveInternal(coords, childNode, level - 1, corner + childIndex * childSize); if (changed) { node.objCount += childNode.objCount - oldChildObjCount; if (childNode.isEmpty) { node.RemoveChild(childIndex); } } return(changed); }
// Returns whether the node is changed. private bool SetInternal(IntVector3 coords, T obj, OctreeNode <T> node, int level, IntVector3 corner) { if (node.obj.Equals(obj)) { return(false); } else if (level == 0) { node.obj = obj; return(true); } else if (node.isFilled) { node.Split(); } int childSize = 1 << (level - 1); IntVector3 childIndex = (coords - corner) / childSize; var childNode = node.GetChild(childIndex); if (childNode == null) { childNode = node.CreateChild(childIndex); } long oldChildObjCount = childNode.objCount; bool changed = SetInternal(coords, obj, childNode, level - 1, corner + childIndex * childSize); if (changed) { node.objCount += childNode.objCount - oldChildObjCount; if (childNode.isFilled) { node.MergeIfPossible(obj); } } return(changed); }
private void AddInternal(Vector3 position, int level, IntVector3 coords, OctreeNode node, OctreeElement element) { if (node.NodeElementCount >= splitThreshold && level < maxLevel) { Vector3 center = GetCenter(level, coords); node.Split(center); } node.TotalElementCount++; if (!node.IsLeaf) { Vector3 center = GetCenter(level, coords); int childIndex = PositionToChildIndex(position, center); OctreeNode child = node.GetOrCreateChild(childIndex); AddInternal(position, level + 1, coords * 2 + ChildIndexToCoords(childIndex), child, element); return; } element.position = position; element.level = level; element.coords = coords; node.Put(element); //Debug.Log(element.ToString() + " is added at " + Time.time); }
void Test2(OctreeNode<Voxel> node, Func<OctreeNode<Voxel>, bool> func) { if (node.Level > maxLevel) return; if (func(node)) { if (node.Level == maxLevel) { node.Fill(); } else { if (node.Children == null) { node.Split(); } Parallel.ForEach(node.Children, child => Test2(child, func)); } } //else //{ // var result = triangles.Where(t => func(node)).ToList(); // if (result.Any()) // { // if (node.Children == null) // { // node.Split(); // } // Parallel.ForEach(node.Children, child => Test2(child, result, func)); // } //} }
void Test(OctreeNode<Voxel> node, IEnumerable<Triangle> triangles) { if (node.Level > maxLevel) return; var result = triangles.Where(t => t.Intersects(node.AABB)).ToList(); if (result.Any()) { if (node.Level == maxLevel) { node.Fill(); } else { if (node.Children == null) { node.Split(); } Parallel.ForEach(node.Children, child => Test(child, result)); } } }
void Intersect(OctreeNode<Voxel> node, Triangle tri) { if(node.Level > maxLevel) return; if (tri.Intersects(node.AABB)) { if (node.Level == maxLevel) { node.Fill(); } else { if (node.Children == null) { node.Split(); } foreach (var child in node.Children) { Intersect(child,tri); } } } }