forked from bartvdbraak/blender
Boolean modifier: prevent crashes when carve returns bad topology
For sure actual issue is in carve's triangulation system which need to be investigated and fixed. For now only fixed by re-shuffling a bit existing degenerative faces check and added extra checks there. Would look into actual fix a bit later.
This commit is contained in:
parent
2a98e83abd
commit
049dd8a0ff
@ -547,13 +547,32 @@ static uint quadMerge(std::map<MeshSet<3>::vertex_t*, uint> *vertexToIndex_map,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool Carve_checkDegeneratedFace(MeshSet<3>::face_t *face)
|
static bool Carve_checkDegeneratedFace(std::map<MeshSet<3>::vertex_t*, uint> *vertexToIndex_map, MeshSet<3>::face_t *face)
|
||||||
{
|
{
|
||||||
/* only tris and quads for now */
|
/* only tris and quads for now */
|
||||||
if (face->n_edges == 3) {
|
if (face->n_edges == 3) {
|
||||||
|
uint v1, v2, v3;
|
||||||
|
|
||||||
|
v1 = vertexToIndex_map->find(face->edge->prev->vert)->second;
|
||||||
|
v2 = vertexToIndex_map->find(face->edge->vert)->second;
|
||||||
|
v3 = vertexToIndex_map->find(face->edge->next->vert)->second;
|
||||||
|
|
||||||
|
if (v1 == v2 || v2 == v3 || v1 == v3)
|
||||||
|
return true;
|
||||||
|
|
||||||
return triangleArea(face->edge->prev->vert->v, face->edge->vert->v, face->edge->next->vert->v) < DBL_EPSILON;
|
return triangleArea(face->edge->prev->vert->v, face->edge->vert->v, face->edge->next->vert->v) < DBL_EPSILON;
|
||||||
}
|
}
|
||||||
else if (face->n_edges == 4) {
|
else if (face->n_edges == 4) {
|
||||||
|
uint v1, v2, v3, v4;
|
||||||
|
|
||||||
|
v1 = vertexToIndex_map->find(face->edge->prev->vert)->second;
|
||||||
|
v2 = vertexToIndex_map->find(face->edge->vert)->second;
|
||||||
|
v3 = vertexToIndex_map->find(face->edge->next->vert)->second;
|
||||||
|
v4 = vertexToIndex_map->find(face->edge->next->next->vert)->second;
|
||||||
|
|
||||||
|
if (v1 == v2 || v1 == v3 || v1 == v4 || v2 == v3 || v2 == v4 || v3 == v4)
|
||||||
|
return true;
|
||||||
|
|
||||||
return triangleArea(face->edge->vert->v, face->edge->next->vert->v, face->edge->next->next->vert->v) +
|
return triangleArea(face->edge->vert->v, face->edge->next->vert->v, face->edge->next->next->vert->v) +
|
||||||
triangleArea(face->edge->prev->vert->v, face->edge->vert->v, face->edge->next->next->vert->v) < DBL_EPSILON;
|
triangleArea(face->edge->prev->vert->v, face->edge->vert->v, face->edge->next->next->vert->v) < DBL_EPSILON;
|
||||||
}
|
}
|
||||||
@ -595,8 +614,14 @@ static BSP_CSGMesh *Carve_exportMesh(MeshSet<3>* &poly, carve::interpolate::Face
|
|||||||
MeshSet<3>::face_iter face_iter = poly->faceBegin();
|
MeshSet<3>::face_iter face_iter = poly->faceBegin();
|
||||||
for (i = 0; face_iter != poly->faceEnd(); ++face_iter, ++i) {
|
for (i = 0; face_iter != poly->faceEnd(); ++face_iter, ++i) {
|
||||||
MeshSet<3>::face_t *f = *face_iter;
|
MeshSet<3>::face_t *f = *face_iter;
|
||||||
|
|
||||||
|
if (Carve_checkDegeneratedFace(&vertexToIndex_map, f))
|
||||||
|
continue;
|
||||||
|
|
||||||
ofaces[oface_num.getAttribute(f)].push_back(i);
|
ofaces[oface_num.getAttribute(f)].push_back(i);
|
||||||
|
|
||||||
MeshSet<3>::face_t::edge_iter_t edge_iter = f->begin();
|
MeshSet<3>::face_t::edge_iter_t edge_iter = f->begin();
|
||||||
|
|
||||||
for (; edge_iter != f->end(); ++edge_iter) {
|
for (; edge_iter != f->end(); ++edge_iter) {
|
||||||
int index = vertexToIndex_map[edge_iter->vert];
|
int index = vertexToIndex_map[edge_iter->vert];
|
||||||
vi[index].push_back(i);
|
vi[index].push_back(i);
|
||||||
@ -659,36 +684,27 @@ static BSP_CSGMesh *Carve_exportMesh(MeshSet<3>* &poly, carve::interpolate::Face
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool degenerativeFace = false;
|
// add all information except vertices to the output mesh
|
||||||
|
outputMesh->FaceSet().push_back(BSP_MFace());
|
||||||
|
BSP_MFace& outFace = outputMesh->FaceSet().back();
|
||||||
|
outFace.m_verts.clear();
|
||||||
|
outFace.m_plane.setValue(f->plane.N.v);
|
||||||
|
outFace.m_orig_face = orig;
|
||||||
|
|
||||||
if (!result) {
|
// if we merged faces, use the list of common vertices; otherwise
|
||||||
/* merged triangles are already checked for degenerative quad */
|
// use the faces's vertices
|
||||||
degenerativeFace = Carve_checkDegeneratedFace(f);
|
if (result) {
|
||||||
}
|
// make quat using verts stored in result
|
||||||
|
outFace.m_verts.push_back(quadverts[0]);
|
||||||
if (!degenerativeFace) {
|
outFace.m_verts.push_back(quadverts[1]);
|
||||||
// add all information except vertices to the output mesh
|
outFace.m_verts.push_back(quadverts[2]);
|
||||||
outputMesh->FaceSet().push_back(BSP_MFace());
|
outFace.m_verts.push_back(quadverts[3]);
|
||||||
BSP_MFace& outFace = outputMesh->FaceSet().back();
|
} else {
|
||||||
outFace.m_verts.clear();
|
MeshSet<3>::face_t::edge_iter_t edge_iter = f->begin();
|
||||||
outFace.m_plane.setValue(f->plane.N.v);
|
for (; edge_iter != f->end(); ++edge_iter) {
|
||||||
outFace.m_orig_face = orig;
|
//int index = ofacevert_num.getAttribute(f, edge_iter.idx());
|
||||||
|
int index = vertexToIndex_map[edge_iter->vert];
|
||||||
// if we merged faces, use the list of common vertices; otherwise
|
outFace.m_verts.push_back( index );
|
||||||
// use the faces's vertices
|
|
||||||
if (result) {
|
|
||||||
// make quat using verts stored in result
|
|
||||||
outFace.m_verts.push_back(quadverts[0]);
|
|
||||||
outFace.m_verts.push_back(quadverts[1]);
|
|
||||||
outFace.m_verts.push_back(quadverts[2]);
|
|
||||||
outFace.m_verts.push_back(quadverts[3]);
|
|
||||||
} else {
|
|
||||||
MeshSet<3>::face_t::edge_iter_t edge_iter = f->begin();
|
|
||||||
for (; edge_iter != f->end(); ++edge_iter) {
|
|
||||||
//int index = ofacevert_num.getAttribute(f, edge_iter.idx());
|
|
||||||
int index = vertexToIndex_map[edge_iter->vert];
|
|
||||||
outFace.m_verts.push_back( index );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user