/// <summary> /// Merge all children into this node - the opposite of Split. /// Note: We only have to check one level down since a merge will never happen if the children already have children, /// since THAT won't happen unless there are already too many objects to merge. /// </summary> void Merge() { // Note: We know children != null or we wouldn't be merging for (int i = 0; i < 8; i++) { PointOctreeNode <T> curChild = children[i]; int numObjects = curChild.objects.Count; for (int j = numObjects - 1; j >= 0; j--) { OctreeObject curObj = curChild.objects[j]; objects.Add(curObj); } } // Remove the child nodes (and the objects in them - they've been added elsewhere now) children = null; }
/* * /// <summary> * /// Get the total amount of objects in this node and all its children, grandchildren etc. Useful for debugging. * /// </summary> * /// <param name="startingNum">Used by recursive calls to add to the previous total.</param> * /// <returns>Total objects in this node and its children, grandchildren etc.</returns> * public int GetTotalObjects(int startingNum = 0) { * int totalObjects = startingNum + objects.Count; * if (children != null) { * for (int i = 0; i < 8; i++) { * totalObjects += children[i].GetTotalObjects(); * } * } * return totalObjects; * } */ public PointOctreeNode <T> ClearNode(PointOctreeNode <T> node) { if (node != null) { if (ReferenceEquals(node.children, null)) { node.objects.Clear(); return(null); } foreach (var item in node.children) { ClearNode(item); } node.objects.Clear(); node = null; return(node); } return(null); }
private void CheckFunc(PointOctreeNode <Integer> .OctreeObject octreeObject) { var objectPosition = DataSet[octreeObject.Obj].Position; var distanceCurrent = Vector3.Distance(cachePosition, objectPosition); if (distanceCurrent > NearRadius && distanceCurrent < FarRadius && !Loaded.Contains(octreeObject.Obj)) { Loaded.Add(octreeObject.Obj); lock (LoadQueue) { LoadQueue.Enqueue(octreeObject.Obj); } } else if ((distanceCurrent < NearRadius || distanceCurrent > FarRadius) && Loaded.Contains(octreeObject.Obj)) { Loaded.Remove(octreeObject.Obj); lock (UnloadQueue) { UnloadQueue.Enqueue(octreeObject.Obj); } } }
// #### PRIVATE METHODS #### /// <summary> /// Grow the octree to fit in all objects. /// </summary> /// <param name="direction">Direction to grow.</param> void Grow(Vector3 direction) { int xDirection = direction.x >= 0 ? 1 : -1; int yDirection = direction.y >= 0 ? 1 : -1; int zDirection = direction.z >= 0 ? 1 : -1; PointOctreeNode <T> oldRoot = rootNode; float half = rootNode.SideLength / 2; float newLength = rootNode.SideLength * 2; Vector3 newCenter = rootNode.Center + new Vector3(xDirection * half, yDirection * half, zDirection * half); // Create a new, bigger octree root node rootNode = new PointOctreeNode <T>(newLength, minSize, newCenter); if (oldRoot.HasAnyObjects()) { // Create 7 new octree children to go with the old root as children of the new root int rootPos = rootNode.BestFitChild(oldRoot.Center); PointOctreeNode <T>[] children = new PointOctreeNode <T> [8]; for (int i = 0; i < 8; i++) { if (i == rootPos) { children[i] = oldRoot; } else { xDirection = i % 2 == 0 ? -1 : 1; yDirection = i > 3 ? -1 : 1; zDirection = (i < 2 || (i > 3 && i < 6)) ? -1 : 1; children[i] = new PointOctreeNode <T>(oldRoot.SideLength, minSize, newCenter + new Vector3(xDirection * half, yDirection * half, zDirection * half)); } } // Attach the new children to the new root node rootNode.SetChildren(children); } }
/// <summary> /// Shrink the octree if possible, else leave it the same. /// </summary> void Shrink() { rootNode = rootNode.ShrinkIfPossible(initialSize); }
public Tuple <Vector3, int, float> CalculateVecAndTemp(PointOctreeNode <CelestialBody> node, int depth) { if (depth > this.depth) { this.depth = depth; } if (!node.HasChildren) { List <Vector3> average = new List <Vector3>(); List <int> averageTempList = new List <int>(); //for (int i = node.start; i < node.end; i++) //{ // average.Add(points[permutation[i]]); // averageTempList.Add(reader.celestialBodyCloud[permutation[i]].temperature); //} foreach (PointOctreeNode <CelestialBody> .OctreeObject celBody in node.objects) { //Debug.Log("Temp: " + ((CelestialBody)celBody.Obj).temperature); average.Add(celBody.Obj.position); averageTempList.Add(celBody.Obj.temperature); } if (average.Count > 0 && averageTempList.Count > 0) { node.averagePositionOfNodes = new Vector3( average.Average(x => x.x), average.Average(x => x.y), average.Average(x => x.z)); node.averageTempOfNodes = (int)averageTempList.Average(); } float maxDistance = 0; foreach (PointOctreeNode <CelestialBody> .OctreeObject celBody in node.objects) { float mag = (node.averagePositionOfNodes - celBody.Obj.position).sqrMagnitude; if (mag > maxDistance) { maxDistance = mag; } } node.distanceFromAverage = maxDistance; node.nodeDepth = depth; node.distanceFromAverage = node.SideLength; //return new Tuple<Vector3, int, float>(node.averagePositionOfNodes, node.averageTempOfNodes, node.distanceFromAverage); return(new Tuple <Vector3, int, float>(node.averagePositionOfNodes, node.averageTempOfNodes, node.distanceFromAverage)); } else { List <Tuple <Vector3, int, float> > listOfResults = new List <Tuple <Vector3, int, float> >(); listOfResults.Add(CalculateVecAndTemp(node.children[0], depth + 1)); listOfResults.Add(CalculateVecAndTemp(node.children[1], depth + 1)); listOfResults.Add(CalculateVecAndTemp(node.children[2], depth + 1)); listOfResults.Add(CalculateVecAndTemp(node.children[3], depth + 1)); listOfResults.Add(CalculateVecAndTemp(node.children[4], depth + 1)); listOfResults.Add(CalculateVecAndTemp(node.children[5], depth + 1)); listOfResults.Add(CalculateVecAndTemp(node.children[6], depth + 1)); listOfResults.Add(CalculateVecAndTemp(node.children[7], depth + 1)); node.nodeDepth = depth; foreach (Tuple <Vector3, int, float> result in listOfResults) { node.averagePositionOfNodes += result.Item1; node.averageTempOfNodes += result.Item2; } node.averagePositionOfNodes /= 8f; node.averageTempOfNodes /= 8; float maxDistance = 0; float resultDistance = 0; foreach (Tuple <Vector3, int, float> result in listOfResults) { float mag = (node.averagePositionOfNodes - result.Item1).sqrMagnitude; if (mag > maxDistance) { maxDistance = mag; resultDistance = result.Item3; } } node.distanceFromAverage = maxDistance + resultDistance; node.distanceFromAverage = node.SideLength; return(new Tuple <Vector3, int, float>(node.averagePositionOfNodes, node.averageTempOfNodes, node.distanceFromAverage)); } }
public IEnumerator SplitOctreeLODWithPixelSize() { placement_manager.coroutineRunning = true; for (; ;) { int count = 0; Queue <PointOctreeNode <CelestialBody> > nodeQueue = new Queue <PointOctreeNode <CelestialBody> >(); nodeList = new List <PointOctreeNode <CelestialBody> >(); PointOctreeNode <CelestialBody> tempNode = octree.rootNode; nodeQueue.Enqueue(tempNode); while (nodeQueue.Count > 0) { tempNode = nodeQueue.Dequeue(); count++; if (count > 2000) { count = 0; yield return(null); } //Debug.Log(tempNode); if (tempNode != null && !tempNode.HasChildren) { nodeList.Add(tempNode); continue; } else if (tempNode != null && tempNode.HasChildren) { //nodeList.Add(tempNode); Vector3 centerPos = placement_manager.visualCube.transform.position + tempNode.averagePositionOfNodes; Vector3 edgePos = centerPos + (Vector3.Cross(Camera.main.transform.up, centerPos - Camera.main.transform.position).normalized *(tempNode.distanceFromAverage / 2) * placement_manager.visualCube.transform.localScale.x); //screenCenterPos = Camera.main.WorldToScreenPoint(centerPos); float distanceInPixel = Vector3.Magnitude(Camera.main.WorldToScreenPoint(centerPos) - Camera.main.WorldToScreenPoint(edgePos)); if (distanceInPixel > 2) { foreach (PointOctreeNode <CelestialBody> childNode in tempNode.children) { nodeQueue.Enqueue(childNode); } } else { nodeList.Add(tempNode); continue; } } } CalculateAverageLists(nodeList); ui_manager.SetLegendCount(averageSpectralM.Count, averageSpectralK.Count, averageSpectralG.Count, averageSpectralF.Count, averageSpectralA.Count); yield return(new WaitForSeconds(1f)); Debug.Log(count); //count = 0; //// yield return null; } }