//std::vector<Face> deadfaces; void FaceEmbed(BSPNode *node, Face && face) { assert(node); if(node->isleaf==OVER) { //deadfaces.push_back(std::move(face)); return; } if(node->isleaf==UNDER) { node->brep.push_back(std::move(face)); return; } int flag = FaceSplitTest(face, node->plane()); if(flag==UNDER) { FaceEmbed(node->under.get(),std::move(face)); return; } if(flag==OVER) { FaceEmbed(node->over.get(),std::move(face)); return; } if(flag==COPLANAR) { FaceEmbed(dot(node->xyz(), face.xyz()) > 0 ? node->under.get() : node->over.get(), std::move(face)); return; } assert(flag==SPLIT); // FIXME: add FaceSliceEdge calls here! FaceEmbed(node->over.get(), FaceClip(face, -node->plane())); FaceEmbed(node->under.get(), FaceClip(std::move(face), node->plane())); }
static void GenerateFaces(BSPNode *root) { assert(root); for (auto n : treetraverse(root)) if(n->isleaf==OVER) for (auto &f : GenerateFacesReverse(n->convex)) FaceEmbed(root, std::move(f)); }
void BSPPartition(std::unique_ptr<BSPNode> n, const float4 &p, std::unique_ptr<BSPNode> & nodeunder, std::unique_ptr<BSPNode> & nodeover) { nodeunder=NULL; nodeover =NULL; if(!n) { return; } // assert(n->cell); int flag; //flag = SplitTest(n->cell,p); //assert(flag==SplitTest(*n->convex,p)); flag = n->convex.SplitTest(p); if(flag == UNDER) { nodeunder = move(n); return; } if(flag==OVER) { nodeover = move(n); return; } assert(flag==SPLIT); // Polyhedron *cellover = PolyhedronDup(n->cell); // Polyhedron *cellunder = PolyhedronDup(n->cell); // cellunder->Crop(p); // cellover->Crop(Plane(-p.normal,-p.dist)); nodeunder.reset(new BSPNode(n->xyz(), n->w)); nodeover.reset(new BSPNode(n->xyz(),n->w)); nodeunder->isleaf = n->isleaf; nodeover->isleaf = n->isleaf; // nodeunder->cell= cellunder; // nodeover->cell = cellover; nodeunder->convex = WingMeshCrop(n->convex,p); nodeover->convex = WingMeshCrop(n->convex, float4(-p.xyz(), -p.w)); if(n->isleaf==UNDER) { int i; BSPNode fake(p.xyz(), p.w); fake.under=move(nodeunder); fake.over=move(nodeover); i=n->brep.size(); while(i--){ FaceEmbed(&fake, std::move(n->brep[i])); } n->brep.clear(); nodeunder = move(fake.under); nodeover = move(fake.over); } BSPPartition(move(n->under), p, nodeunder->under, nodeover->under); BSPPartition(move(n->over), p, nodeunder->over, nodeover->over ); if(n->isleaf) { assert(nodeunder->isleaf); assert(nodeover->isleaf); return; } assert(nodeunder->over || nodeunder->under); assert(nodeover->over || nodeover->under); n.reset(); if(!nodeunder->under) { // assert(SplitTest(nodeunder->cell,*nodeunder)==OVER); nodeunder = move(nodeunder->over); } else if(!nodeunder->over) { // assert(SplitTest(nodeunder->cell,*nodeunder)==UNDER); nodeunder = move(nodeunder->under); } assert(nodeunder); assert(nodeunder->isleaf || (nodeunder->under && nodeunder->over)); if(!nodeover->under) { // assert(SplitTest(nodeover->cell,*nodeover)==OVER); nodeover = move(nodeover->over); } else if(!nodeover->over) { // assert(SplitTest(nodeover->cell,*nodeover)==UNDER); nodeover = move(nodeover->under); } assert(nodeover); assert(nodeover->isleaf || (nodeover->under && nodeover->over)); if(!nodeunder->isleaf && nodeunder->over->isleaf && nodeunder->over->isleaf==nodeunder->under->isleaf) { nodeunder->isleaf = nodeunder->over->isleaf; // pick one of the children int i; i=nodeunder->under->brep.size(); while(i--){ nodeunder->brep.push_back(nodeunder->under->brep[i]); } nodeunder->under->brep.clear(); i=nodeunder->over->brep.size(); while(i--){ nodeunder->brep.push_back(nodeunder->over->brep[i]); } nodeunder->over->brep.clear(); nodeunder->under.reset(); nodeunder->over.reset(); } // wtf: if(!nodeover->isleaf && nodeover->over->isleaf==nodeover->under->isleaf) { if(!nodeover->isleaf && nodeover->over->isleaf && nodeover->over->isleaf==nodeover->under->isleaf) { nodeover->isleaf = nodeover->over->isleaf; // pick one of the children int i; i=nodeover->under->brep.size(); while(i--){ nodeover->brep.push_back(nodeover->under->brep[i]); } nodeover->under->brep.clear(); i=nodeover->over->brep.size(); while(i--){ nodeover->brep.push_back(nodeover->over->brep[i]); } nodeover->over->brep.clear(); nodeover->under.reset(); nodeover->over.reset(); } /* if(fusenodes) { if(0==nodeunder->isleaf) { if(nodeunder->over->isleaf==UNDER) { DeriveCells(nodeunder->under,nodeunder->cell); nodeunder = nodeunder->under; // memleak } else if(nodeunder->under->isleaf==OVER) { DeriveCells(nodeunder->over,nodeunder->cell); nodeunder = nodeunder->over; // memleak } } assert(nodeunder); if(0==nodeover->isleaf) { if(nodeover->over->isleaf==UNDER) { DeriveCells(nodeover->under,nodeover->cell); nodeover = nodeover->under; // memleak } else if(nodeover->under->isleaf==OVER) { DeriveCells(nodeover->over,nodeover->cell); nodeover = nodeover->over; // memleak } } assert(nodeover); } */ }
std::unique_ptr<BSPNode> BSPIntersect(std::unique_ptr<BSPNode> a, std::unique_ptr<BSPNode> b) { int swapflag; if(!a||a->isleaf == UNDER || b->isleaf==OVER) { if(a&&a->isleaf==UNDER ) { while (a->brep.size()) { FaceEmbed(b.get(), Pop(a->brep)); } } return b; } assert(b); if(b->isleaf == UNDER || a->isleaf==OVER) { if(b->isleaf==UNDER ) { while (b->brep.size()) { FaceEmbed(a.get(), Pop(b->brep)); } } return a; } // I'm not sure about the following bit - it only works if booleaning bsp's cells cover entire area volume too if(bspmergeallowswap)if( SPLIT != (swapflag = b->convex.SplitTest( *a))) { if(swapflag == OVER) { a->over = BSPIntersect(move(a->over), move(b)); return a; } if(swapflag == UNDER) { a->under= BSPIntersect(move(a->under), move(b)); return a; } } std::unique_ptr<BSPNode> aover; std::unique_ptr<BSPNode> aunder; // its like "b" is the master, so a should be the little object and b is the area's shell BSPPartition(move(a), float4(b->xyz(), b->w), aunder, aover); b->under = BSPIntersect(move(aunder), move(b->under)); b->over = BSPIntersect(move(aover), move(b->over)); if(b->over->isleaf && b->over->isleaf==b->under->isleaf) { // both children are leaves of same type so merge them into parent while (b->over->brep.size()) { b->brep.push_back(Pop(b->over->brep)); } assert(b->over->brep.size()==0); while (b->under->brep.size()) { b->brep.push_back(Pop(b->under->brep)); } b->isleaf = b->over->isleaf; b->over.reset(); b->under.reset(); } /* if(fusenodes) { if(b->over->isleaf == UNDER) { DeriveCells(b->under,b->cell); return b->under; } if(b->under->isleaf == OVER) { DeriveCells(b->over,b->cell); return b->over; } } */ return b; }
void NegateTree(BSPNode & root) { NegateTreePlanes(&root); // this flips the faces too for (auto & f : BSPRipBrep(&root)) FaceEmbed(&root, std::move(f)); }