forked from bartvdbraak/blender
Boolean op are undeffined when one of the two meshes are a no closed mesh (without holes).
I put a test to check the input meshes before do any thing. If one mesh have holes a error code is returned.
This commit is contained in:
parent
b7a4a6c837
commit
738d3e4ae3
@ -146,7 +146,7 @@ void BOP_mergeVertexs(BOP_Mesh *mesh, unsigned int firstFace);
|
||||
* @param facesB set of faces from object B
|
||||
*/
|
||||
void BOP_Face2Face(BOP_Mesh *mesh, BOP_Faces *facesA, BOP_Faces *facesB)
|
||||
{
|
||||
{
|
||||
for(unsigned int idxFaceA=0;idxFaceA<facesA->size();idxFaceA++) {
|
||||
BOP_Face *faceA = (*facesA)[idxFaceA];
|
||||
MT_Plane3 planeA = faceA->getPlane();
|
||||
@ -160,28 +160,28 @@ void BOP_Face2Face(BOP_Mesh *mesh, BOP_Faces *facesA, BOP_Faces *facesB)
|
||||
idxFaceB<facesB->size() && (faceA->getTAG() != BROKEN) && (faceA->getTAG() != PHANTOM);) {
|
||||
BOP_Face *faceB = (*facesB)[idxFaceB];
|
||||
if ((faceB->getTAG() != BROKEN) && (faceB->getTAG() != PHANTOM)) {
|
||||
BOP_BBox boxB(mesh->getVertex(faceB->getVertex(0))->getPoint(),
|
||||
mesh->getVertex(faceB->getVertex(1))->getPoint(),
|
||||
mesh->getVertex(faceB->getVertex(2))->getPoint());
|
||||
if (boxA.intersect(boxB)) {
|
||||
BOP_BBox boxB(mesh->getVertex(faceB->getVertex(0))->getPoint(),
|
||||
mesh->getVertex(faceB->getVertex(1))->getPoint(),
|
||||
mesh->getVertex(faceB->getVertex(2))->getPoint());
|
||||
if (boxA.intersect(boxB)) {
|
||||
|
||||
MT_Plane3 planeB = faceB->getPlane();
|
||||
if (BOP_containsPoint(planeB,p1) &&
|
||||
BOP_containsPoint(planeB,p2) &&
|
||||
BOP_containsPoint(planeB,p3)) {
|
||||
if (BOP_orientation(planeB,planeA)>0) {
|
||||
BOP_intersectCoplanarFaces(mesh,facesB,faceA,faceB,false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
BOP_intersectNonCoplanarFaces(mesh,facesA,facesB,faceA,faceB);
|
||||
}
|
||||
}
|
||||
MT_Plane3 planeB = faceB->getPlane();
|
||||
if (BOP_containsPoint(planeB,p1) &&
|
||||
BOP_containsPoint(planeB,p2) &&
|
||||
BOP_containsPoint(planeB,p3)) {
|
||||
if (BOP_orientation(planeB,planeA)>0) {
|
||||
BOP_intersectCoplanarFaces(mesh,facesB,faceA,faceB,false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
BOP_intersectNonCoplanarFaces(mesh,facesA,facesB,faceA,faceB);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (faceB->getTAG()==BROKEN){
|
||||
facesB->erase(facesB->begin()+idxFaceB);
|
||||
facesB->erase(facesB->begin()+idxFaceB);
|
||||
}else
|
||||
idxFaceB++;
|
||||
idxFaceB++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,9 +92,9 @@ BoolOpState BOP_performBooleanOperation(BoolOpType opType,
|
||||
CSG_VertexIteratorDescriptor obBVertices,
|
||||
CSG_InterpolateUserFaceVertexDataFunc interpFunc)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG
|
||||
cout << "BEGIN BOP_performBooleanOperation" << endl;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Set invert flags depending on boolean operation type:
|
||||
// INTERSECTION: A^B = and(A,B)
|
||||
@ -121,6 +121,9 @@ BoolOpState BOP_performBooleanOperation(BoolOpType opType,
|
||||
// Add B-mesh into C-mesh
|
||||
BOP_addMesh(&meshC, &meshBFacesId, &materials, obBProps, obBFaces, obBVertices, invertMeshB);
|
||||
|
||||
if (!meshC.isClosedMesh())
|
||||
return BOP_NO_SOLID;
|
||||
|
||||
// Perform the intersection boolean operation.
|
||||
BoolOpState result = BOP_intersectionBoolOp(&meshC, &meshAFacesId, &meshBFacesId,
|
||||
invertMeshA, invertMeshB);
|
||||
@ -128,9 +131,9 @@ BoolOpState BOP_performBooleanOperation(BoolOpType opType,
|
||||
// Invert the output mesh if is required
|
||||
*outputMesh = BOP_exportMesh(&meshC, &materials, outputProps, invertMeshC);
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG
|
||||
cout << "END BOP_performBooleanOperation" << endl;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -151,13 +154,13 @@ BoolOpState BOP_intersectionBoolOp(BOP_Mesh* meshC,
|
||||
bool invertMeshA,
|
||||
bool invertMeshB)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG
|
||||
BOP_Chrono chrono;
|
||||
float t = 0.0f;
|
||||
float c = 0.0f;
|
||||
chrono.start();
|
||||
cout << "---" << endl;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Create BSPs trees for mesh A & B
|
||||
BOP_BSPTree bspA;
|
||||
@ -168,10 +171,10 @@ BoolOpState BOP_intersectionBoolOp(BOP_Mesh* meshC,
|
||||
bspB.addMesh(meshC, *facesB);
|
||||
bspB.computeBox();
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG
|
||||
c = chrono.stamp(); t += c;
|
||||
cout << "Create BSP " << c << endl;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
unsigned int numVertices = meshC->getNumVertexs();
|
||||
|
||||
@ -184,54 +187,54 @@ BoolOpState BOP_intersectionBoolOp(BOP_Mesh* meshC,
|
||||
if ((0.25*facesB->size()) > bspA.getDeep())
|
||||
BOP_meshFilter(meshC, facesB, &bspA);
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG
|
||||
c = chrono.stamp(); t += c;
|
||||
cout << "mesh Filter " << c << endl;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Face 2 Face
|
||||
BOP_Face2Face(meshC,facesA,facesB);
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG
|
||||
c = chrono.stamp(); t += c;
|
||||
cout << "Face2Face " << c << endl;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// BSP classification
|
||||
BOP_meshClassify(meshC,facesA,&bspB);
|
||||
BOP_meshClassify(meshC,facesB,&bspA);
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG
|
||||
c = chrono.stamp(); t += c;
|
||||
cout << "Classification " << c << endl;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Process overlapped faces
|
||||
BOP_removeOverlappedFaces(meshC,facesA,facesB);
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG
|
||||
c = chrono.stamp(); t += c;
|
||||
cout << "Remove overlap " << c << endl;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Sew two meshes
|
||||
BOP_sew(meshC,facesA,facesB);
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG
|
||||
c = chrono.stamp(); t += c;
|
||||
cout << "Sew " << c << endl;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Merge faces
|
||||
BOP_Merge::getInstance().mergeFaces(meshC,numVertices);
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG
|
||||
c = chrono.stamp(); t += c;
|
||||
cout << "Merge faces " << c << endl;
|
||||
cout << "Total " << t << endl;
|
||||
// Test integrity
|
||||
meshC->testMesh();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return BOP_OK;
|
||||
}
|
||||
|
@ -553,6 +553,23 @@ BOP_Index BOP_Mesh::replaceVertexIndex(BOP_Index oldIndex, BOP_Index newIndex)
|
||||
return newIndex;
|
||||
}
|
||||
|
||||
bool BOP_Mesh::isClosedMesh()
|
||||
{
|
||||
for(unsigned int i=0; i<m_edges.size(); i++) {
|
||||
BOP_Edge *edge = m_edges[i];
|
||||
BOP_Indexs faces = edge->getFaces();
|
||||
unsigned int count = 0;
|
||||
const BOP_IT_Indexs facesEnd = faces.end();
|
||||
for(BOP_IT_Indexs it = faces.begin();it!=facesEnd;it++) {
|
||||
if (m_faces[*it]->getTAG()!=BROKEN)
|
||||
count++;
|
||||
}
|
||||
|
||||
if ((count%2)!=0) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/** ***************************************************************************
|
||||
|
@ -82,6 +82,7 @@ public:
|
||||
unsigned int getNumVertexs(BOP_TAG tag);
|
||||
unsigned int getNumFaces(BOP_TAG tag);
|
||||
BOP_Index replaceVertexIndex(BOP_Index oldIndex, BOP_Index newIndex);
|
||||
bool isClosedMesh();
|
||||
|
||||
// Debug functions
|
||||
void print();
|
||||
|
@ -103,15 +103,15 @@ CSG_DescibeOperands(
|
||||
/**
|
||||
* Compute the boolean operation, UNION, INTERSECION or DIFFERENCE
|
||||
*/
|
||||
int
|
||||
int
|
||||
CSG_PerformBooleanOperation(
|
||||
CSG_BooleanOperation *operation,
|
||||
CSG_OperationType op_type,
|
||||
CSG_FaceIteratorDescriptor obAFaces,
|
||||
CSG_VertexIteratorDescriptor obAVertices,
|
||||
CSG_FaceIteratorDescriptor obBFaces,
|
||||
CSG_VertexIteratorDescriptor obBVertices,
|
||||
CSG_InterpolateUserFaceVertexDataFunc interp_func
|
||||
CSG_BooleanOperation *operation,
|
||||
CSG_OperationType op_type,
|
||||
CSG_FaceIteratorDescriptor obAFaces,
|
||||
CSG_VertexIteratorDescriptor obAVertices,
|
||||
CSG_FaceIteratorDescriptor obBFaces,
|
||||
CSG_VertexIteratorDescriptor obBVertices,
|
||||
CSG_InterpolateUserFaceVertexDataFunc interp_func
|
||||
){
|
||||
if (operation == NULL) return 0;
|
||||
BSP_MeshInfo * mesh_info = static_cast<BSP_MeshInfo *>(operation->CSG_info);
|
||||
@ -128,33 +128,39 @@ CSG_PerformBooleanOperation(
|
||||
|
||||
switch( op_type ) {
|
||||
case e_csg_union:
|
||||
boolType = BOP_UNION;
|
||||
break;
|
||||
boolType = BOP_UNION;
|
||||
break;
|
||||
case e_csg_difference:
|
||||
boolType = BOP_DIFFERENCE;
|
||||
break;
|
||||
boolType = BOP_DIFFERENCE;
|
||||
break;
|
||||
default:
|
||||
boolType = BOP_INTERSECTION;
|
||||
break;
|
||||
boolType = BOP_INTERSECTION;
|
||||
break;
|
||||
}
|
||||
|
||||
BoolOpState boolOpResult;
|
||||
try {
|
||||
BOP_performBooleanOperation( boolType,
|
||||
mesh_info->output_descriptor,
|
||||
(BSP_CSGMesh**) &(mesh_info->output_mesh),
|
||||
mesh_info->obB_descriptor,
|
||||
obBFaces,
|
||||
obBVertices,
|
||||
mesh_info->obA_descriptor,
|
||||
obAFaces,
|
||||
obAVertices,
|
||||
interp_func );
|
||||
boolOpResult= BOP_performBooleanOperation( boolType,
|
||||
mesh_info->output_descriptor,
|
||||
(BSP_CSGMesh**) &(mesh_info->output_mesh),
|
||||
mesh_info->obB_descriptor,
|
||||
obBFaces,
|
||||
obBVertices,
|
||||
mesh_info->obA_descriptor,
|
||||
obAFaces,
|
||||
obAVertices,
|
||||
interp_func );
|
||||
}
|
||||
catch(...) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return success;
|
||||
switch (boolOpResult) {
|
||||
case BOP_OK: return 1;
|
||||
case BOP_NO_SOLID: return -2;
|
||||
case BOP_ERROR: return 0;
|
||||
default: return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
|
Loading…
Reference in New Issue
Block a user