void BuildTreeRecursive(bsptree_t *tree, bspnode_t *node, bspline_t *lines) { plane_t plane; bspline_t *sides[2]; if (!lines) { node->leafnext = tree->leafs; tree->leafs = node; tree->numleafs++; return; } plane = SelectSplitPlane(lines); PartitionLineList(plane, lines, sides); node->plane = plane; // add two new nodes to the tree node->children[0] = MallocBSPNode(tree, node); node->children[1] = MallocBSPNode(tree, node); // recurse down the front and back sides BuildTreeRecursive(tree, node->children[0], sides[0]); BuildTreeRecursive(tree, node->children[1], sides[1]); }
bsptree_t *BuildTree() { bspline_t *lines = MakeLineList(); bsptree_t *tree = MakeEmptyTree(); BuildTreeRecursive(tree, tree->root, lines); return tree; }
void JRTHeuristicKDTreeBuilder::BuildTreeImpl(const JRTBoundingBox& rBounds, const std::vector<const JRTTriangle*>& rTris, std::vector<JRTKDNode>& rNodesOut, std::vector<UINT>& rTrisOut) { rNodesOut.push_back(JRTKDNode()); // create root node // extract triangle BBs BuildBBs(rTris, m_bbs); // extract split planes std::vector<Split> splits[3]; for (int i = 0; i < 3; i++) { ExtractSplits(i, m_bbs, splits[i], rBounds); } // build vectors of pointers to these split planes for shuffling around SplitVec splitPtrs[3]; for (int i = 0; i < 3; i++) { splitPtrs[i].resize(splits[i].size()); for (int j = 0; j < (int)splits[i].size(); j++) { splitPtrs[i][j] = &splits[i][j]; } } // build vectors of pointers to BBs, also for shuffling around std::vector<TriangleBB*> bbPtrs; for (int i = 0; i < (int)m_bbs.size(); i++) { bbPtrs.push_back(&m_bbs[i]); } BuildTreeRecursive(JRTKDTree::MAX_TREE_DEPTH, rBounds, splitPtrs, bbPtrs, &rNodesOut[0], rNodesOut, rTrisOut); }
void JRTHeuristicKDTreeBuilder::BuildTreeRecursive(UINT nDepthLimit, const JRTBoundingBox& rNodeBounds, SplitVec splits[3], std::vector<TriangleBB*>& rBBsThisNode, JRTKDNode* pNode, std::vector<JRTKDNode>& rNodesOut, std::vector<UINT>& rTrisOut) { UINT nTriCount = (UINT)rBBsThisNode.size(); JRT_ASSERT(splits[0].size() == splits[1].size() && splits[1].size() == splits[2].size()); // initialize best cost to cost of not splitting float fBestCost = INTERSECT_COST * nTriCount; // find the optimal split bool bSplit = false; float fSplitValue; UINT eSplitAxis = X_AXIS; float fNodeBBInvArea = 1.0f / Max(0.0000001f, rNodeBounds.GetSurfaceArea()); float fNodeVolume = rNodeBounds.GetVolume(); for (UINT axis = X_AXIS; axis <= Z_AXIS; axis++) { LocateBestSplit(fNodeBBInvArea, rNodeBounds, splits, axis, nTriCount, fBestCost, bSplit, eSplitAxis, fSplitValue); } if (!bSplit || nDepthLimit == 0) { // we either don't want to split, or can't split, so make a leaf pNode->leaf.is_leaf = true; pNode->leaf.triangle_count = 0; pNode->leaf.triangle_start = (UINT)rTrisOut.size(); for (UINT i = 0; i < rBBsThisNode.size(); i++) { // do robust tri-box clipping at the leaves const Vec3f* pV1 = &rBBsThisNode[i]->pTri->GetV1(); const Vec3f* pV2 = &rBBsThisNode[i]->pTri->GetV2(); const Vec3f* pV3 = &rBBsThisNode[i]->pTri->GetV3(); if (rNodeBounds.TriangleIntersect(pV1, pV2, pV3)) { rTrisOut.push_back(rBBsThisNode[i]->nIndex); pNode->leaf.triangle_count++; } } } else { // make a non-leaf pNode->inner.axis = eSplitAxis; pNode->inner.is_leaf = false; pNode->inner.position = fSplitValue; JRT_ASSERT(fSplitValue > rNodeBounds.GetMin()[eSplitAxis] && fSplitValue < rNodeBounds.GetMax()[eSplitAxis]); ClassifyBBs(splits[0], m_bbs, eSplitAxis, fSplitValue); // partition the splits SplitVec frontSplits[3]; SplitVec backSplits[3]; for (int j = X_AXIS; j <= Z_AXIS; j++) { PartitionSplits(fSplitValue, eSplitAxis, splits[j], m_bbs, backSplits[j], frontSplits[j]); // clear old split vec to save memory splits[j].clear(); } // partition BBs std::vector<TriangleBB*> backBBs; std::vector<TriangleBB*> frontBBs; PartitionBBs(eSplitAxis, fSplitValue, rBBsThisNode, backBBs, frontBBs); rBBsThisNode.clear(); // save memory // create new nodes // by convention, always create front child right before back child pNode->inner.front_offset = (UINT)rNodesOut.size(); UINT nFront = (UINT)rNodesOut.size(); UINT nBack = nFront + 1; rNodesOut.push_back(JRTKDNode()); rNodesOut.push_back(JRTKDNode()); // split the node bounding box JRTBoundingBox front_bounds, back_bounds; rNodeBounds.Split(eSplitAxis, fSplitValue, front_bounds, back_bounds); // recursively build the subtrees BuildTreeRecursive(nDepthLimit - 1, front_bounds, frontSplits, frontBBs, &rNodesOut[ nFront ], rNodesOut, rTrisOut); BuildTreeRecursive(nDepthLimit - 1, back_bounds, backSplits, backBBs, &rNodesOut[ nBack ], rNodesOut, rTrisOut); } }