Пример #1
0
//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()));
}
Пример #2
0
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));
}
Пример #3
0
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);
	}
*/
}
Пример #4
0
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;
}
Пример #5
0
void NegateTree(BSPNode & root) 
{
	NegateTreePlanes(&root);  // this flips the faces too
	for (auto & f : BSPRipBrep(&root))
		FaceEmbed(&root, std::move(f)); 
}