From a3a6f304038932f13225c1346742c63e15afba7d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 29 Feb 2012 13:48:19 +0000 Subject: Boolean modifier: - Fixed convex quad detection (in some special cases non-convex quad was detecting as convex) - Do not add faces with zero area to the output object. This should resolve #30395: Degenerated triangles from BMesh + Difference --- intern/boolop/intern/BOP_CarveInterface.cpp | 81 +++++++++++++++++++++-------- 1 file changed, 58 insertions(+), 23 deletions(-) (limited to 'intern') diff --git a/intern/boolop/intern/BOP_CarveInterface.cpp b/intern/boolop/intern/BOP_CarveInterface.cpp index 6fc08e52ade..aa6de7f3017 100644 --- a/intern/boolop/intern/BOP_CarveInterface.cpp +++ b/intern/boolop/intern/BOP_CarveInterface.cpp @@ -430,6 +430,14 @@ static MeshSet<3> *Carve_addMesh(CSG_FaceIteratorDescriptor &face_it, return poly; } +static double triangleArea(carve::geom3d::Vector &v1, carve::geom3d::Vector &v2, carve::geom3d::Vector &v3) +{ + carve::geom3d::Vector a = v2 - v1; + carve::geom3d::Vector b = v3 - v1; + + return carve::geom::cross(a, b).length(); +} + static bool checkValidQuad(std::vector::vertex_t> &vertex_storage, uint quad[4]) { carve::geom3d::Vector &v1 = vertex_storage[quad[0]].v; @@ -465,12 +473,12 @@ static bool checkValidQuad(std::vector::vertex_t> &vertex_storage, ui carve::geom3d::Vector current_normal = carve::geom::cross(edges[i], edges[n]); - if (current_normal.length() > 1e-6) { + if (current_normal.length() > DBL_EPSILON) { if (!normal_set) { normal = current_normal; normal_set = true; } - else if (carve::geom::dot(normal, current_normal) < -1e-6) { + else if (carve::geom::dot(normal, current_normal) < 0) { return false; } } @@ -481,6 +489,10 @@ static bool checkValidQuad(std::vector::vertex_t> &vertex_storage, ui return false; } + double area = triangleArea(v1, v2, v3) + triangleArea(v1, v3, v4); + if (area <= DBL_EPSILON) + return false; + return true; } @@ -535,6 +547,20 @@ static uint quadMerge(std::map::vertex_t*, uint> *vertexToIndex_map, return 0; } +static bool Carve_checkDegeneratedFace(MeshSet<3>::face_t *face) +{ + /* only tris and quads for now */ + if (face->n_edges == 3) { + return triangleArea(face->edge->prev->vert->v, face->edge->vert->v, face->edge->next->vert->v) < DBL_EPSILON; + } + else if (face->n_edges == 4) { + 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; + } + + return false; +} + static BSP_CSGMesh *Carve_exportMesh(MeshSet<3>* &poly, carve::interpolate::FaceAttr &oface_num, uint num_origfaces) { @@ -591,13 +617,6 @@ static BSP_CSGMesh *Carve_exportMesh(MeshSet<3>* &poly, carve::interpolate::Face MeshSet<3>::face_t *f = *(poly->faceBegin() + findex); - // 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; - // for each vertex of this face, check other faces containing // that vertex to see if there is a neighbor also belonging to // the original face @@ -640,20 +659,36 @@ static BSP_CSGMesh *Carve_exportMesh(MeshSet<3>* &poly, carve::interpolate::Face } } - // if we merged faces, use the list of common vertices; otherwise - // 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 ); + bool degenerativeFace = false; + + if (!result) { + /* merged triangles are already checked for degenerative quad */ + degenerativeFace = Carve_checkDegeneratedFace(f); + } + + if (!degenerativeFace) { + // 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 we merged faces, use the list of common vertices; otherwise + // 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 ); + } } } } -- cgit v1.2.3