std::unique_ptr<BSPNode> BSPUnion(std::unique_ptr<BSPNode> a, std::unique_ptr<BSPNode> b) { if(!a || b->isleaf == UNDER || a->isleaf==OVER) { if(a && b->isleaf==UNDER) { FaceCutting(a.get(), b->brep); } return b; } if(a->isleaf == UNDER || b->isleaf==OVER) { 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 assert(!a->isleaf); BSPPartition(move(a), float4(b->xyz(), b->w), aunder, aover); assert(aunder || aover); b->under = BSPUnion(move(aunder), move(b->under)); b->over = BSPUnion(move(aover), move(b->over)); /* 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; }
BSPNode *BSPUnion(BSPNode *a,BSPNode *b) { if(!a || b->isleaf == UNDER || a->isleaf==OVER) { if(a && b->isleaf==UNDER) { FaceCutting(a,b->brep); } return b; } if(a->isleaf == UNDER || b->isleaf==OVER) { return a; } BSPNode *aover; BSPNode *aunder; // its like "b" is the master, so a should be the little object and b is the area's shell assert(!a->isleaf); BSPPartition(a, float4(b->xyz(), b->w), aunder, aover); assert(aunder || aover); b->under = BSPUnion(aunder,b->under); b->over = BSPUnion(aover ,b->over ); /* 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 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; }