//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())); }
Face FaceClip(Face && face,const float4 &clip) { assert(FaceSplitTest(face, clip) == SPLIT); FaceSlice(face,clip); std::vector<float3> tmp; for(unsigned int i=0;i<face.vertex.size();i++){ if (PlaneTest(clip, face.vertex[i]) != OVER) { tmp.push_back(face.vertex[i]); } } face.vertex.clear(); for (unsigned int i = 0; i<tmp.size(); i++){ face.vertex.push_back(tmp[i]); } return face; }
void FaceCutting(BSPNode *n,std::vector<Face*> &faces) { if(n->isleaf==OVER) { return; } if(n->isleaf==UNDER) { for(auto &f : faces) { delete f; } faces.clear(); return; } std::vector<Face*> faces_over; std::vector<Face*> faces_under; std::vector<Face*> faces_coplanar; while (faces.size()) { Face *f; f= Pop(faces); int s = FaceSplitTest(f, n->plane()); if(s==COPLANAR) faces_coplanar.push_back(f); else if(s==UNDER) faces_under.push_back(f); else if(s==OVER) faces_over.push_back(f); else { assert(s==SPLIT); Face *ovr = FaceDup(f); FaceClip(f,(*n)); FaceClip(ovr, float4(-n->xyz(), -n->w)); faces_under.push_back(f); faces_over.push_back(ovr); } } FaceCutting(n->under,faces_under); FaceCutting(n->over,faces_over); for(unsigned int i=0;i<faces_under.size();i++) faces.push_back(faces_under[i]); for (unsigned int i = 0; i<faces_over.size(); i++) faces.push_back(faces_over[i]); for (unsigned int i = 0; i<faces_coplanar.size(); i++) faces.push_back(faces_coplanar[i]); }
static void ExtractMat(BSPNode *n,const Face &poly) { for(unsigned int i=0;i<n->brep.size();i++) { ExtractMat(n->brep[i],poly); } if(n->isleaf) { return; } int flag = FaceSplitTest(poly, n->plane()); if(flag==COPLANAR) { ExtractMat((dot(n->xyz(), poly.xyz())>0) ? n->under.get() : n->over.get(), poly); return; } if(flag & UNDER) { ExtractMat(n->under.get(),poly); } if(flag & OVER) { ExtractMat(n->over.get() ,poly); } }
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); }
static void ExtractMat(Face & face,const Face & src) { if (dot(face.xyz(), src.xyz())<0.95f) { return; } if (FaceSplitTest(face, src.plane(), PAPERWIDTH) != COPLANAR) { return; } float3 interior(0,0,0); for(auto &v : face.vertex) interior += v * (1.0f/face.vertex.size()); if (!PolyHitCheck(src.vertex, interior + face.xyz(), interior - face.xyz())){ return; } // src and face coincident face.matid = src.matid; face.gu = src.gu; face.gv = src.gv; face.ot = src.ot; }
void FaceCutting(BSPNode *n, std::vector<Face> & faces) { if(n->isleaf==OVER) { return; } if(n->isleaf==UNDER) { faces.clear(); return; } std::vector<Face> faces_over; std::vector<Face> faces_under; std::vector<Face> faces_coplanar; while (faces.size()) { Face f = Pop(faces); int s = FaceSplitTest(f, n->plane()); if(s==COPLANAR) faces_coplanar.push_back(std::move(f)); else if(s==UNDER) faces_under.push_back(std::move(f)); else if(s==OVER) faces_over.push_back(std::move(f)); else { assert(s==SPLIT); faces_under.push_back(FaceClip(f, n->plane())); faces_over.push_back(FaceClip(std::move(f), -n->plane())); } } FaceCutting(n->under.get(),faces_under); FaceCutting(n->over.get(),faces_over); for(unsigned int i=0;i<faces_under.size();i++) faces.push_back(faces_under[i]); for (unsigned int i = 0; i<faces_over.size(); i++) faces.push_back(faces_over[i]); for (unsigned int i = 0; i<faces_coplanar.size(); i++) faces.push_back(faces_coplanar[i]); }
void DividePolys(const float4 &splitplane,std::vector<Face> && inputfaces, std::vector<Face> &under,std::vector<Face> &over,std::vector<Face> &coplanar){ int i=inputfaces.size(); while(i--) { int flag = FaceSplitTest(inputfaces[i],splitplane,FUZZYWIDTH); if(flag == OVER) { over.push_back(std::move(inputfaces[i])); } else if(flag == UNDER) { under.push_back(std::move(inputfaces[i])); } else if(flag == COPLANAR) { coplanar.push_back(std::move(inputfaces[i])); } else { assert(flag == SPLIT); over.push_back(FaceClip(inputfaces[i], -splitplane)); under.push_back(FaceClip(std::move(inputfaces[i]), splitplane)); } } }
static void BSPClipFace(BSPNode *n,Face && face,const float3 &position,std::vector<Face> &under,std::vector<Face> &over) { if(n->isleaf==UNDER) { under.push_back(face); return; } if(n->isleaf==OVER) { over.push_back(face); return; } float4 plane(n->xyz(), n->w + dot(position, n->xyz())); int flag = FaceSplitTest(face, plane); if(flag == UNDER) { return BSPClipFace(n->under.get(),std::move(face),position,under,over); } if(flag == OVER) { return BSPClipFace(n->over.get(),std::move(face),position,under,over); } if(flag==COPLANAR) { return BSPClipFace(dot(n->xyz(), face.xyz()) > 0 ? n->under.get() : n->over.get(), std::move(face), position, under, over); } assert(flag==SPLIT); Face funder, fover; fover.xyz() = funder.xyz() = face.xyz(); fover.w = funder.w = face.w; fover.gu = funder.gu = face.gu; fover.gv = funder.gv = face.gv; fover.ot = funder.ot = face.ot; fover.matid= funder.matid= face.matid; for(unsigned int i=0;i<face.vertex.size();i++){ float3& vi = face.vertex[i]; float3& vi1= face.vertex[(i+1)%face.vertex.size()]; int vf = PlaneTest(float4(plane.xyz(), plane.w), vi); int vf1 = PlaneTest(float4(plane.xyz(), plane.w), vi1); if(vf==COPLANAR) { funder.vertex.push_back(vi); fover.vertex.push_back(vi); continue; // possible loop optimization } else if(vf==UNDER) { funder.vertex.push_back(vi); } else { assert(vf==OVER); fover.vertex.push_back(vi); } if(vf != vf1 && vf !=COPLANAR && vf1 != COPLANAR) { float3 vmid = PlaneLineIntersection(plane.xyz(), plane.w, vi, vi1); funder.vertex.push_back(vmid); fover.vertex.push_back(vmid); } } BSPClipFace(n->under.get(),std::move(funder),position,under,over); BSPClipFace(n->over.get() ,std::move(fover) ,position,under,over); }