unsafe void CollapseTree(int depthRemaining, TempNode *tempNodes, int tempNodeIndex, int *nodeChildren, ref int childCount, BoundingBox *nodeBounds, int *leafCounts) { var tempNode = tempNodes + tempNodeIndex; if (tempNode->A >= 0) { //Internal node. if (depthRemaining > 0) { depthRemaining -= 1; CollapseTree(depthRemaining, tempNodes, tempNode->A, nodeChildren, ref childCount, nodeBounds, leafCounts); CollapseTree(depthRemaining, tempNodes, tempNode->B, nodeChildren, ref childCount, nodeBounds, leafCounts); } else { //Reached the bottom of the recursion. Add the collected children. int a = childCount++; int b = childCount++; nodeBounds[a] = tempNodes[tempNode->A].BoundingBox; nodeBounds[b] = tempNodes[tempNode->B].BoundingBox; //If the child is a leaf, collapse it. Slightly less annoying to handle it here than later. //This is a byproduct of the awkward data layout for tempnodes... if (tempNodes[tempNode->A].A >= 0) { nodeChildren[a] = tempNode->A; } else { nodeChildren[a] = tempNodes[tempNode->A].A; //It's a leaf. } if (tempNodes[tempNode->B].A >= 0) { nodeChildren[b] = tempNode->B; } else { nodeChildren[b] = tempNodes[tempNode->B].A; //It's a leaf. Leaf index is always stored in A... } leafCounts[a] = tempNodes[tempNode->A].LeafCount; leafCounts[b] = tempNodes[tempNode->B].LeafCount; } } else { //Leaf node. var index = childCount++; nodeBounds[index] = tempNode->BoundingBox; nodeChildren[index] = tempNode->A; leafCounts[index] = tempNode->LeafCount; } }
unsafe int BuildStagingChild(int parent, int indexInParent, TempNode *tempNodes, int tempNodeIndex, int collapseCount, Node *stagingNodes, ref int stagingNodeCount, out float treeletCost) { //Get ready to build a staging node out of this. var internalNodeIndex = stagingNodeCount++; var internalNode = stagingNodes + internalNodeIndex; internalNode->Parent = parent; internalNode->IndexInParent = indexInParent; internalNode->ChildCount = 0; var internalNodeChildren = &internalNode->ChildA; var internalNodeBounds = &internalNode->A; CollapseTree(collapseCount, tempNodes, tempNodeIndex, internalNodeChildren, ref internalNode->ChildCount, internalNodeBounds, &internalNode->LeafCountA); treeletCost = 0; //ValidateLeafNodeIndices(); //The node now contains valid bounding boxes, but the children indices are not yet valid. They're pointing into the tempnodes. //Reify each one in sequence. for (int i = 0; i < internalNode->ChildCount; ++i) { treeletCost += ComputeBoundsMetric(ref internalNodeBounds[i]); //The internalNodeChildren[i] can be negative, as a result of a subtree being encountered in CollapseTree. //tempNodes[internalNodeChildren[i]].A is never negative for any internal node (internalNodeChildren[i] >= 0), //because we pre-collapsed that reference in CollapseTree for convenience. if (internalNodeChildren[i] >= 0) { //It's still an internal node. float childTreeletCost; var childIndex = BuildStagingChild(internalNodeIndex, i, tempNodes, internalNodeChildren[i], collapseCount, stagingNodes, ref stagingNodeCount, out childTreeletCost); treeletCost += childTreeletCost; internalNodeChildren[i] = childIndex; } //If it's a subtree, then we don't need to change it at all. } return(internalNodeIndex); }
public static int Add(ref TempNode newNode, TempNode *tempNodes, ref int count) { tempNodes[count] = newNode; return(count++); }