_Use_decl_annotations_ int32_t BspCompiler::ProcessTriangles(Triangle** triangles, uint32_t count) { Triangle* front = nullptr; Triangle* back = nullptr; const Triangle* splitTriangle = nullptr; uint32_t frontCount, backCount; if (FindBestSplit(triangles, count, &splitTriangle, &front, &frontCount, &back, &backCount)) { // Able to split the set of triangles. We need a node to desribe this Node node; node.Plane = splitTriangle->Plane; node.Front = ProcessTriangles(&front, frontCount); node.Back = ProcessTriangles(&back, backCount); _nodes.push_back(node); return static_cast<int32_t>(_nodes.size() - 1); } else { // Not able to split, already convex. Make it a sector Sector sector; CreateSectorFromTriangles(triangles, count, §or); _sectors.push_back(sector); return static_cast<int32_t>(_sectors.size() - 1) * -1 - 1; } }
BVHAccelTreeNode *BVHAccel::BuildHierarchy(std::vector<BVHAccelTreeNode *> &list, unsigned int begin, unsigned int end, unsigned int axis) { unsigned int splitAxis = axis; float splitValue; nNodes += 1; if (end - begin == 1) // Only a single item in list so return it return list[begin]; BVHAccelTreeNode *parent = new BVHAccelTreeNode(); parent->primitive = 0xffffffffu; parent->leftChild = NULL; parent->rightSibling = NULL; std::vector<unsigned int> splits; splits.reserve(treeType + 1); splits.push_back(begin); splits.push_back(end); for (unsigned int i = 2; i <= treeType; i *= 2) { // Calculate splits, according to tree type and do partition for (unsigned int j = 0, offset = 0; j + offset < i && splits.size() > j + 1; j += 2) { if (splits[j + 1] - splits[j] < 2) { j--; offset++; continue; // Less than two elements: no need to split } FindBestSplit(list, splits[j], splits[j + 1], &splitValue, &splitAxis); std::vector<BVHAccelTreeNode *>::iterator it = partition(list.begin() + splits[j], list.begin() + splits[j + 1], bind2nd(ptr_fun(bvh_ltf[splitAxis]), splitValue)); unsigned int middle = distance(list.begin(), it); middle = Max(splits[j] + 1, Min(splits[j + 1] - 1, middle)); // Make sure coincidental BBs are still split splits.insert(splits.begin() + j + 1, middle); } } BVHAccelTreeNode *child, *lastChild; // Left Child child = BuildHierarchy(list, splits[0], splits[1], splitAxis); parent->leftChild = child; parent->bbox = child->bbox; lastChild = child; // Add remaining children for (unsigned int i = 1; i < splits.size() - 1; i++) { child = BuildHierarchy(list, splits[i], splits[i + 1], splitAxis); lastChild->rightSibling = child; parent->bbox = Union(parent->bbox, child->bbox); lastChild = child; } return parent; }
void RayIntersectorKDTreeNode::MakeInteriorNode(const Vector<UINT> &TriangleIndices, const RayIntersectorKDTree &Root, UINT Depth, Vector<UINT> &LeafTriangles) { UINT BestAxis; float SplitValue; if(FindBestSplit(TriangleIndices, Root, BestAxis, SplitValue)) { _Flags.Leaf = 0; //_Flags.Axis = BestAxis; Vector<UINT> LeftTriangleIndices, RightTriangleIndices; for(UINT TriangleIndex = 0; TriangleIndex < TriangleIndices.Length(); TriangleIndex++) { UINT LeftVertices = 0, RightVertices = 0; const UINT BaseIndexIndex = TriangleIndices[TriangleIndex] * 3; for(UINT VertexIndex = 0; VertexIndex < 3; VertexIndex++) { const Vec3f &CurVertex = Root._Vertices[Root._Indices[BaseIndexIndex + VertexIndex]]; if(CurVertex[BestAxis] < SplitValue) { LeftVertices++; } if(CurVertex[BestAxis] >= SplitValue) { RightVertices++; } } bool OnLeftSide = (LeftVertices > RightVertices); bool OnRightSide = !OnLeftSide; if(OnLeftSide) { LeftTriangleIndices.PushEnd(TriangleIndices[TriangleIndex]); } if(OnRightSide) { RightTriangleIndices.PushEnd(TriangleIndices[TriangleIndex]); } } //_Interior.SplitValue = SplitValue; _Interior.Left = new RayIntersectorKDTreeNode(LeftTriangleIndices, Root, Depth + 1, LeafTriangles); _Interior.Right = new RayIntersectorKDTreeNode(RightTriangleIndices, Root, Depth + 1, LeafTriangles); } else { MakeLeafNode(TriangleIndices, LeafTriangles); } }
_Use_decl_annotations_ void KdTreeCompiler2::Process(uint32_t nodeIndex, uint32_t trianglesRoot, uint32_t numTriangles, const float min[3], const float max[3]) { // Find the best split. If this function fails, it means we can't/shouldn't split further, // and should just make this node into a leaf. uint32_t splitAxis, frontRoot, backRoot, frontCount, backCount; float splitValue, frontMin[3], frontMax[3], backMin[3], backMax[3]; if (FindBestSplit(trianglesRoot, numTriangles, &splitAxis, &splitValue, min, max, &frontRoot, &frontCount, frontMin, frontMax, &backRoot, &backCount, backMin, backMax)) { uint32_t frontNode = AllocNode(); uint32_t backNode = AllocNode(); KdNode* node = &_nodes[nodeIndex]; node->Axis = splitAxis; node->Value = splitValue; node->Front = frontNode; memcpy_s(node->Min, sizeof(node->Min), min, sizeof(node->Min)); memcpy_s(node->Max, sizeof(node->Max), max, sizeof(node->Max)); Process(frontNode, frontRoot, frontCount, frontMin, frontMax); Process(backNode, backRoot, backCount, backMin, backMax); } else { KdNode* node = &_nodes[nodeIndex]; node->Axis = 3; node->NumTriangles = numTriangles; memcpy_s(node->Min, sizeof(node->Min), min, sizeof(node->Min)); memcpy_s(node->Max, sizeof(node->Max), max, sizeof(node->Max)); for (uint32_t i = 0; i < numTriangles; ++i) { uint32_t tri = AllocTriangle(_compilerTriangles[i]); if (i == 0) { node->FirstTriangle = tri; } } } }
// // Pick a splitter poly then split a pool of polygons into front and back polygons and // recurse. // // iParent = Parent Bsp node, or INDEX_NONE if this is the root node. // IsFront = 1 if this is the front node of iParent, 0 of back (undefined if iParent==INDEX_NONE) // void FBSPOps::SplitPolyList ( UModel *Model, int32 iParent, ENodePlace NodePlace, int32 NumPolys, FPoly **PolyList, EBspOptimization Opt, int32 Balance, int32 PortalBias, int32 RebuildSimplePolys ) { FMemMark Mark(FMemStack::Get()); // Keeping track of allocated FPoly structures to delete later on. TArray<FPoly*> AllocatedFPolys; // To account for big EdPolys split up. int32 NumPolysToAlloc = NumPolys + 8 + NumPolys/4; int32 NumFront=0; FPoly **FrontList = new(FMemStack::Get(),NumPolysToAlloc)FPoly*; int32 NumBack =0; FPoly **BackList = new(FMemStack::Get(),NumPolysToAlloc)FPoly*; FPoly *SplitPoly = FindBestSplit( NumPolys, PolyList, Opt, Balance, PortalBias ); // Add the splitter poly to the Bsp with either a new BspSurf or an existing one. if( RebuildSimplePolys ) { SplitPoly->iLink = Model->Surfs.Num(); } int32 iOurNode = bspAddNode(Model,iParent,NodePlace,0,SplitPoly); int32 iPlaneNode = iOurNode; // Now divide all polygons in the pool into (A) polygons that are // in front of Poly, and (B) polygons that are in back of Poly. // Coplanar polys are inserted immediately, before recursing. // If any polygons are split by Poly, we ignrore the original poly, // split it into two polys, and add two new polys to the pool. FPoly *FrontEdPoly = new FPoly; FPoly *BackEdPoly = new FPoly; // Keep track of allocations. AllocatedFPolys.Add( FrontEdPoly ); AllocatedFPolys.Add( BackEdPoly ); for( int32 i=0; i<NumPolys; i++ ) { FPoly *EdPoly = PolyList[i]; if( EdPoly == SplitPoly ) { continue; } switch( EdPoly->SplitWithPlane( SplitPoly->Vertices[0], SplitPoly->Normal, FrontEdPoly, BackEdPoly, 0 ) ) { case SP_Coplanar: if( RebuildSimplePolys ) { EdPoly->iLink = Model->Surfs.Num()-1; } iPlaneNode = bspAddNode( Model, iPlaneNode, NODE_Plane, 0, EdPoly ); break; case SP_Front: FrontList[NumFront++] = PolyList[i]; break; case SP_Back: BackList[NumBack++] = PolyList[i]; break; case SP_Split: // Create front & back nodes. FrontList[NumFront++] = FrontEdPoly; BackList [NumBack ++] = BackEdPoly; FrontEdPoly = new FPoly; BackEdPoly = new FPoly; // Keep track of allocations. AllocatedFPolys.Add( FrontEdPoly ); AllocatedFPolys.Add( BackEdPoly ); break; } } // Recursively split the front and back pools. if( NumFront > 0 ) SplitPolyList( Model, iOurNode, NODE_Front, NumFront, FrontList, Opt, Balance, PortalBias, RebuildSimplePolys ); if( NumBack > 0 ) SplitPolyList( Model, iOurNode, NODE_Back, NumBack, BackList, Opt, Balance, PortalBias, RebuildSimplePolys ); // Delete FPolys allocated above. We cannot use FMemStack::Get() for FPoly as the array data FPoly contains will be allocated in regular memory. for( int32 i=0; i<AllocatedFPolys.Num(); i++ ) { FPoly* AllocatedFPoly = AllocatedFPolys[i]; delete AllocatedFPoly; } Mark.Pop(); }