//Method that creates the 8 children of this node. After creating them, it empties its own List of items- private bool split() { float half = halfSpaceLength / 2f; if (half >= minimumSize) { for (int y = 0; y < 2; y++) { for (int z = 0; z < 2; z++) { for (int x = 0; x < 2; x++) { Vector3 childCenter = new Vector3(centerSpace.x + half * Mathf.Pow(-1f, x), centerSpace.y + half * Mathf.Pow(-1f, y), centerSpace.z + half * Mathf.Pow(-1f, z)); _children [4 * y + 2 * z + x] = new octreeNode(this, new List <octreeItem>(nodeElements), half, childCenter, "node"); } } } return(true); } else { return(false); } }
//Constructor- public octreeNode(octreeNode parent, List <octreeItem> potentialItems, float halfLength, Vector3 centerPos, string name) { this.parent = parent; this.centerSpace = centerPos; this.halfSpaceLength = halfLength; this.name = name + "(" + id++ + ")"; //Only for debugging- for (int i = 0; i < potentialItems.Count; i++) { processItem(potentialItems[i]); } //Graphic representation of the space- drawNodeSpace(); }
//Alternative to push method proposed below: private void pushItem(octreeItem item) { //If the item belongs to this node's elements, then it will not be evaluated: if (!nodeElements.Contains(item)) { //If the item has an owner (meaning he is being modified, not created): if (item.ownerNodes.Count > 0) { //If the item's owner is different from this node (caused by items moved or node split) if (!ReferenceEquals(this, item.ownerNodes [0])) { //You get the previous owner reference: octreeNode prevOwner = item.ownerNodes [0]; prevOwner.nodeElements.Remove(item); item.ownerNodes [0] = this; this.nodeElements.Add(item); //If the previous owner was not root, then you have to check wether his parent should merge his children back together: //If the previous owner is the parent of this node, it does not enter here since it means it just split: //Later, a bool could be used to know when we want to dinamically update the tree: while (prevOwner.parent != null && !ReferenceEquals(this.parent, prevOwner)) //if (prevOwner.parent != null && !ReferenceEquals(this.parent, prevOwner))**## { //We get the parent node of the previous owner, which might get terminated: octreeNode prevOwnerParent = prevOwner.parent; List <octreeItem> tempElementsList = new List <octreeItem> (); int totalCount = 0; for (int i = 0; i < 8; i++) { octreeNode child = prevOwnerParent.children [i]; totalCount += child.nodeElements.Count; tempElementsList.AddRange(child.nodeElements); } //Here, the prevOwnerParent destroy his children: if (totalCount <= maxNumberOfElements) { for (int i = 0; i < 8; i++) { GameObject.Destroy(prevOwnerParent.children [i].obj); prevOwnerParent.children [i] = null; } //Every item which pointed to these destroyed child nodes must now point to their parent (new owner): for (int i = 0; i < tempElementsList.Count; i++) { tempElementsList [i].ownerNodes [0] = prevOwnerParent; prevOwnerParent.nodeElements.Add(tempElementsList[i]); } } //Now, we should set up the params for the next iteration: prevOwner = prevOwnerParent; //Only when using the while()-**## } } } //If the item doesn't have an owner, he must be entering the octree for the first time: else { item.ownerNodes.Add(this); this.nodeElements.Add(item); } } //If after adding the element the node is overloaded, it has to split and then empty his list: if (nodeElements.Count > maxNumberOfElements) { if (split()) { nodeElements.Clear(); } } }