public MeshNode ConstructMeshTree() { // Create the grid CreateGrid(); // Do the hierarchical clustering on the grid Dictionary <Vector3, MeshNode> slotClusterAssign = new Dictionary <Vector3, MeshNode>(); int maxClusterSize = 1; // Assign the slotClusterAssign foreach (Vector3 key in slots.Keys) { slotClusterAssign.Add(key, new MeshNode(slots[key].GetMesh(), key, slots[key].GetOffset())); } // Processing queue Queue <List <Vector3> > clusters = new Queue <List <Vector3> >(); // Add initial clusters to the queue System.Random rand = new System.Random(); List <Vector3> randomOrder = new List <Vector3>(slotClusterAssign.Keys); randomOrder.Sort((x, y) => rand.Next(100000)); foreach (Vector3 key in randomOrder) { List <Vector3> cluster = new List <Vector3>(); cluster.Add(key); clusters.Enqueue(cluster); } while (maxClusterSize != slots.Count && clusters.Count != 0) { // Get the processing position foreach (Vector3 procPos in clusters.Dequeue()) { // Get the node behind the key MeshNode procNode = slotClusterAssign[procPos]; // Get all the positions inside the cluster (this nodes cluster) HashSet <Vector3> selfClusterPositions = new HashSet <Vector3>(procNode.GetPositions()); // Find the neighboring cluster with the lowest size int minClusterSize = 1000; Vector3 minClusterKey = new Vector3(10000f, 10000f, 10000f); foreach (Vector3 n in basisvectors) { // Get a neighbor key Vector3 candidate = procPos + n;; // Check if the candidate exists if (!slots.ContainsKey(candidate)) { continue; } // Check if the candidate is in the same cluster as current node if (selfClusterPositions.Contains(candidate)) { continue; } // Check the size of the cluster MeshNode neigh = slotClusterAssign[candidate]; if (neigh.GetSize() < minClusterSize) { minClusterSize = neigh.GetSize(); minClusterKey = candidate; } } // No eligable neighbours if (minClusterSize == 1000) { continue; } // Now we know the cluster we want to pair with // Get the node of the cluster MeshNode clusterNode = slotClusterAssign[minClusterKey]; // Create a new cluster where the children are the current cluster and the neighbor cluster MeshNode newNode = new MeshNode(clusterNode.GetMesh(), procNode.GetMesh()); newNode.AddChild(clusterNode); newNode.AddChild(procNode); // Get all the positions in the new cluster List <Vector3> clusterPositions = newNode.GetPositions(); // Update the cluster assignment foreach (Vector3 position in clusterPositions) { slotClusterAssign[position] = newNode; } // Add the cluster positions to the processing queue clusters.Enqueue(clusterPositions); // Get the cluster size if (newNode.GetSize() > maxClusterSize) { maxClusterSize = newNode.GetSize(); // Early exit if task is already finished if (maxClusterSize == slots.Count) { break; } } } } // Return the topmost cluster return(slotClusterAssign[new Vector3(0f, 0f, 0f)]); }