diff options
Diffstat (limited to 'source/blender/blenlib')
-rw-r--r-- | source/blender/blenlib/BLI_mesh_intersect.hh | 8 | ||||
-rw-r--r-- | source/blender/blenlib/intern/mesh_boolean.cc | 12 | ||||
-rw-r--r-- | source/blender/blenlib/intern/mesh_intersect.cc | 48 |
3 files changed, 57 insertions, 11 deletions
diff --git a/source/blender/blenlib/BLI_mesh_intersect.hh b/source/blender/blenlib/BLI_mesh_intersect.hh index 877363b998a..ddda3edf2ff 100644 --- a/source/blender/blenlib/BLI_mesh_intersect.hh +++ b/source/blender/blenlib/BLI_mesh_intersect.hh @@ -327,8 +327,14 @@ class IMesh { * Replace face at given index with one that elides the * vertices at the positions in face_pos_erase that are true. * Use arena to allocate the new face in. + * This may end up setting the face at f_index to NULL. + * Return true if that is so, else return false. + * The caller may want to use remove_null_faces if any face + * was removed, to avoid the need to check for null faces later. */ - void erase_face_positions(int f_index, Span<bool> face_pos_erase, IMeshArena *arena); + bool erase_face_positions(int f_index, Span<bool> face_pos_erase, IMeshArena *arena); + + void remove_null_faces(); }; std::ostream &operator<<(std::ostream &os, const IMesh &mesh); diff --git a/source/blender/blenlib/intern/mesh_boolean.cc b/source/blender/blenlib/intern/mesh_boolean.cc index 4ff5afdb05f..bac1b0665c8 100644 --- a/source/blender/blenlib/intern/mesh_boolean.cc +++ b/source/blender/blenlib/intern/mesh_boolean.cc @@ -751,7 +751,7 @@ static PatchesInfo find_patches(const IMesh &tm, const TriMeshTopology &tmtopo) if (dbg_level > 1) { std::cout << "\ntriangle map\n"; for (int t : tm.face_index_range()) { - std::cout << t << ": patch " << pinfo.tri_patch(t) << "\n"; + std::cout << t << ": " << tm.face(t) << " patch " << pinfo.tri_patch(t) << "\n"; } } std::cout << "\npatch-patch incidences\n"; @@ -3135,6 +3135,7 @@ static void dissolve_verts(IMesh *imesh, const Array<bool> dissolve, IMeshArena { constexpr int inline_face_size = 100; Vector<bool, inline_face_size> face_pos_erase; + bool any_faces_erased = false; for (int f : imesh->face_index_range()) { const Face &face = *imesh->face(f); face_pos_erase.clear(); @@ -3151,10 +3152,13 @@ static void dissolve_verts(IMesh *imesh, const Array<bool> dissolve, IMeshArena } } if (num_erase > 0) { - imesh->erase_face_positions(f, face_pos_erase, arena); + any_faces_erased |= imesh->erase_face_positions(f, face_pos_erase, arena); } } imesh->set_dirty_verts(); + if (any_faces_erased) { + imesh->remove_null_faces(); + } } /** @@ -3376,6 +3380,10 @@ IMesh boolean_mesh(IMesh &imesh, IMesh ans = polymesh_from_trimesh_with_dissolve(tm_out, imesh, arena); if (dbg_level > 0) { std::cout << "boolean_mesh output:\n" << ans; + if (dbg_level > 2) { + ans.populate_vert(); + dump_test_spec(ans); + } } return ans; } diff --git a/source/blender/blenlib/intern/mesh_intersect.cc b/source/blender/blenlib/intern/mesh_intersect.cc index 1eea58e4eb2..3929cc12198 100644 --- a/source/blender/blenlib/intern/mesh_intersect.cc +++ b/source/blender/blenlib/intern/mesh_intersect.cc @@ -81,11 +81,15 @@ uint64_t Vert::hash() const std::ostream &operator<<(std::ostream &os, const Vert *v) { + constexpr int dbg_level = 0; os << "v" << v->id; if (v->orig != NO_INDEX) { os << "o" << v->orig; } os << v->co; + if (dbg_level > 0) { + os << "=" << v->co_exact; + } return os; } @@ -259,10 +263,7 @@ std::ostream &operator<<(std::ostream &os, const Face *f) { os << "f" << f->id << "o" << f->orig << "["; for (const Vert *v : *f) { - os << "v" << v->id; - if (v->orig != NO_INDEX) { - os << "o" << v->orig; - } + os << v; if (v != f->vert[f->size() - 1]) { os << " "; } @@ -650,7 +651,7 @@ void IMesh::populate_vert(int max_verts) vert_populated_ = true; } -void IMesh::erase_face_positions(int f_index, Span<bool> face_pos_erase, IMeshArena *arena) +bool IMesh::erase_face_positions(int f_index, Span<bool> face_pos_erase, IMeshArena *arena) { const Face *cur_f = this->face(f_index); int cur_len = cur_f->size(); @@ -661,12 +662,18 @@ void IMesh::erase_face_positions(int f_index, Span<bool> face_pos_erase, IMeshAr } } if (num_to_erase == 0) { - return; + return false; } int new_len = cur_len - num_to_erase; if (new_len < 3) { - /* Invalid erase. Don't do anything. */ - return; + /* This erase causes removal of whole face. + * Because this may be called from a loop over the face array, + * we don't want to compress that array right here; instead will + * mark with null pointer and caller should call remove_null_faces(). + * the loop is done. + */ + this->face_[f_index] = NULL; + return true; } Array<const Vert *> new_vert(new_len); Array<int> new_edge_orig(new_len); @@ -682,6 +689,31 @@ void IMesh::erase_face_positions(int f_index, Span<bool> face_pos_erase, IMeshAr } BLI_assert(new_index == new_len); this->face_[f_index] = arena->add_face(new_vert, cur_f->orig, new_edge_orig, new_is_intersect); + return false; +} + +void IMesh::remove_null_faces() +{ + int64_t nullcount = 0; + for (Face *f : this->face_) { + if (f == NULL) { + ++nullcount; + } + } + if (nullcount == 0) { + return; + } + int64_t new_size = this->face_.size() - nullcount; + int64_t copy_to_index = 0; + int64_t copy_from_index = 0; + Array<Face *> new_face(new_size); + while (copy_from_index < face_.size()) { + Face *f_from = face_[copy_from_index++]; + if (f_from) { + new_face[copy_to_index++] = f_from; + } + } + this->face_ = new_face; } std::ostream &operator<<(std::ostream &os, const IMesh &mesh) |