Example #1
0
void BSPDeriveConvex(BSPNode & node, WingMesh cnvx) 
{
	if (cnvx.edges.size() && cnvx.verts.size())
	{
		assert(cnvx.verts.size());
		assert(cnvx.edges.size());
		assert(cnvx.faces.size());
	}
	node.convex = std::move(cnvx);
	if(node.isleaf) return;

	// if we are "editing" a bsp then the current plane may become coplanar to one of its parents (boundary of convex) or outside of the current volume (outside the convex)
	WingMesh cu;
	WingMesh co;
	if(node.convex.verts.size())  // non empty
	{
		int f = node.convex.SplitTest(node.plane());
		if(f==SPLIT)
		{
			cu = WingMeshCrop(node.convex, node.plane());
			co = WingMeshCrop(node.convex, -node.plane());
		}
		else if(f==OVER)
		{
			co = node.convex;
		}
		else if(f==UNDER)
		{
			cu = node.convex;
		}
		else
		{
			assert(0); // hunh? the 3d convex has 0 volume
		}
	}

	// Under SubTree
	assert(node.under);
	BSPDeriveConvex(*node.under,cu); 
	// Over  SubTree
	assert(node.over);
	BSPDeriveConvex(*node.over ,co);
}
Example #2
0
float PlaneCost(const std::vector<Face> &inputfaces,const float4 &split,const WingMesh &space,int onbrep)
{
	count[COPLANAR] = 0;
	count[UNDER]    = 0;
	count[OVER]     = 0;
	count[SPLIT]    = 0;
	for(unsigned int i=0;i<inputfaces.size();i++) {
		count[FaceSplitTest(inputfaces[i],split,FUZZYWIDTH)]++;
	}
    if (space.verts.size() == 0) {
		// The following formula isn't that great.
		// Better to use volume as well eh.
		return (float)(abs(count[OVER]-count[UNDER]) + count[SPLIT] - count[COPLANAR]);
	}
	float volumeover =(float)1.0;
	float volumeunder=(float)1.0;
	float volumetotal=WingMeshVolume(space);
	WingMesh spaceunder= WingMeshCrop(space,float4( split.xyz(), split.w));
	WingMesh spaceover = WingMeshCrop(space,float4(-split.xyz(),-split.w));
	if(usevolcalc==1)
	{
		volumeunder = WingMeshVolume(spaceunder);
		volumeover  = WingMeshVolume(spaceover );
	}
	else if (usevolcalc==2)
	{
		volumeunder = sumbboxdim(spaceunder);
		volumeover  = sumbboxdim(spaceover );
	}
	assert(volumeover/volumetotal>=-0.01);
	assert(volumeunder/volumetotal>=-0.01);
	if(fabs((volumeover+volumeunder-volumetotal)/volumetotal)>0.01)	{
		// ok our volume equations are starting to break down here
		// lets hope that we dont have too many polys to deal with at this point.
		volumetotal=volumeover+volumeunder;
	}
	if(solidbias && onbrep && count[OVER]==0 && count[SPLIT]==0)
	{
		return volumeunder;
	}
	return volumeover *powf(count[OVER] +1.5f*count[SPLIT],0.9f) + 
	       volumeunder*powf(count[UNDER]+1.5f*count[SPLIT],0.9f);
}
Example #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);
	}
*/
}
Example #4
0
std::unique_ptr<BSPNode> BSPCompile(std::vector<Face> && inputfaces,WingMesh space,int side) 
{
    if (inputfaces.size() == 0) {
        std::unique_ptr<BSPNode> node(new BSPNode);
		node->convex = space;
		node->isleaf=side; 
		return node;
	}
	std::vector<Face> over;
	std::vector<Face> under;
	std::vector<Face> coplanar;
	ReorderFaceArray(inputfaces);
	// select partitioning plane
	float minval=FLT_MAX;
	float4 split(float3(0,0,0),0);

//    if (inputfaces.size()>1 && inputfaces.size() <= allowhull)
//	{
//		int j;
//		std::vector<float3> verts;
//		for(i=0;i<inputfaces.size();i++) 
//			for(j=0;j<inputfaces[i]->vertex.size();j++)
//                AddUnique(verts, inputfaces[i]->vertex[j]);
//
//
//        std::vector<int3> tris=calchull(verts.data(), verts.size(), 50);  // passing in array members might not be the best thing here!!
//
//		for(i=0;i<tris.size();i++)
//		{
//			float4 p(TriNormal(verts[tris[i][0]],verts[tris[i][1]],verts[tris[i][2]]),0);
//			if(p.xyz()==float3(0,0,0))continue;
//			p.w = -dot(verts[tris[i][0]],p.xyz());
//			float3 c = (verts[tris[i][0]]+verts[tris[i][1]]+verts[tris[i][2]]) /3.0f + p.xyz() * 0.001f;
//			if(solidbias && !currentbsp) continue; 
//			if(solidbias && HitCheck(currentbsp,1,c,c,&c)) continue;
//			if(WingMeshSplitTest(space,p)!= SPLIT) continue;
//			float val = PlaneCost(inputfaces,p,space,1)*1.01f;
//			if(val<minval) 
//			{
//				minval=val;
//				split = p;
//			}
//		}
//	}

	if(!solidbias || split.xyz()==float3(0,0,0))
	{
        for (unsigned int i = 0; i<inputfaces.size() && (int)i<facetestlimit; i++) {
			float val=PlaneCost(inputfaces, inputfaces[i].plane(), space, 1);
			if(val<minval) {
				minval=val;
				split = inputfaces[i].plane();
			}
		}
		assert(split.xyz() != float3(0,0,0));
		PlaneCost(inputfaces,split,space,1);
        if (allowaxial && inputfaces.size() > 8) {
			// consider some other planes:
            for (unsigned int i = 0; i<inputfaces.size() && (int)i<facetestlimit; i++) {
				for(unsigned int j=0;j<inputfaces[i].vertex.size();j++ ) {
					float val;
					if(allowaxial & (1<<0))
					{
						val = PlaneCost(inputfaces,float4(float3(1,0,0),-inputfaces[i].vertex[j].x),space,0);
						if(val<minval && (count[OVER]*count[UNDER]>0 || count[SPLIT]>0)) { 
							minval=val;
							split.xyz() = float3(1, 0, 0);
							split.w   = -inputfaces[i].vertex[j].x;
						}
					}
					if(allowaxial & (1<<1))
					{
						val = PlaneCost(inputfaces,float4(float3(0,1,0),-inputfaces[i].vertex[j].y),space,0);
						if(val<minval && (count[OVER]*count[UNDER]>0 || count[SPLIT]>0)) { 
							minval=val;
							split.xyz() = float3(0, 1, 0);
							split.w   = -inputfaces[i].vertex[j].y;
						}
					}
					if(allowaxial & (1<<2))
					{
						val = PlaneCost(inputfaces,float4(float3(0,0,1),-inputfaces[i].vertex[j].z),space,0);
						if(val<minval && (count[OVER]*count[UNDER]>0 || count[SPLIT]>0)) { 
							minval=val;
							split.xyz() = float3(0, 0, 1);
							split.w   = -inputfaces[i].vertex[j].z;
						}
					}
				}
			}
		}
	}
	// Divide the faces
    std::unique_ptr<BSPNode> node(new BSPNode);
    node->plane() = split;
	node->convex = space;

	DividePolys(float4(split.xyz(), split.w), std::move(inputfaces), under, over, coplanar);

	for(unsigned int i=0;i<over.size();i++) {
		for(unsigned int j=0;j<over[i].vertex.size();j++) {
			assert(dot(node->xyz(),over[i].vertex[j])+node->w >= -FUZZYWIDTH);
		}
	}
	for(unsigned int i=0;i<under.size();i++) {
		for(unsigned int j=0;j<under[i].vertex.size();j++) {
			assert(dot(node->xyz(),under[i].vertex[j])+node->w <= FUZZYWIDTH);
		}
	}

	node->under = BSPCompile(std::move(under), WingMeshCrop(space, split), UNDER);
	node->over = BSPCompile(std::move(over), WingMeshCrop(space, -split), OVER);
	return node;
}