Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHoward Trickey <howard.trickey@gmail.com>2020-08-22 14:30:13 +0300
committerHoward Trickey <howard.trickey@gmail.com>2020-08-22 14:30:13 +0300
commit9810cfa1e83f173ccbdc1c3335183f93529838b5 (patch)
tree3f3d79feb348f1b41125c965ec2ce632a3a200f4
parent0a6ef6950959ae0e86a5a7ff12262e78eb852a9f (diff)
Addressed comments of reviewers on D8623.
Almost all changes asked for by Campbell and Jacques have been addressed. The clang-tidy fixes will happen in the next commit.
-rw-r--r--build_files/build_environment/cmake/versions.cmake2
-rw-r--r--source/blender/blenlib/BLI_double2.hh7
-rw-r--r--source/blender/blenlib/BLI_double3.hh5
-rw-r--r--source/blender/blenlib/BLI_mesh_boolean.hh18
-rw-r--r--source/blender/blenlib/BLI_mesh_intersect.hh21
-rw-r--r--source/blender/blenlib/BLI_mpq2.hh5
-rw-r--r--source/blender/blenlib/BLI_mpq3.hh5
-rw-r--r--source/blender/blenlib/intern/delaunay_2d.cc62
-rw-r--r--source/blender/blenlib/intern/mesh_boolean.cc304
-rw-r--r--source/blender/blenlib/intern/mesh_intersect.cc138
-rw-r--r--source/blender/blenlib/tests/BLI_mesh_boolean_test.cc97
-rw-r--r--source/blender/blenlib/tests/BLI_mesh_intersect_test.cc4
-rw-r--r--source/blender/bmesh/tools/bmesh_boolean.cc21
13 files changed, 338 insertions, 351 deletions
diff --git a/build_files/build_environment/cmake/versions.cmake b/build_files/build_environment/cmake/versions.cmake
index e5a24e4fe13..37bfac8bfba 100644
--- a/build_files/build_environment/cmake/versions.cmake
+++ b/build_files/build_environment/cmake/versions.cmake
@@ -312,9 +312,11 @@ set(NASM_HASH f4fd1329b1713e1ccd34b2fc121c4bcd278c9f91cc4cb205ae8fcd2e4728dd14)
set(XR_OPENXR_SDK_VERSION 1.0.8)
set(XR_OPENXR_SDK_URI https://github.com/KhronosGroup/OpenXR-SDK/archive/release-${XR_OPENXR_SDK_VERSION}.tar.gz)
set(XR_OPENXR_SDK_HASH c6de63d2e0f9029aa58dfa97cad8ce07)
+set(ISPC_VERSION v1.13.0)
set(ISPC_URI https://github.com/ispc/ispc/archive/${ISPC_VERSION}.tar.gz)
set(ISPC_HASH 4bf5e8d0020c4b9980faa702c1a6f25f)
set(GMP_VERSION 6.2.0)
+
set(GMP_URI https://gmplib.org/download/gmp/gmp-${GMP_VERSION}.tar.xz)
set(GMP_HASH a325e3f09e6d91e62101e59f9bda3ec1)
diff --git a/source/blender/blenlib/BLI_double2.hh b/source/blender/blenlib/BLI_double2.hh
index a85f74ee442..654207d98f1 100644
--- a/source/blender/blenlib/BLI_double2.hh
+++ b/source/blender/blenlib/BLI_double2.hh
@@ -83,6 +83,11 @@ struct double2 {
return a.x == b.x && a.y == b.y;
}
+ friend bool operator!=(const double2 &a, const double2 &b)
+ {
+ return a.x != b.x || a.y != b.y;
+ }
+
friend std::ostream &operator<<(std::ostream &stream, const double2 &v)
{
stream << "(" << v.x << ", " << v.y << ")";
@@ -101,7 +106,7 @@ struct double2 {
static double2 abs(const double2 &a)
{
- return double2(fabsf(a.x), fabsf(a.y));
+ return double2(fabs(a.x), fabs(a.y));
}
static double distance(const double2 &a, const double2 &b)
diff --git a/source/blender/blenlib/BLI_double3.hh b/source/blender/blenlib/BLI_double3.hh
index 11a88e121ca..fb9823c3ec0 100644
--- a/source/blender/blenlib/BLI_double3.hh
+++ b/source/blender/blenlib/BLI_double3.hh
@@ -176,6 +176,11 @@ struct double3 {
return a.x == b.x && a.y == b.y && a.z == b.z;
}
+ friend bool operator!=(const double3 &a, const double3 &b)
+ {
+ return a.x != b.x || a.y != b.y || a.z != b.z;
+ }
+
friend std::ostream &operator<<(std::ostream &stream, const double3 &v)
{
stream << "(" << v.x << ", " << v.y << ", " << v.z << ")";
diff --git a/source/blender/blenlib/BLI_mesh_boolean.hh b/source/blender/blenlib/BLI_mesh_boolean.hh
index 324a5adecc7..2b5afb2bffc 100644
--- a/source/blender/blenlib/BLI_mesh_boolean.hh
+++ b/source/blender/blenlib/BLI_mesh_boolean.hh
@@ -30,12 +30,12 @@ namespace blender::meshintersect {
/* Enum values after BOOLEAN_NONE need to match BMESH_ISECT_BOOLEAN_... values in
* editmesh_intersect.c. */
-enum bool_optype {
- BOOLEAN_NONE = -1,
+enum class BoolOpType {
+ None = -1,
/* Aligned with BooleanModifierOp. */
- BOOLEAN_ISECT = 0,
- BOOLEAN_UNION = 1,
- BOOLEAN_DIFFERENCE = 2,
+ Intersect = 0,
+ Union = 1,
+ Difference = 2,
};
/* Do the boolean operation op on the mesh pm_in.
@@ -52,8 +52,8 @@ enum bool_optype {
* The output IMesh will have faces whose orig fields map back to faces and edges in
* the input mesh.
*/
-IMesh boolean_mesh(IMesh &pm,
- bool_optype op,
+IMesh boolean_mesh(IMesh &imesh,
+ BoolOpType op,
int nshapes,
std::function<int(int)> shape_fn,
bool use_self,
@@ -64,8 +64,8 @@ IMesh boolean_mesh(IMesh &pm,
* It is exposed mainly for unit testing, at the moment: boolean_mesh() uses
* it to do most of its work.
*/
-IMesh boolean_trimesh(IMesh &tm,
- bool_optype op,
+IMesh boolean_trimesh(IMesh &trimesh,
+ BoolOpType op,
int nshapes,
std::function<int(int)> shape_fn,
bool use_self,
diff --git a/source/blender/blenlib/BLI_mesh_intersect.hh b/source/blender/blenlib/BLI_mesh_intersect.hh
index 1c77a67877d..d7cf0b01823 100644
--- a/source/blender/blenlib/BLI_mesh_intersect.hh
+++ b/source/blender/blenlib/BLI_mesh_intersect.hh
@@ -34,6 +34,7 @@
# include "BLI_math_mpq.hh"
# include "BLI_mpq3.hh"
# include "BLI_span.hh"
+# include "BLI_utility_mixins.hh"
# include "BLI_vector.hh"
namespace blender::meshintersect {
@@ -62,14 +63,8 @@ struct Vert {
Vert() = default;
Vert(const mpq3 &mco, const double3 &dco, int id, int orig);
- Vert(const Vert &other);
- Vert(Vert &&other) noexcept;
-
~Vert() = default;
- Vert &operator=(const Vert &other);
- Vert &operator=(Vert &&other) noexcept;
-
/* Test equality on the co_exact field. */
bool operator==(const Vert &other) const;
@@ -127,14 +122,8 @@ struct Face {
Face() = default;
Face(Span<const Vert *> verts, int id, int orig, Span<int> edge_origs, Span<bool> is_intersect);
Face(Span<const Vert *> verts, int id, int orig);
- Face(const Face &other);
- Face(Face &&other) noexcept;
-
~Face() = default;
- Face &operator=(const Face &other);
- Face &operator=(Face &&other) noexcept;
-
bool is_tri() const
{
return vert.size() == 3;
@@ -190,20 +179,14 @@ std::ostream &operator<<(std::ostream &os, const Face *f);
* ensure that only one instance of a Vert with a given co_exact will
* exist. I.e., it dedups the vertices.
*/
-class IMeshArena {
+class IMeshArena : NonCopyable, NonMovable {
class IMeshArenaImpl;
std::unique_ptr<IMeshArenaImpl> pimpl_;
public:
IMeshArena();
- IMeshArena(const IMeshArena &) = delete;
- IMeshArena(IMeshArena &&) = delete;
-
~IMeshArena();
- IMeshArena &operator=(const IMeshArena &) = delete;
- IMeshArena &operator=(IMeshArena &&) = delete;
-
/* Provide hints to number of expected Verts and Faces expected
* to be allocated.
*/
diff --git a/source/blender/blenlib/BLI_mpq2.hh b/source/blender/blenlib/BLI_mpq2.hh
index a37140da5ec..86a7b0ac3a8 100644
--- a/source/blender/blenlib/BLI_mpq2.hh
+++ b/source/blender/blenlib/BLI_mpq2.hh
@@ -116,6 +116,11 @@ struct mpq2 {
return a.x == b.x && a.y == b.y;
}
+ friend bool operator!=(const mpq2 &a, const mpq2 &b)
+ {
+ return a.x != b.x || a.y != b.y;
+ }
+
friend std::ostream &operator<<(std::ostream &stream, const mpq2 &v)
{
stream << "(" << v.x << ", " << v.y << ")";
diff --git a/source/blender/blenlib/BLI_mpq3.hh b/source/blender/blenlib/BLI_mpq3.hh
index fd47abe3dde..a0f1b342d06 100644
--- a/source/blender/blenlib/BLI_mpq3.hh
+++ b/source/blender/blenlib/BLI_mpq3.hh
@@ -198,6 +198,11 @@ struct mpq3 {
return a.x == b.x && a.y == b.y && a.z == b.z;
}
+ friend bool operator!=(const mpq3 &a, const mpq3 &b)
+ {
+ return a.x != b.x || a.y != b.y || a.z != b.z;
+ }
+
friend std::ostream &operator<<(std::ostream &stream, const mpq3 &v)
{
stream << "(" << v.x << ", " << v.y << ", " << v.z << ")";
diff --git a/source/blender/blenlib/intern/delaunay_2d.cc b/source/blender/blenlib/intern/delaunay_2d.cc
index 0cb53a71432..18ce976da82 100644
--- a/source/blender/blenlib/intern/delaunay_2d.cc
+++ b/source/blender/blenlib/intern/delaunay_2d.cc
@@ -529,7 +529,7 @@ template<typename T> CDTVert<T>::CDTVert(const vec2<T> &pt)
template<typename T> CDTVert<T> *CDTArrangement<T>::add_vert(const vec2<T> &pt)
{
CDTVert<T> *v = new CDTVert<T>(pt);
- int index = static_cast<int>(this->verts.append_and_get_index(v));
+ int index = this->verts.append_and_get_index(v);
v->index = index;
return v;
}
@@ -912,7 +912,7 @@ template<typename T> bool site_lexicographic_sort(const SiteInfo<T> &a, const Si
*/
template<typename T> void find_site_merges(Array<SiteInfo<T>> &sites)
{
- int n = static_cast<int>(sites.size());
+ int n = sites.size();
for (int i = 0; i < n - 1; ++i) {
int j = i + 1;
while (j < n && sites[j].v->co == sites[i].v->co) {
@@ -1154,7 +1154,7 @@ template<typename T> void dc_triangulate(CDTArrangement<T> *cdt, Array<SiteInfo<
/* Compress sites in place to eliminted verts that merge to others. */
int i = 0;
int j = 0;
- int nsites = static_cast<int>(sites.size());
+ int nsites = sites.size();
while (j < nsites) {
/* Invariante: sites[0..i-1] have non-merged verts from 0..(j-1) in them. */
sites[i] = sites[j++];
@@ -1191,7 +1191,7 @@ template<typename T> void dc_triangulate(CDTArrangement<T> *cdt, Array<SiteInfo<
*/
template<typename T> void initial_triangulation(CDTArrangement<T> *cdt)
{
- int n = static_cast<int>(cdt->verts.size());
+ int n = cdt->verts.size();
if (n <= 1) {
return;
}
@@ -1433,7 +1433,8 @@ void fill_crossdata_for_intersect(const vec2<T> &curco,
cd->out = se_vcva;
}
}
- } break;
+ break;
+ }
case vec2<T>::isect_result::LINE_LINE_EXACT: {
if (lambda == 0) {
fill_crossdata_for_through_vert(va, se_vcva, cd, cd_next);
@@ -1447,7 +1448,8 @@ void fill_crossdata_for_intersect(const vec2<T> &curco,
cd->out = se_vcva;
}
}
- } break;
+ break;
+ }
case vec2<T>::isect_result::LINE_LINE_NONE: {
#ifdef WITH_GMP
if (std::is_same<T, mpq_class>::value) {
@@ -1462,7 +1464,8 @@ void fill_crossdata_for_intersect(const vec2<T> &curco,
else {
fill_crossdata_for_through_vert(vb, se_vcvb, cd, cd_next);
}
- } break;
+ break;
+ }
case vec2<T>::isect_result::LINE_LINE_COLINEAR: {
if (vec2<T>::distance_squared(va->co, v2->co) <= vec2<T>::distance_squared(vb->co, v2->co)) {
fill_crossdata_for_through_vert(va, se_vcva, cd, cd_next);
@@ -1470,7 +1473,8 @@ void fill_crossdata_for_intersect(const vec2<T> &curco,
else {
fill_crossdata_for_through_vert(vb, se_vcvb, cd, cd_next);
}
- } break;
+ break;
+ }
}
} // namespace blender::meshintersect
@@ -1562,7 +1566,7 @@ template<typename T>
void dump_crossings(const Vector<CrossData<T>, inline_crossings_size> &crossings)
{
std::cout << "CROSSINGS\n";
- for (int i = 0; i < static_cast<int>(crossings.size()); ++i) {
+ for (int i = 0; i < crossings.size(); ++i) {
std::cout << i << ": ";
const CrossData<T> &cd = crossings[i];
if (cd.lambda == 0) {
@@ -1641,7 +1645,7 @@ void add_edge_constraint(
Vector<CrossData<T>, inline_crossings_size> crossings;
crossings.append(CrossData<T>(T(0), v1, nullptr, nullptr));
int n;
- while (!((n = static_cast<int>(crossings.size())) > 0 && crossings[n - 1].vert == v2)) {
+ while (!((n = crossings.size()) > 0 && crossings[n - 1].vert == v2)) {
crossings.append(CrossData<T>());
CrossData<T> *cd = &crossings[n - 1];
CrossData<T> *cd_next = &crossings[n];
@@ -1683,7 +1687,7 @@ void add_edge_constraint(
* This loop marks certain crossings as "deleted", by setting
* their lambdas to -1.0.
*/
- int ncrossings = static_cast<int>(crossings.size());
+ int ncrossings = crossings.size();
for (int i = 2; i < ncrossings; ++i) {
CrossData<T> *cd = &crossings[i];
if (cd->lambda == 0.0) {
@@ -1816,8 +1820,8 @@ void add_edge_constraint(
*/
template<typename T> void add_edge_constraints(CDT_state<T> *cdt_state, const CDT_input<T> &input)
{
- int ne = static_cast<int>(input.edge.size());
- int nv = static_cast<int>(input.vert.size());
+ int ne = input.edge.size();
+ int nv = input.vert.size();
for (int i = 0; i < ne; i++) {
int iv1 = input.edge[i].first;
int iv2 = input.edge[i].second;
@@ -1903,14 +1907,14 @@ static int power_of_10_greater_equal_to(int x)
*/
template<typename T> void add_face_constraints(CDT_state<T> *cdt_state, const CDT_input<T> &input)
{
- int nv = static_cast<int>(input.vert.size());
- int nf = static_cast<int>(input.face.size());
+ int nv = input.vert.size();
+ int nf = input.face.size();
int fstart = 0;
SymEdge<T> *face_symedge0 = nullptr;
CDTArrangement<T> *cdt = &cdt_state->cdt;
int maxflen = 0;
for (int f = 0; f < nf; f++) {
- maxflen = max_ii(maxflen, static_cast<int>(input.face[f].size()));
+ maxflen = max_ii(maxflen, input.face[f].size());
}
/* For convenience in debugging, make face_edge_offset be a power of 10. */
cdt_state->face_edge_offset = power_of_10_greater_equal_to(
@@ -1921,7 +1925,7 @@ template<typename T> void add_face_constraints(CDT_state<T> *cdt_state, const CD
*/
BLI_assert(INT_MAX / cdt_state->face_edge_offset > nf);
for (int f = 0; f < nf; f++) {
- int flen = static_cast<int>(input.face[f].size());
+ int flen = input.face[f].size();
if (flen <= 2) {
/* Ignore faces with fewer than 3 vertices. */
fstart += flen;
@@ -2199,7 +2203,7 @@ CDT_result<T> get_cdt_output(CDT_state<T> *cdt_state,
* corresponding to the vert in position i in cdt->verts.
* This first loop sets vert_to_output_map for unmerged verts.
*/
- int verts_size = static_cast<int>(cdt->verts.size());
+ int verts_size = cdt->verts.size();
Array<int> vert_to_output_map(verts_size);
int nv = 0;
for (int i = 0; i < verts_size; ++i) {
@@ -2300,9 +2304,9 @@ template<typename T> void add_input_verts(CDT_state<T> *cdt_state, const CDT_inp
template<typename T>
CDT_result<T> delaunay_calc(const CDT_input<T> &input, CDT_output_type output_type)
{
- int nv = static_cast<int>(input.vert.size());
- int ne = static_cast<int>(input.edge.size());
- int nf = static_cast<int>(input.face.size());
+ int nv = input.vert.size();
+ int ne = input.edge.size();
+ int nf = input.face.size();
CDT_state<T> cdt_state(nv, ne, nf, input.epsilon);
add_input_verts(&cdt_state, input);
initial_triangulation(&cdt_state.cdt);
@@ -2363,22 +2367,22 @@ extern "C" ::CDT_result *BLI_delaunay_2d_cdt_calc(const ::CDT_input *input,
in, output_type);
::CDT_result *output = static_cast<::CDT_result *>(MEM_mallocN(sizeof(*output), __func__));
- int nv = output->verts_len = static_cast<int>(res.vert.size());
- int ne = output->edges_len = static_cast<int>(res.edge.size());
- int nf = output->faces_len = static_cast<int>(res.face.size());
+ int nv = output->verts_len = res.vert.size();
+ int ne = output->edges_len = res.edge.size();
+ int nf = output->faces_len = res.face.size();
int tot_v_orig = 0;
int tot_e_orig = 0;
int tot_f_orig = 0;
int tot_f_lens = 0;
for (int v = 0; v < nv; ++v) {
- tot_v_orig += static_cast<int>(res.vert_orig[v].size());
+ tot_v_orig += res.vert_orig[v].size();
}
for (int e = 0; e < ne; ++e) {
- tot_e_orig += static_cast<int>(res.edge_orig[e].size());
+ tot_e_orig += res.edge_orig[e].size();
}
for (int f = 0; f < nf; ++f) {
- tot_f_orig += static_cast<int>(res.face_orig[f].size());
- tot_f_lens += static_cast<int>(res.face[f].size());
+ tot_f_orig += res.face_orig[f].size();
+ tot_f_lens += res.face[f].size();
}
output->vert_coords = static_cast<decltype(output->vert_coords)>(
@@ -2427,7 +2431,7 @@ extern "C" ::CDT_result *BLI_delaunay_2d_cdt_calc(const ::CDT_input *input,
int f_index = 0;
for (int f = 0; f < nf; ++f) {
output->faces_start_table[f] = f_index;
- int flen = static_cast<int>(res.face[f].size());
+ int flen = res.face[f].size();
output->faces_len_table[f] = flen;
for (int j = 0; j < flen; ++j) {
output->faces[f_index++] = res.face[f][j];
diff --git a/source/blender/blenlib/intern/mesh_boolean.cc b/source/blender/blenlib/intern/mesh_boolean.cc
index 0095ec95140..ff54ae128a9 100644
--- a/source/blender/blenlib/intern/mesh_boolean.cc
+++ b/source/blender/blenlib/intern/mesh_boolean.cc
@@ -235,11 +235,6 @@ class Patch {
tri_.append(t);
}
- const Vector<int> &tri() const
- {
- return tri_;
- }
-
int tot_tri() const
{
return tri_.size();
@@ -267,7 +262,7 @@ class Patch {
static std::ostream &operator<<(std::ostream &os, const Patch &patch)
{
- os << "Patch " << patch.tri();
+ os << "Patch " << patch.tris();
if (patch.cell_above != NO_INDEX) {
os << " cell_above=" << patch.cell_above;
}
@@ -351,6 +346,16 @@ class PatchesInfo {
return patch_.end();
}
+ Patch *begin()
+ {
+ return patch_.begin();
+ }
+
+ Patch *end()
+ {
+ return patch_.end();
+ }
+
void add_new_patch_patch_edge(int p1, int p2, Edge e)
{
pp_edge_.add_new(std::pair<int, int>(p1, p2), e);
@@ -363,7 +368,7 @@ class PatchesInfo {
}
};
-static bool apply_bool_op(int bool_optype, const Array<int> &winding);
+static bool apply_bool_op(BoolOpType bool_optype, const Array<int> &winding);
/* A Cell is a volume of 3-space, surrounded by patches.
* We will partition all 3-space into Cells.
@@ -374,8 +379,8 @@ class Cell {
Array<int> winding_;
int merged_to_{NO_INDEX};
bool winding_assigned_{false};
- /* flag_ will be true when this cell should be in the output volume. */
- bool flag_{false};
+ /* in_output_volume_ will be true when this cell should be in the output volume. */
+ bool in_output_volume_{false};
/* zero_volume_ will be true when this is a zero-volume cell (inside a stack of identical
* triangles). */
bool zero_volume_{false};
@@ -393,14 +398,14 @@ class Cell {
patches_.append_non_duplicates(p);
}
- const Vector<int> &patches() const
+ const Span<int> patches() const
{
- return patches_;
+ return Span<int>(patches_);
}
- const Array<int> &winding() const
+ const Span<int> winding() const
{
- return winding_;
+ return Span<int>(winding_);
}
void init_winding(int winding_len)
@@ -414,17 +419,20 @@ class Cell {
winding_assigned_ = true;
}
- void set_winding_and_flag(const Cell &from_cell, int shape, int delta, int bool_optype)
+ void set_winding_and_in_output_volume(const Cell &from_cell,
+ int shape,
+ int delta,
+ BoolOpType bool_optype)
{
std::copy(from_cell.winding().begin(), from_cell.winding().end(), winding_.begin());
winding_[shape] += delta;
winding_assigned_ = true;
- flag_ = apply_bool_op(bool_optype, winding_);
+ in_output_volume_ = apply_bool_op(bool_optype, winding_);
}
- bool flag() const
+ bool in_output_volume() const
{
- return flag_;
+ return in_output_volume_;
}
bool winding_assigned() const
@@ -458,7 +466,7 @@ static std::ostream &operator<<(std::ostream &os, const Cell &cell)
os << "Cell patches " << cell.patches();
if (cell.winding().size() > 0) {
os << " winding=" << cell.winding();
- os << " flag=" << cell.flag();
+ os << " in_output_volume=" << cell.in_output_volume();
}
os << " zv=" << cell.zero_volume();
return os;
@@ -511,7 +519,7 @@ class CellsInfo {
int add_cell()
{
int index = cell_.append_and_get_index(Cell());
- return static_cast<int>(index);
+ return index;
}
Cell &cell(int c)
@@ -544,6 +552,16 @@ class CellsInfo {
return cell_.end();
}
+ Cell *begin()
+ {
+ return cell_.begin();
+ }
+
+ Cell *end()
+ {
+ return cell_.end();
+ }
+
void init_windings(int winding_len)
{
for (Cell &cell : cell_) {
@@ -628,8 +646,7 @@ static void merge_cells(int merge_to, int merge_from, CellsInfo &cinfo, PatchesI
final_merge_to = merge_to_cell.merged_to();
merge_to_cell = cinfo.cell(final_merge_to);
}
- for (int p : pinfo.index_range()) {
- Patch &patch = pinfo.patch(p);
+ for (Patch &patch : pinfo) {
if (patch.cell_above == merge_from) {
patch.cell_above = final_merge_to;
}
@@ -860,7 +877,6 @@ static void sort_by_signed_triangle_index(Vector<int> &g,
{
Array<int> signed_g(g.size());
for (int i : g.index_range()) {
-
const Face &tri = g[i] == EXTRA_TRI_INDEX ? *extra_tri : *tm.face(g[i]);
bool rev;
find_flap_vert(tri, e, &rev);
@@ -890,7 +906,7 @@ static void sort_by_signed_triangle_index(Vector<int> &g,
static Array<int> sort_tris_around_edge(const IMesh &tm,
const TriMeshTopology &tmtopo,
const Edge e,
- const Span<int> &tris,
+ const Span<int> tris,
const int t0,
const Face *extra_tri)
{
@@ -921,7 +937,7 @@ static Array<int> sort_tris_around_edge(const IMesh &tm,
Vector<int> g2;
Vector<int> g3;
Vector<int> g4;
- Vector<int> *groups[] = {&g1, &g2, &g3, &g4};
+ std::array<Vector<int> *, 4> groups = {&g1, &g2, &g3, &g4};
const Face &triref = *tm.face(tris[0]);
for (int i : tris.index_range()) {
if (i == 0) {
@@ -1012,7 +1028,7 @@ static void find_cells_from_edge(const IMesh &tm,
Array<int> sorted_tris = sort_tris_around_edge(
tm, tmtopo, e, Span<int>(*edge_tris), (*edge_tris)[0], nullptr);
- int n_edge_tris = static_cast<int>(edge_tris->size());
+ int n_edge_tris = edge_tris->size();
Array<int> edge_patches(n_edge_tris);
for (int i = 0; i < n_edge_tris; ++i) {
edge_patches[i] = pinfo.tri_patch(sorted_tris[i]);
@@ -1308,6 +1324,7 @@ static int find_cell_for_point_near_edge(mpq3 p,
NO_INDEX,
{NO_INDEX, NO_INDEX, NO_INDEX},
{false, false, false});
+ BLI_assert(etris != nullptr);
Array<int> edge_tris(etris->size() + 1);
std::copy(etris->begin(), etris->end(), edge_tris.begin());
edge_tris[edge_tris.size() - 1] = EXTRA_TRI_INDEX;
@@ -1321,9 +1338,8 @@ static int find_cell_for_point_near_edge(mpq3 p,
int dummy_index = p_sorted_dummy - sorted_tris.begin();
int prev_tri = (dummy_index == 0) ? sorted_tris[sorted_tris.size() - 1] :
sorted_tris[dummy_index - 1];
- int next_tri = (dummy_index == static_cast<int>(sorted_tris.size() - 1)) ?
- sorted_tris[0] :
- sorted_tris[dummy_index + 1];
+ int next_tri = (dummy_index == sorted_tris.size() - 1) ? sorted_tris[0] :
+ sorted_tris[dummy_index + 1];
if (dbg_level > 0) {
std::cout << "prev tri to dummy = " << prev_tri << "; next tri to dummy = " << next_tri
<< "\n";
@@ -1414,7 +1430,7 @@ static int find_ambient_cell(const IMesh &tm,
Edge ehull;
mpq_class max_abs_slope = -1;
for (Edge e : edges) {
- const const Vert *v_other = (e.v0() == v_extreme) ? e.v1() : e.v0();
+ const Vert *v_other = (e.v0() == v_extreme) ? e.v1() : e.v0();
const mpq3 &co_other = v_other->co_exact;
mpq_class delta_x = co_other.x - extreme_x;
if (delta_x == 0) {
@@ -1467,7 +1483,7 @@ static Edge find_good_sorting_edge(const Vert *testp,
*/
const mpq3 &co_closest = closestp->co_exact;
const mpq3 &co_test = testp->co_exact;
- BLI_assert(!(co_test == co_closest));
+ BLI_assert(co_test != co_closest);
mpq3 abscissa = co_test - co_closest;
/* Find a non-zero-component axis of abscissa. */
int axis;
@@ -1935,14 +1951,14 @@ static void finish_patch_cell_graph(const IMesh &tm,
* triangle is part of.
* Also, as soon as the winding numbers for a cell are set, use bool_optype
* to decide whether that cell is included or excluded from the boolean output.
- * If included, the cell's flag will be set to true.
+ * If included, the cell's in_output_volume will be set to true.
*/
-static void propagate_windings_and_flag(PatchesInfo &pinfo,
- CellsInfo &cinfo,
- int c_ambient,
- bool_optype op,
- int nshapes,
- std::function<int(int)> shape_fn)
+static void propagate_windings_and_in_output_volume(PatchesInfo &pinfo,
+ CellsInfo &cinfo,
+ int c_ambient,
+ BoolOpType op,
+ int nshapes,
+ std::function<int(int)> shape_fn)
{
int dbg_level = 0;
if (dbg_level > 0) {
@@ -1978,7 +1994,7 @@ static void propagate_windings_and_flag(PatchesInfo &pinfo,
if (dbg_level > 1) {
std::cout << " representative tri " << t << ": in shape " << shape << "\n";
}
- cell_neighbor.set_winding_and_flag(cell, shape, winding_delta, op);
+ cell_neighbor.set_winding_and_in_output_volume(cell, shape, winding_delta, op);
if (dbg_level > 1) {
std::cout << " now cell_neighbor = " << cell_neighbor << "\n";
}
@@ -2003,12 +2019,12 @@ static void propagate_windings_and_flag(PatchesInfo &pinfo,
* Difference (first shape minus the rest): first winding number must be nonzero
* and the rest must have at least one zero winding number.
*/
-static bool apply_bool_op(int bool_optype, const Array<int> &winding)
+static bool apply_bool_op(BoolOpType bool_optype, const Array<int> &winding)
{
- int nw = static_cast<int>(winding.size());
+ int nw = winding.size();
BLI_assert(nw > 0);
switch (bool_optype) {
- case BOOLEAN_ISECT: {
+ case BoolOpType::Intersect: {
for (int i = 0; i < nw; ++i) {
if (winding[i] == 0) {
return false;
@@ -2016,7 +2032,7 @@ static bool apply_bool_op(int bool_optype, const Array<int> &winding)
}
return true;
}
- case BOOLEAN_UNION: {
+ case BoolOpType::Union: {
for (int i = 0; i < nw; ++i) {
if (winding[i] != 0) {
return true;
@@ -2024,7 +2040,7 @@ static bool apply_bool_op(int bool_optype, const Array<int> &winding)
}
return false;
}
- case BOOLEAN_DIFFERENCE: {
+ case BoolOpType::Difference: {
/* if nw > 2, make it shape 0 minus the union of the rest. */
if (winding[0] == 0) {
return false;
@@ -2044,11 +2060,11 @@ static bool apply_bool_op(int bool_optype, const Array<int> &winding)
}
}
-/* Special processing for extract_from_flag_diffs to handle
+/* Special processing for extract_from_in_output_volume_diffs to handle
* triangles that are part of stacks of geometrically identical
* triangles enclosing zero volume cells.
*/
-static void extract_zero_volume_cell_tris(Vector<const Face *> &out_tris,
+static void extract_zero_volume_cell_tris(Vector<const Face *> &r_tris,
const IMesh &tm_subdivided,
const PatchesInfo &pinfo,
const CellsInfo &cinfo,
@@ -2131,8 +2147,8 @@ static void extract_zero_volume_cell_tris(Vector<const Face *> &out_tris,
}
std::cout << "\n";
}
- if (above_stack_cell->flag() ^ below_stack_cell->flag()) {
- bool need_flipped_tri = above_stack_cell->flag();
+ if (above_stack_cell->in_output_volume() ^ below_stack_cell->in_output_volume()) {
+ bool need_flipped_tri = above_stack_cell->in_output_volume();
if (dbg_level > 0) {
std::cout << "need tri " << (need_flipped_tri ? "flipped" : "") << "\n";
}
@@ -2143,7 +2159,7 @@ static void extract_zero_volume_cell_tris(Vector<const Face *> &out_tris,
if (dbg_level > 0) {
std::cout << "using tri " << t_to_add << "\n";
}
- out_tris.append(tm_subdivided.face(t_to_add));
+ r_tris.append(tm_subdivided.face(t_to_add));
break;
}
}
@@ -2157,25 +2173,26 @@ static void extract_zero_volume_cell_tris(Vector<const Face *> &out_tris,
tri.is_intersect[2], tri.is_intersect[1], tri.is_intersect[0]};
const Face *flipped_f = arena->add_face(
flipped_vs, f->orig, flipped_e_origs, flipped_is_intersect);
- out_tris.append(flipped_f);
+ r_tris.append(flipped_f);
}
}
}
}
/* Extract the output mesh from tm_subdivided and return it as a new mesh.
- * The cells in cinfo must have cells-to-be-retained flagged.
- * We keep only triangles between flagged and unflagged cells.
- * We flip the normals of any triangle that has a flagged cell above
- * and an unflagged cell below.
+ * The cells in cinfo must have cells-to-be-retained with in_output_volume set.
+ * We keep only triangles between those in the output volume and those not in.
+ * We flip the normals of any triangle that has an in_output_volume cell above
+ * and a not-in_output_volume cell below.
* For all stacks of exact duplicate coplanar triangles, we want to
* include either one version of the triangle or none, depending on
- * whether the flags on either side of the stack are different or the same.
+ * whether the in_output_volume in_output_volumes on either side of the stack are
+ * different or the same.
*/
-static IMesh extract_from_flag_diffs(const IMesh &tm_subdivided,
- const PatchesInfo &pinfo,
- const CellsInfo &cinfo,
- IMeshArena *arena)
+static IMesh extract_from_in_output_volume_diffs(const IMesh &tm_subdivided,
+ const PatchesInfo &pinfo,
+ const CellsInfo &cinfo,
+ IMeshArena *arena)
{
constexpr int dbg_level = 0;
if (dbg_level > 0) {
@@ -2192,22 +2209,24 @@ static IMesh extract_from_flag_diffs(const IMesh &tm_subdivided,
if (dbg_level > 0) {
std::cout << "tri " << t << ": cell_above=" << patch.cell_above
<< " cell_below=" << patch.cell_below << "\n";
- std::cout << " flag_above=" << cell_above.flag() << " flag_below=" << cell_below.flag()
- << "\n";
+ std::cout << " in_output_volume_above=" << cell_above.in_output_volume()
+ << " in_output_volume_below=" << cell_below.in_output_volume() << "\n";
}
bool adjacent_zero_volume_cell = cell_above.zero_volume() || cell_below.zero_volume();
any_zero_volume_cell |= adjacent_zero_volume_cell;
- if (cell_above.flag() ^ cell_below.flag() && !adjacent_zero_volume_cell) {
- bool flip = cell_above.flag();
+ if (cell_above.in_output_volume() ^ cell_below.in_output_volume() &&
+ !adjacent_zero_volume_cell) {
+ bool flip = cell_above.in_output_volume();
if (dbg_level > 0) {
std::cout << "need tri " << t << " flip=" << flip << "\n";
}
const Face *f = tm_subdivided.face(t);
if (flip) {
const Face &tri = *f;
- Array<const Vert *> flipped_vs = {tri[0], tri[2], tri[1]};
- Array<int> flipped_e_origs = {tri.edge_orig[2], tri.edge_orig[1], tri.edge_orig[0]};
- Array<bool> flipped_is_intersect = {
+ std::array<const Vert *, 3> flipped_vs = {tri[0], tri[2], tri[1]};
+ std::array<int, 3> flipped_e_origs = {
+ tri.edge_orig[2], tri.edge_orig[1], tri.edge_orig[0]};
+ std::array<bool, 3> flipped_is_intersect = {
tri.is_intersect[2], tri.is_intersect[1], tri.is_intersect[0]};
const Face *flipped_f = arena->add_face(
flipped_vs, f->orig, flipped_e_origs, flipped_is_intersect);
@@ -2224,16 +2243,16 @@ static IMesh extract_from_flag_diffs(const IMesh &tm_subdivided,
return IMesh(out_tris);
}
-static const char *bool_optype_name(bool_optype op)
+static const char *bool_optype_name(BoolOpType op)
{
switch (op) {
- case BOOLEAN_NONE:
+ case BoolOpType::None:
return "none";
- case BOOLEAN_ISECT:
+ case BoolOpType::Intersect:
return "intersect";
- case BOOLEAN_UNION:
+ case BoolOpType::Union:
return "union";
- case BOOLEAN_DIFFERENCE:
+ case BoolOpType::Difference:
return "difference";
default:
return "<unknown>";
@@ -2335,7 +2354,7 @@ static bool point_is_inside_shape(const IMesh &tm,
* and return the mesh that is the boolean result.
*/
static IMesh gwn_boolean(const IMesh &tm,
- bool_optype op,
+ BoolOpType op,
int nshapes,
std::function<int(int)> shape_fn,
const PatchesInfo &pinfo,
@@ -2379,15 +2398,15 @@ static IMesh gwn_boolean(const IMesh &tm,
bool do_remove;
bool do_flip;
switch (op) {
- case BOOLEAN_ISECT:
+ case BoolOpType::Intersect:
do_remove = !inside;
do_flip = false;
break;
- case BOOLEAN_UNION:
+ case BoolOpType::Union:
do_remove = inside;
do_flip = false;
break;
- case BOOLEAN_DIFFERENCE:
+ case BoolOpType::Difference:
do_remove = (shape == 0) ? inside : !inside;
do_flip = (shape == 1);
break;
@@ -2453,7 +2472,7 @@ static Array<const Face *> triangulate_poly(const Face *f, IMeshArena *arena)
cdt_in.face = Array<Vector<int>>(1);
cdt_in.face[0].reserve(flen);
for (int i : f->index_range()) {
- cdt_in.face[0].append(static_cast<int>(i));
+ cdt_in.face[0].append(i);
}
/* Project poly along dominant axis of normal to get 2d coords. */
const mpq3 &poly_normal = f->plane.norm_exact;
@@ -2463,12 +2482,11 @@ static Array<const Face *> triangulate_poly(const Face *f, IMeshArena *arena)
* Yet another reversal happens if the poly normal in the dominant
* direction is opposite that of the positive dominant axis.
*/
- int iflen = static_cast<int>(flen);
bool rev1 = (axis == 1);
bool rev2 = poly_normal[axis] < 0;
bool rev = rev1 ^ rev2;
- for (int i = 0; i < iflen; ++i) {
- int ii = rev ? iflen - i - 1 : i;
+ for (int i = 0; i < flen; ++i) {
+ int ii = rev ? flen - i - 1 : i;
mpq2 &p2d = cdt_in.vert[ii];
int k = 0;
for (int j = 0; j < 3; ++j) {
@@ -2512,16 +2530,16 @@ static Array<const Face *> triangulate_poly(const Face *f, IMeshArena *arena)
}
/* Return an IMesh that is a triangulation of a mesh with general
- * polygonal faces, pm.
+ * polygonal faces, imesh.
* Added diagonals will be distinguishable by having edge original
* indices of NO_INDEX.
*/
-static IMesh triangulate_polymesh(IMesh &pm, IMeshArena *arena)
+static IMesh triangulate_polymesh(IMesh &imesh, IMeshArena *arena)
{
Vector<const Face *> face_tris;
constexpr int estimated_tris_per_face = 3;
- face_tris.reserve(estimated_tris_per_face * pm.face_size());
- for (const Face *f : pm.faces()) {
+ face_tris.reserve(estimated_tris_per_face * imesh.face_size());
+ for (const Face *f : imesh.faces()) {
/* Tesselate face f, following plan similar to BM_face_calc_tesselation. */
int flen = f->size();
if (flen == 3) {
@@ -2655,7 +2673,7 @@ static void init_face_merge_state(FaceMergeState *fms,
constexpr int dbg_level = 0;
/* Reserve enough faces and edges so that neither will have to resize. */
fms->face.reserve(tris.size() + 1);
- fms->edge.reserve((3 * tris.size()));
+ fms->edge.reserve(3 * tris.size());
fms->edge_map.reserve(3 * tris.size());
if (dbg_level > 0) {
std::cout << "\nINIT_FACE_MERGE_STATE\n";
@@ -2676,7 +2694,7 @@ static void init_face_merge_state(FaceMergeState *fms,
mf.vert.append(tri[1]);
mf.vert.append(tri[2]);
mf.orig = tri.orig;
- int f = static_cast<int>(fms->face.append_and_get_index(mf));
+ int f = fms->face.append_and_get_index(mf);
if (dbg_level > 1) {
std::cout << "appended MergeFace for tri at f = " << f << "\n";
}
@@ -2696,7 +2714,7 @@ static void init_face_merge_state(FaceMergeState *fms,
new_me.is_intersect = tri.is_intersect[i];
new_me.dissolvable = (new_me.orig == NO_INDEX && !new_me.is_intersect);
fms->edge.append(new_me);
- me_index = static_cast<int>(fms->edge.size()) - 1;
+ me_index = fms->edge.size() - 1;
fms->edge_map.add_new(canon_vs, me_index);
if (dbg_level > 1) {
std::cout << "added new me with me_index = " << me_index << "\n";
@@ -2764,8 +2782,8 @@ static bool dissolve_leaves_valid_bmesh(FaceMergeState *fms,
{
int a_edge_start = mf_left.edge.first_index_of_try(me_index);
BLI_assert(a_edge_start != -1);
- int alen = static_cast<int>(mf_left.vert.size());
- int blen = static_cast<int>(mf_right.vert.size());
+ int alen = mf_left.vert.size();
+ int blen = mf_right.vert.size();
int b_left_face = me.right_face;
bool ok = true;
/* Is there another edge, not me, in A's face, whose right face is B's left? */
@@ -2805,8 +2823,8 @@ static void splice_faces(
int a_edge_start = mf_left.edge.first_index_of_try(me_index);
int b_edge_start = mf_right.edge.first_index_of_try(me_index);
BLI_assert(a_edge_start != -1 && b_edge_start != -1);
- int alen = static_cast<int>(mf_left.vert.size());
- int blen = static_cast<int>(mf_right.vert.size());
+ int alen = mf_left.vert.size();
+ int blen = mf_right.vert.size();
Vector<const Vert *> splice_vert;
Vector<int> splice_edge;
splice_vert.reserve(alen + blen - 2);
@@ -2898,7 +2916,7 @@ static void do_dissolve(FaceMergeState *fms)
}
}
-/* Given that tris form a triangulation of a face or part of a face that was in pm_in,
+/* Given that tris form a triangulation of a face or part of a face that was in imesh_in,
* merge as many of the triangles together as possible, by dissolving the edges between them.
* We can only dissolve triangulation edges that don't overlap real input edges, and we
* can only dissolve them if doing so leaves the remaining faces able to create valid BMesh.
@@ -2909,7 +2927,7 @@ static void do_dissolve(FaceMergeState *fms)
*/
static Vector<const Face *> merge_tris_for_face(Vector<int> tris,
const IMesh &tm,
- const IMesh &pm_in,
+ const IMesh &imesh_in,
IMeshArena *arena)
{
constexpr int dbg_level = 0;
@@ -2933,7 +2951,7 @@ static Vector<const Face *> merge_tris_for_face(Vector<int> tris,
*/
const Face &tri1 = *tm.face(tris[0]);
const Face &tri2 = *tm.face(tris[1]);
- const Face *in_face = pm_in.face(tri1.orig);
+ const Face *in_face = imesh_in.face(tri1.orig);
if (in_face->size() == 4) {
std::pair<int, int> estarts = find_tris_common_edge(tri1, tri2);
if (estarts.first != -1 && tri1.edge_orig[estarts.first] == NO_INDEX) {
@@ -2989,31 +3007,31 @@ static Vector<const Face *> merge_tris_for_face(Vector<int> tris,
return ans;
}
-/* Return an array, paralleling pm_out.vert, saying which vertices can be dissolved.
+/* Return an array, paralleling imesh_out.vert, saying which vertices can be dissolved.
* A vertex v can be dissolved if (a) it is not an input vertex; (b) it has valence 2;
* and (c) if v's two neighboring vertices are u and w, then (u,v,w) forms a straight line.
* Return the number of dissolvable vertices in r_count_dissolve.
*/
-static Array<bool> find_dissolve_verts(IMesh &pm_out, int *r_count_dissolve)
+static Array<bool> find_dissolve_verts(IMesh &imesh_out, int *r_count_dissolve)
{
- pm_out.populate_vert();
- /* dissolve[i] will say whether pm_out.vert(i) can be dissolved. */
- Array<bool> dissolve(pm_out.vert_size());
- for (int v_index : pm_out.vert_index_range()) {
- const Vert &vert = *pm_out.vert(v_index);
+ imesh_out.populate_vert();
+ /* dissolve[i] will say whether imesh_out.vert(i) can be dissolved. */
+ Array<bool> dissolve(imesh_out.vert_size());
+ for (int v_index : imesh_out.vert_index_range()) {
+ const Vert &vert = *imesh_out.vert(v_index);
dissolve[v_index] = (vert.orig == NO_INDEX);
}
/* neighbors[i] will be a pair giving the up-to-two neighboring vertices
- * of the vertex v in position i of pm_out.vert.
+ * of the vertex v in position i of imesh_out.vert.
* If we encounter a third, then v will not be dissolvable.
*/
Array<std::pair<const Vert *, const Vert *>> neighbors(
- pm_out.vert_size(), std::pair<const Vert *, const Vert *>(nullptr, nullptr));
- for (int f : pm_out.face_index_range()) {
- const Face &face = *pm_out.face(f);
+ imesh_out.vert_size(), std::pair<const Vert *, const Vert *>(nullptr, nullptr));
+ for (int f : imesh_out.face_index_range()) {
+ const Face &face = *imesh_out.face(f);
for (int i : face.index_range()) {
const Vert *v = face[i];
- int v_index = pm_out.lookup_vert(v);
+ int v_index = imesh_out.lookup_vert(v);
BLI_assert(v_index != NO_INDEX);
if (dissolve[v_index]) {
const Vert *n1 = face[face.next_pos(i)];
@@ -3035,7 +3053,7 @@ static Array<bool> find_dissolve_verts(IMesh &pm_out, int *r_count_dissolve)
}
}
int count = 0;
- for (int v_out : pm_out.vert_index_range()) {
+ for (int v_out : imesh_out.vert_index_range()) {
if (dissolve[v_out]) {
dissolve[v_out] = false; /* Will set back to true if final condition is satisfied. */
const std::pair<const Vert *, const Vert *> &nbrs = neighbors[v_out];
@@ -3043,7 +3061,7 @@ static Array<bool> find_dissolve_verts(IMesh &pm_out, int *r_count_dissolve)
BLI_assert(nbrs.second != nullptr);
const mpq3 &co1 = nbrs.first->co_exact;
const mpq3 &co2 = nbrs.second->co_exact;
- const mpq3 &co = pm_out.vert(v_out)->co_exact;
+ const mpq3 &co = imesh_out.vert(v_out)->co_exact;
mpq3 dir1 = co - co1;
mpq3 dir2 = co2 - co;
mpq3 cross = mpq3::cross(dir1, dir2);
@@ -3060,20 +3078,20 @@ static Array<bool> find_dissolve_verts(IMesh &pm_out, int *r_count_dissolve)
return dissolve;
}
-/* The dissolve array parallels the pm.vert array. Wherever it is true,
+/* The dissolve array parallels the imesh.vert array. Wherever it is true,
* remove the corresponding vertex from the vertices in the faces of
- * pm.faces to account for the close-up of the gaps in pm.vert.
+ * imesh.faces to account for the close-up of the gaps in imesh.vert.
*/
-static void dissolve_verts(IMesh *pm, const Array<bool> dissolve, IMeshArena *arena)
+static void dissolve_verts(IMesh *imesh, const Array<bool> dissolve, IMeshArena *arena)
{
constexpr int inline_face_size = 100;
Vector<bool, inline_face_size> face_pos_erase;
- for (int f : pm->face_index_range()) {
- const Face &face = *pm->face(f);
+ for (int f : imesh->face_index_range()) {
+ const Face &face = *imesh->face(f);
face_pos_erase.clear();
int num_erase = 0;
for (const Vert *v : face) {
- int v_index = pm->lookup_vert(v);
+ int v_index = imesh->lookup_vert(v);
BLI_assert(v_index != NO_INDEX);
if (dissolve[v_index]) {
face_pos_erase.append(true);
@@ -3084,10 +3102,10 @@ static void dissolve_verts(IMesh *pm, const Array<bool> dissolve, IMeshArena *ar
}
}
if (num_erase > 0) {
- pm->erase_face_positions(f, face_pos_erase, arena);
+ imesh->erase_face_positions(f, face_pos_erase, arena);
}
}
- pm->set_dirty_verts();
+ imesh->set_dirty_verts();
}
/* The main boolean function operates on a triangle IMesh and produces a
@@ -3101,7 +3119,7 @@ static void dissolve_verts(IMesh *pm, const Array<bool> dissolve, IMeshArena *ar
* or have several disconnected boundaries (e.g., faces with holes).
*/
static IMesh polymesh_from_trimesh_with_dissolve(const IMesh &tm_out,
- const IMesh &pm_in,
+ const IMesh &imesh_in,
IMeshArena *arena)
{
const int dbg_level = 0;
@@ -3112,7 +3130,7 @@ static IMesh polymesh_from_trimesh_with_dissolve(const IMesh &tm_out,
* face_output_tris[f] will be indices of triangles in tm_out
* that have f as their original face.
*/
- int tot_in_face = pm_in.face_size();
+ int tot_in_face = imesh_in.face_size();
Array<Vector<int>> face_output_tris(tot_in_face);
for (int t : tm_out.face_index_range()) {
const Face &tri = *tm_out.face(t);
@@ -3132,7 +3150,7 @@ static IMesh polymesh_from_trimesh_with_dissolve(const IMesh &tm_out,
*/
Array<Vector<const Face *>> face_output_face(tot_in_face);
int tot_out_face = 0;
- for (int in_f : pm_in.face_index_range()) {
+ for (int in_f : imesh_in.face_index_range()) {
if (dbg_level > 1) {
std::cout << "merge tris for face " << in_f << "\n";
}
@@ -3140,33 +3158,33 @@ static IMesh polymesh_from_trimesh_with_dissolve(const IMesh &tm_out,
if (num_out_tris_for_face == 0) {
continue;
}
- face_output_face[in_f] = merge_tris_for_face(face_output_tris[in_f], tm_out, pm_in, arena);
+ face_output_face[in_f] = merge_tris_for_face(face_output_tris[in_f], tm_out, imesh_in, arena);
tot_out_face += face_output_face[in_f].size();
}
Array<const Face *> face(tot_out_face);
int out_f_index = 0;
- for (int in_f : pm_in.face_index_range()) {
+ for (int in_f : imesh_in.face_index_range()) {
const Vector<const Face *> &f_faces = face_output_face[in_f];
if (f_faces.size() > 0) {
std::copy(f_faces.begin(), f_faces.end(), &face[out_f_index]);
out_f_index += f_faces.size();
}
}
- IMesh pm_out(face);
+ IMesh imesh_out(face);
/* Dissolve vertices that were (a) not original; and (b) now have valence 2 and
* are between two other vertices that are exactly in line with them.
* These were created because of triangulation edges that have been dissolved.
*/
int count_dissolve;
- Array<bool> v_dissolve = find_dissolve_verts(pm_out, &count_dissolve);
+ Array<bool> v_dissolve = find_dissolve_verts(imesh_out, &count_dissolve);
if (count_dissolve > 0) {
- dissolve_verts(&pm_out, v_dissolve, arena);
+ dissolve_verts(&imesh_out, v_dissolve, arena);
}
if (dbg_level > 1) {
- write_obj_mesh(pm_out, "boolean_post_dissolve");
+ write_obj_mesh(imesh_out, "boolean_post_dissolve");
}
- return pm_out;
+ return imesh_out;
}
/*
@@ -3176,7 +3194,7 @@ static IMesh polymesh_from_trimesh_with_dissolve(const IMesh &tm_out,
* a number in the range 0 to nshapes-1, to say which shape that triangle is in.
*/
IMesh boolean_trimesh(IMesh &tm_in,
- bool_optype op,
+ BoolOpType op,
int nshapes,
std::function<int(int)> shape_fn,
bool use_self,
@@ -3207,7 +3225,7 @@ IMesh boolean_trimesh(IMesh &tm_in,
std::cout << "\nboolean_tm_input after intersection:\n" << tm_si;
}
/* It is possible for tm_si to be empty if all the input triangles are bogus/degenerate. */
- if (tm_si.face_size() == 0 || op == BOOLEAN_NONE) {
+ if (tm_si.face_size() == 0 || op == BoolOpType::None) {
return tm_si;
}
auto si_shape_fn = [shape_fn, tm_si](int t) { return shape_fn(tm_si.face(t)->orig); };
@@ -3239,8 +3257,8 @@ IMesh boolean_trimesh(IMesh &tm_in,
std::cout << "Could not find an ambient cell; input not valid?\n";
return IMesh(tm_si);
}
- propagate_windings_and_flag(pinfo, cinfo, c_ambient, op, nshapes, si_shape_fn);
- tm_out = extract_from_flag_diffs(tm_si, pinfo, cinfo, arena);
+ propagate_windings_and_in_output_volume(pinfo, cinfo, c_ambient, op, nshapes, si_shape_fn);
+ tm_out = extract_from_in_output_volume_diffs(tm_si, pinfo, cinfo, arena);
if (dbg_level > 0) {
/* Check if output is PWN. */
TriMeshTopology tm_out_topo(tm_out);
@@ -3256,30 +3274,30 @@ IMesh boolean_trimesh(IMesh &tm_in,
return tm_out;
}
-static void dump_test_spec(IMesh &pm)
+static void dump_test_spec(IMesh &imesh)
{
- std::cout << "test spec = " << pm.vert_size() << " " << pm.face_size() << "\n";
- for (const Vert *v : pm.vertices()) {
+ std::cout << "test spec = " << imesh.vert_size() << " " << imesh.face_size() << "\n";
+ for (const Vert *v : imesh.vertices()) {
std::cout << v->co_exact[0] << " " << v->co_exact[1] << " " << v->co_exact[2] << " # "
<< v->co[0] << " " << v->co[1] << " " << v->co[2] << "\n";
}
- for (const Face *f : pm.faces()) {
+ for (const Face *f : imesh.faces()) {
for (const Vert *fv : *f) {
- std::cout << pm.lookup_vert(fv) << " ";
+ std::cout << imesh.lookup_vert(fv) << " ";
}
std::cout << "\n";
}
}
-/* Do the boolean operation op on the polygon mesh pm_in.
+/* Do the boolean operation op on the polygon mesh imesh_in.
* See the header file for a complete description.
*/
-IMesh boolean_mesh(IMesh &pm,
- bool_optype op,
+IMesh boolean_mesh(IMesh &imesh,
+ BoolOpType op,
int nshapes,
std::function<int(int)> shape_fn,
bool use_self,
- IMesh *pm_triangulated,
+ IMesh *imesh_triangulated,
IMeshArena *arena)
{
constexpr int dbg_level = 0;
@@ -3288,17 +3306,17 @@ IMesh boolean_mesh(IMesh &pm,
<< nshapes << " operand" << (nshapes == 1 ? "" : "s")
<< " op=" << bool_optype_name(op) << "\n";
if (dbg_level > 1) {
- write_obj_mesh(pm, "boolean_mesh_in");
- std::cout << pm;
+ write_obj_mesh(imesh, "boolean_mesh_in");
+ std::cout << imesh;
if (dbg_level > 2) {
- dump_test_spec(pm);
+ dump_test_spec(imesh);
}
}
}
- IMesh *tm_in = pm_triangulated;
+ IMesh *tm_in = imesh_triangulated;
IMesh our_triangulation;
if (tm_in == nullptr) {
- our_triangulation = triangulate_polymesh(pm, arena);
+ our_triangulation = triangulate_polymesh(imesh, arena);
tm_in = &our_triangulation;
}
IMesh tm_out = boolean_trimesh(*tm_in, op, nshapes, shape_fn, use_self, arena);
@@ -3306,7 +3324,7 @@ IMesh boolean_mesh(IMesh &pm,
std::cout << "bool_trimesh_output:\n" << tm_out;
write_obj_mesh(tm_out, "bool_trimesh_output");
}
- IMesh ans = polymesh_from_trimesh_with_dissolve(tm_out, pm, arena);
+ IMesh ans = polymesh_from_trimesh_with_dissolve(tm_out, imesh, arena);
if (dbg_level > 0) {
std::cout << "boolean_mesh output:\n" << ans;
}
diff --git a/source/blender/blenlib/intern/mesh_intersect.cc b/source/blender/blenlib/intern/mesh_intersect.cc
index 38b17b7100e..32b423c9f2c 100644
--- a/source/blender/blenlib/intern/mesh_intersect.cc
+++ b/source/blender/blenlib/intern/mesh_intersect.cc
@@ -61,36 +61,6 @@ Vert::Vert(const mpq3 &mco, const double3 &dco, int id, int orig)
{
}
-Vert::Vert(const Vert &other)
- : co_exact(other.co_exact), co(other.co), id(other.id), orig(other.orig)
-{
-}
-
-Vert::Vert(Vert &&other) noexcept
- : co_exact(std::move(other.co_exact)), co(std::move(other.co)), id(other.id), orig(other.orig)
-{
-}
-
-Vert &Vert::operator=(const Vert &other)
-{
- if (this != &other) {
- this->co_exact = other.co_exact;
- this->co = other.co;
- this->id = other.id;
- this->orig = other.orig;
- }
- return *this;
-}
-
-Vert &Vert::operator=(Vert &&other) noexcept
-{
- this->co_exact = std::move(other.co_exact);
- this->co = std::move(other.co);
- this->id = other.id;
- this->orig = other.orig;
- return *this;
-}
-
bool Vert::operator==(const Vert &other) const
{
return this->co_exact == other.co_exact;
@@ -217,50 +187,6 @@ Face::Face(Span<const Vert *> verts, int id, int orig) : vert(verts), id(id), or
plane = Plane(normal, d);
}
-Face::Face(const Face &other)
- : vert(other.vert),
- edge_orig(other.edge_orig),
- is_intersect(other.is_intersect),
- plane(other.plane),
- id(other.id),
- orig(other.orig)
-{
-}
-
-Face::Face(Face &&other) noexcept
- : vert(std::move(other.vert)),
- edge_orig(std::move(other.edge_orig)),
- is_intersect(std::move(other.is_intersect)),
- plane(std::move(other.plane)),
- id(other.id),
- orig(other.orig)
-{
-}
-
-Face &Face::operator=(const Face &other)
-{
- if (this != &other) {
- this->vert = other.vert;
- this->edge_orig = other.edge_orig;
- this->is_intersect = other.is_intersect;
- this->plane = other.plane;
- this->id = other.id;
- this->orig = other.orig;
- }
- return *this;
-}
-
-Face &Face::operator=(Face &&other) noexcept
-{
- this->vert = std::move(other.vert);
- this->edge_orig = std::move(other.edge_orig);
- this->is_intersect = std::move(other.is_intersect);
- this->plane = std::move(other.plane);
- this->id = other.id;
- this->orig = other.orig;
- return *this;
-}
-
bool Face::operator==(const Face &other) const
{
if (this->size() != other.size()) {
@@ -338,7 +264,13 @@ std::ostream &operator<<(std::ostream &os, const Face *f)
* exist. I.e., it dedups the vertices.
*/
+/* Uncomment the following to try using a spinlock instead of
+ * a mutex in the arena allocation routines.
+ * Initial tests showed that it doesn't seem to help very much,
+ * if at all, to use a spinlock.
+ */
// #define USE_SPINLOCK
+
class IMeshArena::IMeshArenaImpl {
/* Don't use Vert itself as key since resizing may move
@@ -696,7 +628,7 @@ void IMesh::populate_vert(int max_verts)
void 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 = static_cast<int>(cur_f->size());
+ int cur_len = cur_f->size();
int num_to_erase = 0;
for (int i : cur_f->index_range()) {
if (face_pos_erase[i]) {
@@ -2280,7 +2212,7 @@ static IMesh extract_subdivided_tri(const CDT_data &cd,
{
const CDT_result<mpq_class> &cdt_out = cd.cdt_out;
int t_in_cdt = -1;
- for (int i = 0; i < static_cast<int>(cd.input_face.size()); ++i) {
+ for (int i = 0; i < cd.input_face.size(); ++i) {
if (cd.input_face[i] == t) {
t_in_cdt = i;
}
@@ -2374,13 +2306,13 @@ class TriOverlaps {
std::cout << "TriOverlaps construction\n";
}
/* Tree type is 8 => octtree; axis = 6 => using XYZ axes only. */
- tree_ = BLI_bvhtree_new(static_cast<int>(tm.face_size()), FLT_EPSILON, 8, 6);
+ tree_ = BLI_bvhtree_new(tm.face_size(), FLT_EPSILON, 8, 6);
/* In the common case of a binary boolean and no self intersection in
* each shape, we will use two trees and simple bounding box overlap.
*/
bool two_trees_no_self = nshapes == 2 && !use_self;
if (two_trees_no_self) {
- tree_b_ = BLI_bvhtree_new(static_cast<int>(tm.face_size()), FLT_EPSILON, 8, 6);
+ tree_b_ = BLI_bvhtree_new(tm.face_size(), FLT_EPSILON, 8, 6);
}
float bbpts[6];
for (int t : tm.face_index_range()) {
@@ -2390,15 +2322,15 @@ class TriOverlaps {
int shape = shape_fn(tm.face(t)->orig);
if (two_trees_no_self) {
if (shape == 0) {
- BLI_bvhtree_insert(tree_, static_cast<int>(t), bbpts, 2);
+ BLI_bvhtree_insert(tree_, t, bbpts, 2);
}
else if (shape == 1) {
- BLI_bvhtree_insert(tree_b_, static_cast<int>(t), bbpts, 2);
+ BLI_bvhtree_insert(tree_b_, t, bbpts, 2);
}
}
else {
if (shape != -1) {
- BLI_bvhtree_insert(tree_, static_cast<int>(t), bbpts, 2);
+ BLI_bvhtree_insert(tree_, t, bbpts, 2);
}
}
}
@@ -2494,6 +2426,17 @@ struct OverlapIttsData {
}
};
+/* Return a std::pair containing a and b in canonical order:
+ * With a <= b.
+ */
+static std::pair<int, int> canon_int_pair(int a, int b)
+{
+ if (a > b) {
+ std::swap(a, b);
+ }
+ return std::pair<int, int>(a, b);
+}
+
static void calc_overlap_itts_range_func(void *__restrict userdata,
const int iter,
const TaskParallelTLS *__restrict UNUSED(tls))
@@ -2530,15 +2473,10 @@ static void calc_overlap_itts(Map<std::pair<int, int>, ITT_value> &itt_map,
* This means we won't have to protect the itt_map.add_overwrite function with a lock.
*/
for (const BVHTreeOverlap &olap : ov.overlap()) {
- int a = olap.indexA;
- int b = olap.indexB;
- if (a >= b) {
- std::swap(a, b);
- }
- std::pair<int, int> key(a, b);
+ std::pair<int, int> key = canon_int_pair(olap.indexA, olap.indexB);
if (!itt_map.contains(key)) {
- int ca = clinfo.tri_cluster(a);
- int cb = clinfo.tri_cluster(b);
+ int ca = clinfo.tri_cluster(key.first);
+ int cb = clinfo.tri_cluster(key.second);
if (ca == NO_INDEX || ca != cb) {
itt_map.add_new(key, ITT_value());
data.intersect_pairs.append(key);
@@ -2606,12 +2544,7 @@ static void calc_subdivided_tri_range_func(void *__restrict userdata,
Vector<ITT_value, inline_capacity> itts(otr.len);
for (int j = otr.overlap_start; j < otr.overlap_start + otr.len; ++j) {
int t_other = data->overlap[j].indexB;
- int a = t;
- int b = t_other;
- if (a >= b) {
- std::swap(a, b);
- }
- std::pair<int, int> key(a, b);
+ std::pair<int, int> key = canon_int_pair(t, t_other);
ITT_value itt;
if (data->itt_map.contains(key)) {
itt = data->itt_map.lookup(key);
@@ -2740,12 +2673,7 @@ static CDT_data calc_cluster_subdivided(const CoplanarClusterInfo &clinfo,
if (dbg_level > 0) {
std::cout << "use intersect(" << t << "," << t_other << "\n";
}
- int a = t;
- int b = t_other;
- if (a >= b) {
- std::swap(a, b);
- }
- std::pair<int, int> key(a, b);
+ std::pair<int, int> key = canon_int_pair(t, t_other);
if (itt_map.contains(key)) {
ITT_value itt = itt_map.lookup(key);
if (itt.kind != INONE && itt.kind != ICOPLANAR) {
@@ -2926,7 +2854,7 @@ static IMesh remove_degenerate_tris(const IMesh &tm_in)
IMesh trimesh_self_intersect(const IMesh &tm_in, IMeshArena *arena)
{
return trimesh_nary_intersect(
- tm_in, 1, [](int) { return 0; }, true, arena);
+ tm_in, 1, [](int UNUSED(t)) { return 0; }, true, arena);
}
IMesh trimesh_nary_intersect(const IMesh &tm_in,
@@ -2973,9 +2901,9 @@ IMesh trimesh_nary_intersect(const IMesh &tm_in,
}
# ifdef PERFDEBUG
perfdata_init();
- doperfmax(0, static_cast<int>(tm_in.face_size()));
- doperfmax(1, static_cast<int>(clinfo.tot_cluster()));
- doperfmax(2, static_cast<int>(tri_ov.overlap().size()));
+ doperfmax(0, tm_in.face_size());
+ doperfmax(1, clinfo.tot_cluster());
+ doperfmax(2, tri_ov.overlap().size());
# endif
/* itt_map((a,b)) will hold the intersection value resulting from intersecting
* triangles with indices a and b, where a < b.
diff --git a/source/blender/blenlib/tests/BLI_mesh_boolean_test.cc b/source/blender/blenlib/tests/BLI_mesh_boolean_test.cc
index 397a86d98c3..79534c13124 100644
--- a/source/blender/blenlib/tests/BLI_mesh_boolean_test.cc
+++ b/source/blender/blenlib/tests/BLI_mesh_boolean_test.cc
@@ -15,7 +15,7 @@
#include "BLI_mpq3.hh"
#include "BLI_vector.hh"
-namespace blender::meshintersect {
+namespace blender::meshintersect::tests {
constexpr bool DO_OBJ = false;
@@ -103,12 +103,16 @@ class IMeshBuilder {
}
};
+static int all_shape_zero(int UNUSED(t))
+{
+ return 0;
+}
+
TEST(boolean_trimesh, Empty)
{
IMeshArena arena;
IMesh in;
- IMesh out = boolean_trimesh(
- in, BOOLEAN_NONE, 1, [](int) { return 0; }, true, &arena);
+ IMesh out = boolean_trimesh(in, BoolOpType::None, 1, all_shape_zero, true, &arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 0);
EXPECT_EQ(out.face_size(), 0);
@@ -136,8 +140,7 @@ TEST(boolean_trimesh, TetTetTrimesh)
)";
IMeshBuilder mb(spec);
- IMesh out = boolean_trimesh(
- mb.imesh, BOOLEAN_NONE, 1, [](int) { return 0; }, true, &mb.arena);
+ IMesh out = boolean_trimesh(mb.imesh, BoolOpType::None, 1, all_shape_zero, true, &mb.arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 11);
EXPECT_EQ(out.face_size(), 20);
@@ -146,8 +149,7 @@ TEST(boolean_trimesh, TetTetTrimesh)
}
IMeshBuilder mb2(spec);
- IMesh out2 = boolean_trimesh(
- mb2.imesh, BOOLEAN_UNION, 1, [](int) { return 0; }, true, &mb2.arena);
+ IMesh out2 = boolean_trimesh(mb2.imesh, BoolOpType::Union, 1, all_shape_zero, true, &mb2.arena);
out2.populate_vert();
EXPECT_EQ(out2.vert_size(), 10);
EXPECT_EQ(out2.face_size(), 16);
@@ -157,7 +159,7 @@ TEST(boolean_trimesh, TetTetTrimesh)
IMeshBuilder mb3(spec);
IMesh out3 = boolean_trimesh(
- mb3.imesh, BOOLEAN_UNION, 2, [](int t) { return t < 4 ? 0 : 1; }, false, &mb3.arena);
+ mb3.imesh, BoolOpType::Union, 2, [](int t) { return t < 4 ? 0 : 1; }, false, &mb3.arena);
out3.populate_vert();
EXPECT_EQ(out3.vert_size(), 10);
EXPECT_EQ(out3.face_size(), 16);
@@ -167,7 +169,7 @@ TEST(boolean_trimesh, TetTetTrimesh)
IMeshBuilder mb4(spec);
IMesh out4 = boolean_trimesh(
- mb4.imesh, BOOLEAN_UNION, 2, [](int t) { return t < 4 ? 0 : 1; }, true, &mb4.arena);
+ mb4.imesh, BoolOpType::Union, 2, [](int t) { return t < 4 ? 0 : 1; }, true, &mb4.arena);
out4.populate_vert();
EXPECT_EQ(out4.vert_size(), 10);
EXPECT_EQ(out4.face_size(), 16);
@@ -177,7 +179,7 @@ TEST(boolean_trimesh, TetTetTrimesh)
IMeshBuilder mb5(spec);
IMesh out5 = boolean_trimesh(
- mb5.imesh, BOOLEAN_ISECT, 2, [](int t) { return t < 4 ? 0 : 1; }, false, &mb5.arena);
+ mb5.imesh, BoolOpType::Intersect, 2, [](int t) { return t < 4 ? 0 : 1; }, false, &mb5.arena);
out5.populate_vert();
EXPECT_EQ(out5.vert_size(), 4);
EXPECT_EQ(out5.face_size(), 4);
@@ -187,7 +189,12 @@ TEST(boolean_trimesh, TetTetTrimesh)
IMeshBuilder mb6(spec);
IMesh out6 = boolean_trimesh(
- mb6.imesh, BOOLEAN_DIFFERENCE, 2, [](int t) { return t < 4 ? 0 : 1; }, false, &mb6.arena);
+ mb6.imesh,
+ BoolOpType::Difference,
+ 2,
+ [](int t) { return t < 4 ? 0 : 1; },
+ false,
+ &mb6.arena);
out6.populate_vert();
EXPECT_EQ(out6.vert_size(), 6);
EXPECT_EQ(out6.face_size(), 8);
@@ -197,7 +204,12 @@ TEST(boolean_trimesh, TetTetTrimesh)
IMeshBuilder mb7(spec);
IMesh out7 = boolean_trimesh(
- mb7.imesh, BOOLEAN_DIFFERENCE, 2, [](int t) { return t < 4 ? 1 : 0; }, false, &mb7.arena);
+ mb7.imesh,
+ BoolOpType::Difference,
+ 2,
+ [](int t) { return t < 4 ? 1 : 0; },
+ false,
+ &mb7.arena);
out7.populate_vert();
EXPECT_EQ(out7.vert_size(), 8);
EXPECT_EQ(out7.face_size(), 12);
@@ -228,8 +240,7 @@ TEST(boolean_trimesh, TetTet2Trimesh)
)";
IMeshBuilder mb(spec);
- IMesh out = boolean_trimesh(
- mb.imesh, BOOLEAN_UNION, 1, [](int) { return 0; }, true, &mb.arena);
+ IMesh out = boolean_trimesh(mb.imesh, BoolOpType::Union, 1, all_shape_zero, true, &mb.arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 10);
EXPECT_EQ(out.face_size(), 16);
@@ -272,8 +283,7 @@ TEST(boolean_trimesh, CubeTetTrimesh)
)";
IMeshBuilder mb(spec);
- IMesh out = boolean_trimesh(
- mb.imesh, BOOLEAN_UNION, 1, [](int) { return 0; }, true, &mb.arena);
+ IMesh out = boolean_trimesh(mb.imesh, BoolOpType::Union, 1, all_shape_zero, true, &mb.arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 14);
EXPECT_EQ(out.face_size(), 24);
@@ -305,7 +315,7 @@ TEST(boolean_trimesh, BinaryTetTetTrimesh)
IMeshBuilder mb(spec);
IMesh out = boolean_trimesh(
- mb.imesh, BOOLEAN_ISECT, 2, [](int t) { return t < 4 ? 0 : 1; }, false, &mb.arena);
+ mb.imesh, BoolOpType::Intersect, 2, [](int t) { return t < 4 ? 0 : 1; }, false, &mb.arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 4);
EXPECT_EQ(out.face_size(), 4);
@@ -336,8 +346,7 @@ TEST(boolean_trimesh, TetTetCoplanarTrimesh)
)";
IMeshBuilder mb(spec);
- IMesh out = boolean_trimesh(
- mb.imesh, BOOLEAN_UNION, 1, [](int) { return 0; }, true, &mb.arena);
+ IMesh out = boolean_trimesh(mb.imesh, BoolOpType::Union, 1, all_shape_zero, true, &mb.arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 5);
EXPECT_EQ(out.face_size(), 6);
@@ -368,8 +377,7 @@ TEST(boolean_trimesh, TetInsideTetTrimesh)
)";
IMeshBuilder mb(spec);
- IMesh out = boolean_trimesh(
- mb.imesh, BOOLEAN_UNION, 1, [](int) { return 0; }, true, &mb.arena);
+ IMesh out = boolean_trimesh(mb.imesh, BoolOpType::Union, 1, all_shape_zero, true, &mb.arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 4);
EXPECT_EQ(out.face_size(), 4);
@@ -400,8 +408,7 @@ TEST(boolean_trimesh, TetBesideTetTrimesh)
)";
IMeshBuilder mb(spec);
- IMesh out = boolean_trimesh(
- mb.imesh, BOOLEAN_UNION, 1, [](int) { return 0; }, true, &mb.arena);
+ IMesh out = boolean_trimesh(mb.imesh, BoolOpType::Union, 1, all_shape_zero, true, &mb.arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 8);
EXPECT_EQ(out.face_size(), 8);
@@ -437,7 +444,7 @@ TEST(boolean_trimesh, DegenerateTris)
IMeshBuilder mb(spec);
IMesh out = boolean_trimesh(
- mb.imesh, BOOLEAN_ISECT, 2, [](int t) { return t < 5 ? 0 : 1; }, false, &mb.arena);
+ mb.imesh, BoolOpType::Intersect, 2, [](int t) { return t < 5 ? 0 : 1; }, false, &mb.arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 4);
EXPECT_EQ(out.face_size(), 4);
@@ -469,7 +476,7 @@ TEST(boolean_polymesh, TetTet)
IMeshBuilder mb(spec);
IMesh out = boolean_mesh(
- mb.imesh, BOOLEAN_NONE, 1, [](int) { return 0; }, true, nullptr, &mb.arena);
+ mb.imesh, BoolOpType::None, 1, all_shape_zero, true, nullptr, &mb.arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 11);
EXPECT_EQ(out.face_size(), 13);
@@ -479,7 +486,13 @@ TEST(boolean_polymesh, TetTet)
IMeshBuilder mb2(spec);
IMesh out2 = boolean_mesh(
- mb2.imesh, BOOLEAN_NONE, 2, [](int t) { return t < 4 ? 0 : 1; }, false, nullptr, &mb2.arena);
+ mb2.imesh,
+ BoolOpType::None,
+ 2,
+ [](int t) { return t < 4 ? 0 : 1; },
+ false,
+ nullptr,
+ &mb2.arena);
out2.populate_vert();
EXPECT_EQ(out2.vert_size(), 11);
EXPECT_EQ(out2.face_size(), 13);
@@ -526,7 +539,7 @@ TEST(boolean_polymesh, CubeCube)
write_obj_mesh(mb.imesh, "cube_cube_in");
}
IMesh out = boolean_mesh(
- mb.imesh, BOOLEAN_UNION, 1, [](int UNUSED(t)) { return 0; }, true, nullptr, &mb.arena);
+ mb.imesh, BoolOpType::Union, 1, all_shape_zero, true, nullptr, &mb.arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 20);
EXPECT_EQ(out.face_size(), 12);
@@ -536,7 +549,13 @@ TEST(boolean_polymesh, CubeCube)
IMeshBuilder mb2(spec);
IMesh out2 = boolean_mesh(
- mb2.imesh, BOOLEAN_NONE, 2, [](int t) { return t < 6 ? 0 : 1; }, false, nullptr, &mb2.arena);
+ mb2.imesh,
+ BoolOpType::None,
+ 2,
+ [](int t) { return t < 6 ? 0 : 1; },
+ false,
+ nullptr,
+ &mb2.arena);
out2.populate_vert();
EXPECT_EQ(out2.vert_size(), 22);
EXPECT_EQ(out2.face_size(), 18);
@@ -577,7 +596,7 @@ TEST(boolean_polymesh, CubeCone)
IMeshBuilder mb(spec);
IMesh out = boolean_mesh(
- mb.imesh, BOOLEAN_UNION, 1, [](int UNUSED(t)) { return 0; }, true, nullptr, &mb.arena);
+ mb.imesh, BoolOpType::Union, 1, all_shape_zero, true, nullptr, &mb.arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 14);
EXPECT_EQ(out.face_size(), 12);
@@ -621,7 +640,13 @@ TEST(boolean_polymesh, CubeCubeCoplanar)
IMeshBuilder mb(spec);
IMesh out = boolean_mesh(
- mb.imesh, BOOLEAN_UNION, 2, [](int t) { return t < 6 ? 0 : 1; }, false, nullptr, &mb.arena);
+ mb.imesh,
+ BoolOpType::Union,
+ 2,
+ [](int t) { return t < 6 ? 0 : 1; },
+ false,
+ nullptr,
+ &mb.arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 16);
EXPECT_EQ(out.face_size(), 12);
@@ -654,7 +679,7 @@ TEST(boolean_polymesh, TetTeTCoplanarDiff)
IMeshBuilder mb(spec);
IMesh out = boolean_mesh(
mb.imesh,
- BOOLEAN_DIFFERENCE,
+ BoolOpType::Difference,
2,
[](int t) { return t < 4 ? 0 : 1; },
false,
@@ -704,7 +729,7 @@ TEST(boolean_polymesh, CubeCubeStep)
IMeshBuilder mb(spec);
IMesh out = boolean_mesh(
mb.imesh,
- BOOLEAN_DIFFERENCE,
+ BoolOpType::Difference,
2,
[](int t) { return t < 6 ? 0 : 1; },
false,
@@ -754,7 +779,7 @@ TEST(boolean_polymesh, CubeCyl4)
IMeshBuilder mb(spec);
IMesh out = boolean_mesh(
mb.imesh,
- BOOLEAN_DIFFERENCE,
+ BoolOpType::Difference,
2,
[](int t) { return t < 6 ? 1 : 0; },
false,
@@ -825,7 +850,7 @@ TEST(boolean_polymesh, CubeCubesubdivDiff)
IMeshBuilder mb(spec);
IMesh out = boolean_mesh(
mb.imesh,
- BOOLEAN_DIFFERENCE,
+ BoolOpType::Difference,
2,
[](int t) { return t < 16 ? 1 : 0; },
false,
@@ -866,7 +891,7 @@ TEST(boolean_polymesh, CubePlane)
IMeshBuilder mb(spec);
IMesh out = boolean_mesh(
mb.imesh,
- BOOLEAN_DIFFERENCE,
+ BoolOpType::Difference,
2,
[](int t) { return t >= 1 ? 0 : 1; },
false,
@@ -880,4 +905,4 @@ TEST(boolean_polymesh, CubePlane)
}
}
-} // namespace blender::meshintersect
+} // namespace blender::meshintersect::tests
diff --git a/source/blender/blenlib/tests/BLI_mesh_intersect_test.cc b/source/blender/blenlib/tests/BLI_mesh_intersect_test.cc
index bb5e213364f..d4eebe84067 100644
--- a/source/blender/blenlib/tests/BLI_mesh_intersect_test.cc
+++ b/source/blender/blenlib/tests/BLI_mesh_intersect_test.cc
@@ -18,7 +18,7 @@
#define DO_REGULAR_TESTS 1
#define DO_PERF_TESTS 1
-namespace blender::meshintersect {
+namespace blender::meshintersect::tests {
constexpr bool DO_OBJ = false;
@@ -1074,4 +1074,4 @@ TEST(mesh_intersect_perf, SphereGrid)
#endif
-} // namespace blender::meshintersect
+} // namespace blender::meshintersect::tests
diff --git a/source/blender/bmesh/tools/bmesh_boolean.cc b/source/blender/bmesh/tools/bmesh_boolean.cc
index b04b72dbe89..17ed581927a 100644
--- a/source/blender/bmesh/tools/bmesh_boolean.cc
+++ b/source/blender/bmesh/tools/bmesh_boolean.cc
@@ -218,13 +218,13 @@ static bool apply_mesh_output_to_bmesh(BMesh *bm, IMesh &m_out)
*/
int maxflen = 0;
for (const Face *f : m_out.faces()) {
- maxflen = max_ii(maxflen, static_cast<int>(f->size()));
+ maxflen = max_ii(maxflen, f->size());
}
Array<BMVert *> face_bmverts(maxflen);
Array<BMEdge *> face_bmedges(maxflen);
for (const Face *f : m_out.faces()) {
const Face &face = *f;
- int flen = static_cast<int>(face.size());
+ int flen = face.size();
for (int i = 0; i < flen; ++i) {
const Vert *v = face[i];
int v_index = m_out.lookup_vert(v);
@@ -337,7 +337,7 @@ static bool bmesh_boolean(BMesh *bm,
void *user_data,
const bool use_self,
const bool use_separate_all,
- const int boolean_mode)
+ const BoolOpType boolean_mode)
{
IMeshArena arena;
IMesh m_triangulated;
@@ -369,8 +369,8 @@ static bool bmesh_boolean(BMesh *bm,
return -1;
};
}
- bool_optype op = static_cast<bool_optype>(boolean_mode);
- IMesh m_out = boolean_mesh(m_in, op, nshapes, shape_fn, use_self, &m_triangulated, &arena);
+ IMesh m_out = boolean_mesh(
+ m_in, boolean_mode, nshapes, shape_fn, use_self, &m_triangulated, &arena);
bool any_change = apply_mesh_output_to_bmesh(bm, m_out);
if (use_separate_all) {
/* We are supposed to separate all faces that are incident on intersection edges. */
@@ -411,7 +411,14 @@ bool BM_mesh_boolean(BMesh *bm,
const int boolean_mode)
{
return blender::meshintersect::bmesh_boolean(
- bm, looptris, looptris_tot, test_fn, user_data, use_self, false, boolean_mode);
+ bm,
+ looptris,
+ looptris_tot,
+ test_fn,
+ user_data,
+ use_self,
+ false,
+ static_cast<blender::meshintersect::BoolOpType>(boolean_mode));
}
/*
@@ -437,7 +444,7 @@ bool BM_mesh_boolean_knife(BMesh *bm,
user_data,
use_self,
use_separate_all,
- blender::meshintersect::BOOLEAN_NONE);
+ blender::meshintersect::BoolOpType::None);
}
#else
bool BM_mesh_boolean(BMesh *UNUSED(bm),