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-21 17:02:58 +0300
committerHoward Trickey <howard.trickey@gmail.com>2020-08-21 17:02:58 +0300
commit4b13eb278813ad14782bfa16881f27cdd59c2c6a (patch)
tree90d5d03675fc6294bb4d4ef966ac26f8835bc59c /source/blender/blenlib
parent481927d4d6e124af8f707cd9d8c97f9e8a127d0c (diff)
Rename some classes at the suggestion of reviewers.
Mesh -> IMesh; MArena -> IMeshArena Remove type abbreviations Vertp and Facep.
Diffstat (limited to 'source/blender/blenlib')
-rw-r--r--source/blender/blenlib/BLI_mesh_boolean.hh30
-rw-r--r--source/blender/blenlib/BLI_mesh_intersect.hh125
-rw-r--r--source/blender/blenlib/intern/mesh_boolean.cc370
-rw-r--r--source/blender/blenlib/intern/mesh_intersect.cc289
-rw-r--r--source/blender/blenlib/tests/BLI_mesh_boolean_test.cc178
-rw-r--r--source/blender/blenlib/tests/BLI_mesh_intersect_test.cc219
6 files changed, 614 insertions, 597 deletions
diff --git a/source/blender/blenlib/BLI_mesh_boolean.hh b/source/blender/blenlib/BLI_mesh_boolean.hh
index b9b57216345..324a5adecc7 100644
--- a/source/blender/blenlib/BLI_mesh_boolean.hh
+++ b/source/blender/blenlib/BLI_mesh_boolean.hh
@@ -49,27 +49,27 @@ enum bool_optype {
* of triangles, each of whose orig_field says which face in pm that triangle belongs to.
* pm arg isn't const because we may populate its verts (for debugging).
* Same goes for the pm_triangulated arg.
- * The output Mesh will have faces whose orig fields map back to faces and edges in
+ * The output IMesh will have faces whose orig fields map back to faces and edges in
* the input mesh.
*/
-Mesh boolean_mesh(Mesh &pm,
- bool_optype op,
- int nshapes,
- std::function<int(int)> shape_fn,
- bool use_self,
- Mesh *pm_triangulated,
- MArena *arena);
+IMesh boolean_mesh(IMesh &pm,
+ bool_optype op,
+ int nshapes,
+ std::function<int(int)> shape_fn,
+ bool use_self,
+ IMesh *pm_triangulated,
+ IMeshArena *arena);
-/* This is like boolean, but operates on Mesh's whose faces are all triangles.
+/* This is like boolean, but operates on IMesh's whose faces are all triangles.
* It is exposed mainly for unit testing, at the moment: boolean_mesh() uses
* it to do most of its work.
*/
-Mesh boolean_trimesh(Mesh &tm,
- bool_optype op,
- int nshapes,
- std::function<int(int)> shape_fn,
- bool use_self,
- MArena *arena);
+IMesh boolean_trimesh(IMesh &tm,
+ bool_optype op,
+ int nshapes,
+ std::function<int(int)> shape_fn,
+ bool use_self,
+ IMeshArena *arena);
} // namespace blender::meshintersect
diff --git a/source/blender/blenlib/BLI_mesh_intersect.hh b/source/blender/blenlib/BLI_mesh_intersect.hh
index 39738376b1a..1c77a67877d 100644
--- a/source/blender/blenlib/BLI_mesh_intersect.hh
+++ b/source/blender/blenlib/BLI_mesh_intersect.hh
@@ -77,13 +77,7 @@ struct Vert {
uint64_t hash() const;
};
-/* Use Vertp for Verts everywhere: can modify the pointer
- * but not the underlying Vert, which should stay constant
- * after creation.
- */
-using Vertp = const Vert *;
-
-std::ostream &operator<<(std::ostream &os, Vertp v);
+std::ostream &operator<<(std::ostream &os, const Vert *v);
/* A Plane whose equation is dot(nprm, p) + d = 0. */
struct Plane {
@@ -121,7 +115,7 @@ std::ostream &operator<<(std::ostream &os, const Plane &plane);
* a Face also stores the Plane of the face.
*/
struct Face {
- Array<Vertp> vert;
+ Array<const Vert *> vert;
Array<int> edge_orig;
Array<bool> is_intersect;
Plane plane;
@@ -131,8 +125,8 @@ struct Face {
using FacePos = int;
Face() = default;
- Face(Span<Vertp> verts, int id, int orig, Span<int> edge_origs, Span<bool> is_intersect);
- Face(Span<Vertp> verts, int id, int orig);
+ 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;
@@ -162,7 +156,7 @@ struct Face {
return (p + vert.size() - 1) % vert.size();
}
- const Vertp &operator[](int index) const
+ const Vert *const &operator[](int index) const
{
return vert[index];
}
@@ -172,12 +166,12 @@ struct Face {
return vert.size();
}
- const Vertp *begin() const
+ const Vert *const *begin() const
{
return vert.begin();
}
- const Vertp *end() const
+ const Vert *const *end() const
{
return vert.end();
}
@@ -188,29 +182,27 @@ struct Face {
}
};
-using Facep = const Face *;
-
-std::ostream &operator<<(std::ostream &os, Facep f);
+std::ostream &operator<<(std::ostream &os, const Face *f);
-/* MArena is the owner of the Vert and Face resources used
+/* IMeshArena is the owner of the Vert and Face resources used
* during a run of one of the meshintersect main functions.
* It also keeps has a hash table of all Verts created so that it can
* ensure that only one instance of a Vert with a given co_exact will
* exist. I.e., it dedups the vertices.
*/
-class MArena {
- class MArenaImpl;
- std::unique_ptr<MArenaImpl> pimpl_;
+class IMeshArena {
+ class IMeshArenaImpl;
+ std::unique_ptr<IMeshArenaImpl> pimpl_;
public:
- MArena();
- MArena(const MArena &) = delete;
- MArena(MArena &&) = delete;
+ IMeshArena();
+ IMeshArena(const IMeshArena &) = delete;
+ IMeshArena(IMeshArena &&) = delete;
- ~MArena();
+ ~IMeshArena();
- MArena &operator=(const MArena &) = delete;
- MArena &operator=(MArena &&) = delete;
+ IMeshArena &operator=(const IMeshArena &) = delete;
+ IMeshArena &operator=(IMeshArena &&) = delete;
/* Provide hints to number of expected Verts and Faces expected
* to be allocated.
@@ -225,42 +217,45 @@ class MArena {
* or else allocates and returns a new one. The index field of a
* newly allocated Vert will be the index in creation order.
*/
- Vertp add_or_find_vert(const mpq3 &co, int orig);
- Vertp add_or_find_vert(const double3 &co, int orig);
+ const Vert *add_or_find_vert(const mpq3 &co, int orig);
+ const Vert *add_or_find_vert(const double3 &co, int orig);
- Facep add_face(Span<Vertp> verts, int orig, Span<int> edge_origs, Span<bool> is_intersect);
- Facep add_face(Span<Vertp> verts, int orig, Span<int> edge_origs);
- Facep add_face(Span<Vertp> verts, int orig);
+ const Face *add_face(Span<const Vert *> verts,
+ int orig,
+ Span<int> edge_origs,
+ Span<bool> is_intersect);
+ const Face *add_face(Span<const Vert *> verts, int orig, Span<int> edge_origs);
+ const Face *add_face(Span<const Vert *> verts, int orig);
/* The following return nullptr if not found. */
- Vertp find_vert(const mpq3 &co) const;
- Facep find_face(Span<Vertp> verts) const;
+ const Vert *find_vert(const mpq3 &co) const;
+ const Face *find_face(Span<const Vert *> verts) const;
};
-/* A blender::meshintersect::Mesh is a self-contained mesh structure
+/* A blender::meshintersect::IMesh is a self-contained mesh structure
* that can be used in Blenlib without depending on the rest of Blender.
- * The Vert and Face resources used in the Mesh should be owned by
- * some MArena.
- * The Verts used by a Mesh can be recovered from the Faces, so
- * are usually not stored, but on request, the Mesh can populate
+ * The Vert and Face resources used in the IMesh should be owned by
+ * some IMeshArena.
+ * The Verts used by a IMesh can be recovered from the Faces, so
+ * are usually not stored, but on request, the IMesh can populate
* internal structures for indexing exactly the set of needed Verts,
* and also going from a Vert pointer to the index in that system.
*/
-class Mesh {
- Array<Facep> face_;
- Array<Vertp> vert_; /* Only valid if vert_populated_. */
- Map<Vertp, int> vert_to_index_; /* Only valid if vert_populated_. */
+class IMesh {
+ Array<const Face *> face_;
+ Array<const Vert *> vert_; /* Only valid if vert_populated_. */
+ Map<const Vert *, int> vert_to_index_; /* Only valid if vert_populated_. */
bool vert_populated_ = false;
public:
- Mesh() = default;
- Mesh(Span<Facep> faces) : face_(faces)
+ IMesh() = default;
+ IMesh(Span<const Face *> faces) : face_(faces)
{
}
- void set_faces(Span<Facep> faces);
- Facep face(int index) const
+ void set_faces(Span<const Face *> faces);
+ const Face *face(int index) const
{
return face_[index];
}
@@ -284,7 +279,7 @@ class Mesh {
{
vert_populated_ = false;
vert_to_index_.clear();
- vert_ = Array<Vertp>();
+ vert_ = Array<const Vert *>();
}
/* Use the second of these if there is a good bound
@@ -293,14 +288,14 @@ class Mesh {
void populate_vert();
void populate_vert(int max_verts);
- Vertp vert(int index) const
+ const Vert *vert(int index) const
{
BLI_assert(vert_populated_);
return vert_[index];
}
/* Returns index in vert_ where v is, or NO_INDEX. */
- int lookup_vert(Vertp v) const;
+ int lookup_vert(const Vert *v) const;
IndexRange vert_index_range() const
{
@@ -313,45 +308,45 @@ class Mesh {
return IndexRange(face_.size());
}
- Span<Vertp> vertices() const
+ Span<const Vert *> vertices() const
{
BLI_assert(vert_populated_);
- return Span<Vertp>(vert_);
+ return Span<const Vert *>(vert_);
}
- Span<Facep> faces() const
+ Span<const Face *> faces() const
{
- return Span<Facep>(face_);
+ return Span<const Face *>(face_);
}
/* 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.
*/
- void erase_face_positions(int f_index, Span<bool> face_pos_erase, MArena *arena);
+ void erase_face_positions(int f_index, Span<bool> face_pos_erase, IMeshArena *arena);
};
-std::ostream &operator<<(std::ostream &os, const Mesh &mesh);
+std::ostream &operator<<(std::ostream &os, const IMesh &mesh);
/* The output will have dup vertices merged and degenerate triangles ignored.
* If the input has overlapping coplanar triangles, then there will be
* as many duplicates as there are overlaps in each overlapping triangular region.
- * The orig field of each IndexedTriangle will give the orig index in the input TriMesh
+ * The orig field of each IndexedTriangle will give the orig index in the input IMesh
* that the output triangle was a part of (input can have -1 for that field and then
* the index in tri[] will be used as the original index).
- * The orig structure of the output TriMesh gives the originals for vertices and edges.
+ * The orig structure of the output IMesh gives the originals for vertices and edges.
* Note: if the input tm_in has a non-empty orig structure, then it is ignored.
*/
-Mesh trimesh_self_intersect(const Mesh &tm_in, MArena *arena);
+IMesh trimesh_self_intersect(const IMesh &tm_in, IMeshArena *arena);
-Mesh trimesh_nary_intersect(const Mesh &tm_in,
- int nshapes,
- std::function<int(int)> shape_fn,
- bool use_self,
- MArena *arena);
+IMesh trimesh_nary_intersect(const IMesh &tm_in,
+ int nshapes,
+ std::function<int(int)> shape_fn,
+ bool use_self,
+ IMeshArena *arena);
-/* This has the side effect of populating verts in the Mesh. */
-void write_obj_mesh(Mesh &m, const std::string &objname);
+/* This has the side effect of populating verts in the IMesh. */
+void write_obj_mesh(IMesh &m, const std::string &objname);
} /* namespace blender::meshintersect */
diff --git a/source/blender/blenlib/intern/mesh_boolean.cc b/source/blender/blenlib/intern/mesh_boolean.cc
index b76ff3c38a4..4a9bf28ac78 100644
--- a/source/blender/blenlib/intern/mesh_boolean.cc
+++ b/source/blender/blenlib/intern/mesh_boolean.cc
@@ -39,16 +39,16 @@
namespace blender::meshintersect {
-/* Edge as two Vertp's, in a canonical order (lower vert id first).
+/* Edge as two const Vert *'s, in a canonical order (lower vert id first).
* We use the Vert id field for hashing to get algorithms
* that yield predictable results from run-to-run and machine-to-machine.
*/
class Edge {
- Vertp v_[2]{nullptr, nullptr};
+ const Vert *v_[2]{nullptr, nullptr};
public:
Edge() = default;
- Edge(Vertp v0, Vertp v1)
+ Edge(const Vert *v0, const Vert *v1)
{
if (v0->id <= v1->id) {
v_[0] = v0;
@@ -60,17 +60,17 @@ class Edge {
}
}
- Vertp v0() const
+ const Vert *v0() const
{
return v_[0];
}
- Vertp v1() const
+ const Vert *v1() const
{
return v_[1];
}
- Vertp operator[](int i) const
+ const Vert *operator[](int i) const
{
return v_[i];
}
@@ -118,15 +118,15 @@ static std::ostream &operator<<(std::ostream &os, const Array<int> &iarr)
return os;
}
-/* Holds information about topology of a Mesh that is all triangles. */
+/* Holds information about topology of an IMesh that is all triangles. */
class TriMeshTopology {
/* Triangles that contain a given Edge (either order). */
Map<Edge, Vector<int> *> edge_tri_;
/* Edges incident on each vertex. */
- Map<Vertp, Vector<Edge>> vert_edges_;
+ Map<const Vert *, Vector<Edge>> vert_edges_;
public:
- TriMeshTopology(const Mesh &tm);
+ TriMeshTopology(const IMesh &tm);
TriMeshTopology(const TriMeshTopology &other) = delete;
TriMeshTopology(const TriMeshTopology &&other) = delete;
~TriMeshTopology();
@@ -153,7 +153,7 @@ class TriMeshTopology {
/* Which edges are incident on the given vertex?
* We assume v has some incident edges.
*/
- const Vector<Edge> &vert_edges(Vertp v) const
+ const Vector<Edge> &vert_edges(const Vert *v) const
{
return vert_edges_.lookup(v);
}
@@ -164,7 +164,7 @@ class TriMeshTopology {
}
};
-TriMeshTopology::TriMeshTopology(const Mesh &tm)
+TriMeshTopology::TriMeshTopology(const IMesh &tm)
{
const int dbg_level = 0;
if (dbg_level > 0) {
@@ -181,8 +181,8 @@ TriMeshTopology::TriMeshTopology(const Mesh &tm)
const Face &tri = *tm.face(t);
BLI_assert(tri.is_tri());
for (int i = 0; i < 3; ++i) {
- Vertp v = tri[i];
- Vertp vnext = tri[(i + 1) % 3];
+ const Vert *v = tri[i];
+ const Vert *vnext = tri[(i + 1) % 3];
Edge e(v, vnext);
Vector<Edge> *edges = vert_edges_.lookup_ptr(v);
if (edges == nullptr) {
@@ -284,7 +284,7 @@ static std::ostream &operator<<(std::ostream &os, const Patch &patch)
}
class PatchesInfo {
- /* All of the Patches for a Mesh. */
+ /* All of the Patches for a IMesh. */
Vector<Patch> patch_;
/* Patch index for corresponding triangle. */
Array<int> tri_patch_;
@@ -450,7 +450,7 @@ class Cell {
/* Call this when it is possible that this Cell has zero volume,
* and if it does, set zero_volume_ to true.
*/
- void check_for_zero_volume(const PatchesInfo &pinfo, const Mesh &mesh);
+ void check_for_zero_volume(const PatchesInfo &pinfo, const IMesh &mesh);
};
static std::ostream &operator<<(std::ostream &os, const Cell &cell)
@@ -464,7 +464,7 @@ static std::ostream &operator<<(std::ostream &os, const Cell &cell)
return os;
}
-static bool tris_have_same_verts(const Mesh &mesh, int t1, int t2)
+static bool tris_have_same_verts(const IMesh &mesh, int t1, int t2)
{
const Face &tri1 = *mesh.face(t1);
const Face &tri2 = *mesh.face(t2);
@@ -488,7 +488,7 @@ static bool tris_have_same_verts(const Mesh &mesh, int t1, int t2)
* patches are geometrically identical triangles (perhaps flipped versions of each other).
* If this Cell has zero volume, set its zero_volume_ member to true.
*/
-void Cell::check_for_zero_volume(const PatchesInfo &pinfo, const Mesh &mesh)
+void Cell::check_for_zero_volume(const PatchesInfo &pinfo, const IMesh &mesh)
{
if (patches_.size() == 2) {
const Patch &p1 = pinfo.patch(patches_[0]);
@@ -553,7 +553,7 @@ class CellsInfo {
};
/* For Debugging: write a .obj file showing the patch/cell structure or just the cells. */
-static void write_obj_cell_patch(const Mesh &m,
+static void write_obj_cell_patch(const IMesh &m,
const CellsInfo &cinfo,
const PatchesInfo &pinfo,
bool cells_only,
@@ -576,11 +576,11 @@ static void write_obj_cell_patch(const Mesh &m,
return;
}
- /* Copy Mesh so can populate verts. */
- Mesh mm = m;
+ /* Copy IMesh so can populate verts. */
+ IMesh mm = m;
mm.populate_vert();
f << "o cellpatch\n";
- for (Vertp v : mm.vertices()) {
+ for (const Vert *v : mm.vertices()) {
const double3 dv = v->co;
f << "v " << dv[0] << " " << dv[1] << " " << dv[2] << "\n";
}
@@ -591,7 +591,7 @@ static void write_obj_cell_patch(const Mesh &m,
for (int t : patch.tris()) {
const Face &tri = *mm.face(t);
f << "f ";
- for (Vertp v : tri) {
+ for (const Vert *v : tri) {
f << mm.lookup_vert(v) + 1 << " ";
}
f << "\n";
@@ -606,7 +606,7 @@ static void write_obj_cell_patch(const Mesh &m,
for (int t : patch.tris()) {
const Face &tri = *mm.face(t);
f << "f ";
- for (Vertp v : tri) {
+ for (const Vert *v : tri) {
f << mm.lookup_vert(v) + 1 << " ";
}
f << "\n";
@@ -644,7 +644,7 @@ static void merge_cells(int merge_to, int merge_from, CellsInfo &cinfo, PatchesI
}
/* Partition the triangles of tm into Patches. */
-static PatchesInfo find_patches(const Mesh &tm, const TriMeshTopology &tmtopo)
+static PatchesInfo find_patches(const IMesh &tm, const TriMeshTopology &tmtopo)
{
const int dbg_level = 0;
if (dbg_level > 0) {
@@ -744,10 +744,10 @@ static PatchesInfo find_patches(const Mesh &tm, const TriMeshTopology &tmtopo)
* Also, e may be reversed in tri.
* Set *r_rev to true if it is reversed, else false.
*/
-static Vertp find_flap_vert(const Face &tri, const Edge e, bool *r_rev)
+static const Vert *find_flap_vert(const Face &tri, const Edge e, bool *r_rev)
{
*r_rev = false;
- Vertp flapv;
+ const Vert *flapv;
if (tri[0] == e.v0()) {
if (tri[1] == e.v1()) {
*r_rev = false;
@@ -818,8 +818,8 @@ static int sort_tris_class(const Face &tri, const Face &tri0, const Edge e)
mpq3 a2 = tri0[2]->co_exact;
bool rev;
bool rev0;
- Vertp flapv0 = find_flap_vert(tri0, e, &rev0);
- Vertp flapv = find_flap_vert(tri, e, &rev);
+ const Vert *flapv0 = find_flap_vert(tri0, e, &rev0);
+ const Vert *flapv = find_flap_vert(tri, e, &rev);
if (dbg_level > 0) {
std::cout << " t0 = " << tri0[0] << " " << tri0[1] << " " << tri0[2];
std::cout << " rev0 = " << rev0 << " flapv0 = " << flapv0 << "\n";
@@ -855,8 +855,8 @@ constexpr int EXTRA_TRI_INDEX = INT_MAX;
*/
static void sort_by_signed_triangle_index(Vector<int> &g,
const Edge e,
- const Mesh &tm,
- Facep extra_tri)
+ const IMesh &tm,
+ const Face *extra_tri)
{
Array<int> signed_g(g.size());
for (int i : g.index_range()) {
@@ -887,12 +887,12 @@ static void sort_by_signed_triangle_index(Vector<int> &g,
* To accommodate this:
* If extra_tri is non-null, then an index of EXTRA_TRI_INDEX should use it for the triangle.
*/
-static Array<int> sort_tris_around_edge(const Mesh &tm,
+static Array<int> sort_tris_around_edge(const IMesh &tm,
const TriMeshTopology &tmtopo,
const Edge e,
const Span<int> &tris,
const int t0,
- Facep extra_tri)
+ const Face *extra_tri)
{
/* Divide and conquer, quicksort-like sort.
* Pick a triangle t0, then partition into groups:
@@ -997,7 +997,7 @@ static Array<int> sort_tris_around_edge(const Mesh &tm,
* bipartite graph edges between cells and patches.
* Will modify pinfo and cinfo and the patches and cells they contain.
*/
-static void find_cells_from_edge(const Mesh &tm,
+static void find_cells_from_edge(const IMesh &tm,
const TriMeshTopology &tmtopo,
PatchesInfo &pinfo,
CellsInfo &cinfo,
@@ -1094,7 +1094,7 @@ static void find_cells_from_edge(const Mesh &tm,
/* Find the partition of 3-space into Cells.
* This assigns the cell_above and cell_below for each Patch.
*/
-static CellsInfo find_cells(const Mesh &tm, const TriMeshTopology &tmtopo, PatchesInfo &pinfo)
+static CellsInfo find_cells(const IMesh &tm, const TriMeshTopology &tmtopo, PatchesInfo &pinfo)
{
const int dbg_level = 0;
if (dbg_level > 0) {
@@ -1251,7 +1251,7 @@ static bool patch_cell_graph_ok(const CellsInfo &cinfo, const PatchesInfo &pinfo
* this without being PWN. So this routine will be only
* approximately right.
*/
-static bool is_pwn(const Mesh &tm, const TriMeshTopology &tmtopo)
+static bool is_pwn(const IMesh &tm, const TriMeshTopology &tmtopo)
{
constexpr int dbg_level = 0;
for (auto item : tmtopo.edge_tri_map_items()) {
@@ -1293,21 +1293,21 @@ static bool is_pwn(const Mesh &tm, const TriMeshTopology &tmtopo)
*/
static int find_cell_for_point_near_edge(mpq3 p,
const Edge &e,
- const Mesh &tm,
+ const IMesh &tm,
const TriMeshTopology &tmtopo,
const PatchesInfo &pinfo,
- MArena *arena)
+ IMeshArena *arena)
{
constexpr int dbg_level = 0;
if (dbg_level > 0) {
std::cout << "FIND_CELL_FOR_POINT_NEAR_EDGE, p=" << p << " e=" << e << "\n";
}
const Vector<int> *etris = tmtopo.edge_tris(e);
- Vertp dummy_vert = arena->add_or_find_vert(p, NO_INDEX);
- Facep dummy_tri = arena->add_face({e.v0(), e.v1(), dummy_vert},
- NO_INDEX,
- {NO_INDEX, NO_INDEX, NO_INDEX},
- {false, false, false});
+ const Vert *dummy_vert = arena->add_or_find_vert(p, NO_INDEX);
+ const Face *dummy_tri = arena->add_face({e.v0(), e.v1(), dummy_vert},
+ NO_INDEX,
+ {NO_INDEX, NO_INDEX, NO_INDEX},
+ {false, false, false});
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;
@@ -1355,25 +1355,25 @@ static int find_cell_for_point_near_edge(mpq3 p,
* to the dummy triangle - thus revealing the cell that the point
* known to be outside the whole mesh is in.
*/
-static int find_ambient_cell(const Mesh &tm,
+static int find_ambient_cell(const IMesh &tm,
const Vector<int> *component_patches,
const TriMeshTopology &tmtopo,
const PatchesInfo &pinfo,
- MArena *arena)
+ IMeshArena *arena)
{
int dbg_level = 0;
if (dbg_level > 0) {
std::cout << "FIND_AMBIENT_CELL\n";
}
/* First find a vertex with the maximum x value. */
- /* Prefer not to populate the verts in the Mesh just for this. */
- Vertp v_extreme;
+ /* Prefer not to populate the verts in the IMesh just for this. */
+ const Vert *v_extreme;
mpq_class extreme_x;
if (component_patches == nullptr) {
v_extreme = (*tm.face(0))[0];
extreme_x = v_extreme->co_exact.x;
- for (Facep f : tm.faces()) {
- for (Vertp v : *f) {
+ for (const Face *f : tm.faces()) {
+ for (const Vert *v : *f) {
const mpq_class &x = v->co_exact.x;
if (x > extreme_x) {
v_extreme = v;
@@ -1391,8 +1391,8 @@ static int find_ambient_cell(const Mesh &tm,
extreme_x = v_extreme->co_exact.x;
for (int p : *component_patches) {
for (int t : pinfo.patch(p).tris()) {
- Facep f = tm.face(t);
- for (Vertp v : *f) {
+ const Face *f = tm.face(t);
+ for (const Vert *v : *f) {
const mpq_class &x = v->co_exact.x;
if (x > extreme_x) {
v_extreme = v;
@@ -1414,7 +1414,7 @@ static int find_ambient_cell(const Mesh &tm,
Edge ehull;
mpq_class max_abs_slope = -1;
for (Edge e : edges) {
- const Vertp v_other = (e.v0() == v_extreme) ? e.v1() : e.v0();
+ const 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) {
@@ -1450,7 +1450,9 @@ static int find_ambient_cell(const Mesh &tm,
* and then choose the edge that, when projected, has the maximum absolute
* slope (regarding the line testp-closestp as the xaxis for slope computation).
*/
-static Edge find_good_sorting_edge(Vertp testp, Vertp closestp, const TriMeshTopology &tmtopo)
+static Edge find_good_sorting_edge(const Vert *testp,
+ const Vert *closestp,
+ const TriMeshTopology &tmtopo)
{
constexpr int dbg_level = 0;
if (dbg_level > 0) {
@@ -1493,7 +1495,7 @@ static Edge find_good_sorting_edge(Vertp testp, Vertp closestp, const TriMeshTop
Edge esort;
const Vector<Edge> &edges = tmtopo.vert_edges(closestp);
for (Edge e : edges) {
- const Vertp v_other = (e.v0() == closestp) ? e.v1() : e.v0();
+ const const Vert *v_other = (e.v0() == closestp) ? e.v1() : e.v0();
const mpq3 &co_other = v_other->co_exact;
mpq3 evec = co_other - co_closest;
/* Get projection of evec onto plane of abscissa and ordinate. */
@@ -1541,14 +1543,14 @@ static Edge find_good_sorting_edge(Vertp testp, Vertp closestp, const TriMeshTop
* have a particular point (v) and we just want to determine the patches
* that that point is between in sorting-around-an-edge order.
*/
-static int find_containing_cell(Vertp v,
+static int find_containing_cell(const Vert *v,
int t,
int close_edge,
int close_vert,
const PatchesInfo &pinfo,
- const Mesh &tm,
+ const IMesh &tm,
const TriMeshTopology &tmtopo,
- MArena *arena)
+ IMeshArena *arena)
{
constexpr int dbg_level = 0;
if (dbg_level > 0) {
@@ -1561,8 +1563,8 @@ static int find_containing_cell(Vertp v,
close_edge = 0;
}
if (close_edge != -1) {
- Vertp v0 = tri[close_edge];
- Vertp v1 = tri[(close_edge + 1) % 3];
+ const Vert *v0 = tri[close_edge];
+ const Vert *v1 = tri[(close_edge + 1) % 3];
const Vector<Edge> &edges = tmtopo.vert_edges(v0);
if (dbg_level > 0) {
std::cout << "look for edge containing " << v0 << " and " << v1 << "\n";
@@ -1581,7 +1583,7 @@ static int find_containing_cell(Vertp v,
}
else {
int cv = close_vert;
- Vertp vert_cv = tri[cv];
+ const Vert *vert_cv = tri[cv];
if (vert_cv == v) {
/* Need to use another one to find sorting edge. */
vert_cv = tri[(cv + 1) % 3];
@@ -1732,10 +1734,10 @@ struct ComponentContainer {
static Vector<ComponentContainer> find_component_containers(int comp,
const Vector<Vector<int>> &components,
const Array<int> &ambient_cell,
- const Mesh &tm,
+ const IMesh &tm,
const PatchesInfo &pinfo,
const TriMeshTopology &tmtopo,
- MArena *arena)
+ IMeshArena *arena)
{
constexpr int dbg_level = 0;
if (dbg_level > 0) {
@@ -1744,7 +1746,7 @@ static Vector<ComponentContainer> find_component_containers(int comp,
Vector<ComponentContainer> ans;
int test_p = components[comp][0];
int test_t = pinfo.patch(test_p).tri(0);
- Vertp test_v = tm.face(test_t)[0].vert[0];
+ const Vert *test_v = tm.face(test_t)[0].vert[0];
if (dbg_level > 0) {
std::cout << "test vertex in comp: " << test_v << "\n";
}
@@ -1789,7 +1791,7 @@ static Vector<ComponentContainer> find_component_containers(int comp,
if (dbg_level > 0) {
std::cout << "closest tri to comp=" << comp << " in comp_other=" << comp_other << " is t"
<< nearest_tri << "\n";
- Facep tn = tm.face(nearest_tri);
+ const Face *tn = tm.face(nearest_tri);
std::cout << "tri = " << tn << "\n";
std::cout << " (" << tn->vert[0]->co << "," << tn->vert[1]->co << "," << tn->vert[2]->co
<< ")\n";
@@ -1819,11 +1821,11 @@ static Vector<ComponentContainer> find_component_containers(int comp,
* Connect the bipartite graph. This involves discovering the connected components
* of the patches, then the nesting structure of those components.
*/
-static void finish_patch_cell_graph(const Mesh &tm,
+static void finish_patch_cell_graph(const IMesh &tm,
CellsInfo &cinfo,
PatchesInfo &pinfo,
const TriMeshTopology &tmtopo,
- MArena *arena)
+ IMeshArena *arena)
{
constexpr int dbg_level = 0;
if (dbg_level > 0) {
@@ -2046,11 +2048,11 @@ static bool apply_bool_op(int bool_optype, const Array<int> &winding)
* triangles that are part of stacks of geometrically identical
* triangles enclosing zero volume cells.
*/
-static void extract_zero_volume_cell_tris(Vector<Facep> &out_tris,
- const Mesh &tm_subdivided,
+static void extract_zero_volume_cell_tris(Vector<const Face *> &out_tris,
+ const IMesh &tm_subdivided,
const PatchesInfo &pinfo,
const CellsInfo &cinfo,
- MArena *arena)
+ IMeshArena *arena)
{
int dbg_level = 0;
if (dbg_level > 0) {
@@ -2146,14 +2148,14 @@ static void extract_zero_volume_cell_tris(Vector<Facep> &out_tris,
}
}
if (t_to_add == NO_INDEX) {
- Facep f = tm_subdivided.face(pinfo.patch(p).tri(0));
+ const Face *f = tm_subdivided.face(pinfo.patch(p).tri(0));
const Face &tri = *f;
/* We need flipped version or else we would have found it above. */
- Array<Vertp> flipped_vs = {tri[0], tri[2], tri[1]};
+ 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 = {
tri.is_intersect[2], tri.is_intersect[1], tri.is_intersect[0]};
- Facep flipped_f = arena->add_face(
+ const Face *flipped_f = arena->add_face(
flipped_vs, f->orig, flipped_e_origs, flipped_is_intersect);
out_tris.append(flipped_f);
}
@@ -2170,16 +2172,16 @@ static void extract_zero_volume_cell_tris(Vector<Facep> &out_tris,
* 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.
*/
-static Mesh extract_from_flag_diffs(const Mesh &tm_subdivided,
- const PatchesInfo &pinfo,
- const CellsInfo &cinfo,
- MArena *arena)
+static IMesh extract_from_flag_diffs(const IMesh &tm_subdivided,
+ const PatchesInfo &pinfo,
+ const CellsInfo &cinfo,
+ IMeshArena *arena)
{
constexpr int dbg_level = 0;
if (dbg_level > 0) {
std::cout << "\nEXTRACT_FROM_FLAG_DIFFS\n";
}
- Vector<Facep> out_tris;
+ Vector<const Face *> out_tris;
out_tris.reserve(tm_subdivided.face_size());
bool any_zero_volume_cell = false;
for (int t : tm_subdivided.face_index_range()) {
@@ -2200,14 +2202,14 @@ static Mesh extract_from_flag_diffs(const Mesh &tm_subdivided,
if (dbg_level > 0) {
std::cout << "need tri " << t << " flip=" << flip << "\n";
}
- Facep f = tm_subdivided.face(t);
+ const Face *f = tm_subdivided.face(t);
if (flip) {
const Face &tri = *f;
- Array<Vertp> flipped_vs = {tri[0], tri[2], tri[1]};
+ 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 = {
tri.is_intersect[2], tri.is_intersect[1], tri.is_intersect[0]};
- Facep flipped_f = arena->add_face(
+ const Face *flipped_f = arena->add_face(
flipped_vs, f->orig, flipped_e_origs, flipped_is_intersect);
out_tris.append(flipped_f);
}
@@ -2219,7 +2221,7 @@ static Mesh extract_from_flag_diffs(const Mesh &tm_subdivided,
if (any_zero_volume_cell) {
extract_zero_volume_cell_tris(out_tris, tm_subdivided, pinfo, cinfo, arena);
}
- return Mesh(out_tris);
+ return IMesh(out_tris);
}
static const char *bool_optype_name(bool_optype op)
@@ -2243,9 +2245,9 @@ static const char *bool_optype_name(bool_optype op)
static mpq3 calc_point_inside_tri(const Face &tri)
{
- Vertp v0 = tri.vert[0];
- Vertp v1 = tri.vert[1];
- Vertp v2 = tri.vert[2];
+ const Vert *v0 = tri.vert[0];
+ const Vert *v1 = tri.vert[1];
+ const Vert *v2 = tri.vert[2];
mpq3 ans = v0->co_exact / 3 + v1->co_exact / 3 + v2->co_exact / 3;
return ans;
}
@@ -2261,7 +2263,7 @@ static mpq3 calc_point_inside_tri(const Face &tri)
* TOOD: speed up this calculation using the heirarchical algorithm in
* that paper.
*/
-static double generalized_winding_number(const Mesh &tm,
+static double generalized_winding_number(const IMesh &tm,
std::function<int(int)> shape_fn,
const double3 &testp,
int shape)
@@ -2272,15 +2274,15 @@ static double generalized_winding_number(const Mesh &tm,
}
double gwn = 0;
for (int t : tm.face_index_range()) {
- Facep f = tm.face(t);
+ const Face *f = tm.face(t);
const Face &tri = *f;
if (shape_fn(tri.orig) == shape) {
if (dbg_level > 0) {
std::cout << "accumulate for tri t = " << t << " = " << f << "\n";
}
- Vertp v0 = tri.vert[0];
- Vertp v1 = tri.vert[1];
- Vertp v2 = tri.vert[2];
+ const Vert *v0 = tri.vert[0];
+ const Vert *v1 = tri.vert[1];
+ const Vert *v2 = tri.vert[2];
double3 a = v0->co - testp;
double3 b = v1->co - testp;
double3 c = v2->co - testp;
@@ -2319,7 +2321,7 @@ static double generalized_winding_number(const Mesh &tm,
/* Return true if point testp is inside the volume implied by the
* faces for which the shape_fn returns the value shape.
*/
-static bool point_is_inside_shape(const Mesh &tm,
+static bool point_is_inside_shape(const IMesh &tm,
std::function<int(int)> shape_fn,
const double3 &testp,
int shape)
@@ -2335,19 +2337,19 @@ static bool point_is_inside_shape(const Mesh &tm,
* mesh is supposed to be included or excluded in the boolean result,
* and return the mesh that is the boolean result.
*/
-static Mesh gwn_boolean(const Mesh &tm,
- bool_optype op,
- int nshapes,
- std::function<int(int)> shape_fn,
- const PatchesInfo &pinfo,
- MArena *arena)
+static IMesh gwn_boolean(const IMesh &tm,
+ bool_optype op,
+ int nshapes,
+ std::function<int(int)> shape_fn,
+ const PatchesInfo &pinfo,
+ IMeshArena *arena)
{
constexpr int dbg_level = 0;
if (dbg_level > 0) {
std::cout << "GWN_BOOLEAN\n";
}
- Mesh ans;
- Vector<Facep> out_faces;
+ IMesh ans;
+ Vector<const Face *> out_faces;
out_faces.reserve(tm.face_size());
BLI_assert(nshapes == 2); /* TODO: generalize. */
for (int p : pinfo.index_range()) {
@@ -2401,18 +2403,18 @@ static Mesh gwn_boolean(const Mesh &tm,
}
if (!do_remove) {
for (int t : patch.tris()) {
- Facep f = tm.face(t);
+ const Face *f = tm.face(t);
if (!do_flip) {
out_faces.append(f);
}
else {
const Face &tri = *f;
/* We need flipped version of f. */
- Array<Vertp> flipped_vs = {tri[0], tri[2], tri[1]};
+ 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 = {
tri.is_intersect[2], tri.is_intersect[1], tri.is_intersect[0]};
- Facep flipped_f = arena->add_face(
+ const Face *flipped_f = arena->add_face(
flipped_vs, f->orig, flipped_e_origs, flipped_is_intersect);
out_faces.append(flipped_f);
}
@@ -2437,14 +2439,14 @@ static int find_cdt_edge(const CDT_result<mpq_class> &cdt_out, int v1, int v2)
return -1;
}
-/* Tesselate face f into triangles and return an array of Facep
+/* Tesselate face f into triangles and return an array of const Face *
* giving that triangulation.
* Care is taken so that the original edge index associated with
* each edge in the output triangles either matches the original edge
* for the (identical) edge of f, or else is -1. So diagonals added
* for triangulation can later be indentified by having NO_INDEX for original.
*/
-static Array<Facep> triangulate_poly(Facep f, MArena *arena)
+static Array<const Face *> triangulate_poly(const Face *f, IMeshArena *arena)
{
int flen = f->size();
CDT_input<mpq_class> cdt_in;
@@ -2478,10 +2480,10 @@ static Array<Facep> triangulate_poly(Facep f, MArena *arena)
}
CDT_result<mpq_class> cdt_out = delaunay_2d_calc(cdt_in, CDT_INSIDE);
int n_tris = cdt_out.face.size();
- Array<Facep> ans(n_tris);
+ Array<const Face *> ans(n_tris);
for (int t = 0; t < n_tris; ++t) {
int i_v_out[3];
- Vertp v[3];
+ const Vert *v[3];
int eo[3];
for (int i = 0; i < 3; ++i) {
i_v_out[i] = cdt_out.face[t][i];
@@ -2510,44 +2512,46 @@ static Array<Facep> triangulate_poly(Facep f, MArena *arena)
return ans;
}
-/* Return a Mesh that is a triangulation of a mesh with general
+/* Return an IMesh that is a triangulation of a mesh with general
* polygonal faces, pm.
* Added diagonals will be distinguishable by having edge original
* indices of NO_INDEX.
*/
-static Mesh triangulate_polymesh(Mesh &pm, MArena *arena)
+static IMesh triangulate_polymesh(IMesh &pm, IMeshArena *arena)
{
- Vector<Facep> face_tris;
+ Vector<const Face *> face_tris;
constexpr int estimated_tris_per_face = 3;
face_tris.reserve(estimated_tris_per_face * pm.face_size());
- for (Facep f : pm.faces()) {
+ for (const Face *f : pm.faces()) {
/* Tesselate face f, following plan similar to BM_face_calc_tesselation. */
int flen = f->size();
if (flen == 3) {
face_tris.append(f);
}
else if (flen == 4) {
- Vertp v0 = (*f)[0];
- Vertp v1 = (*f)[1];
- Vertp v2 = (*f)[2];
- Vertp v3 = (*f)[3];
+ const Vert *v0 = (*f)[0];
+ const Vert *v1 = (*f)[1];
+ const Vert *v2 = (*f)[2];
+ const Vert *v3 = (*f)[3];
int eo_01 = f->edge_orig[0];
int eo_12 = f->edge_orig[1];
int eo_23 = f->edge_orig[2];
int eo_30 = f->edge_orig[3];
- Facep f0 = arena->add_face({v0, v1, v2}, f->orig, {eo_01, eo_12, -1}, {false, false, false});
- Facep f1 = arena->add_face({v0, v2, v3}, f->orig, {-1, eo_23, eo_30}, {false, false, false});
+ const Face *f0 = arena->add_face(
+ {v0, v1, v2}, f->orig, {eo_01, eo_12, -1}, {false, false, false});
+ const Face *f1 = arena->add_face(
+ {v0, v2, v3}, f->orig, {-1, eo_23, eo_30}, {false, false, false});
face_tris.append(f0);
face_tris.append(f1);
}
else {
- Array<Facep> tris = triangulate_poly(f, arena);
- for (Facep tri : tris) {
+ Array<const Face *> tris = triangulate_poly(f, arena);
+ for (const Face *tri : tris) {
face_tris.append(tri);
}
}
}
- return Mesh(face_tris);
+ return IMesh(face_tris);
}
/* If tri1 and tri2 have a common edge (in opposite orientation), return the indices into tri1 and
@@ -2569,8 +2573,8 @@ struct MergeEdge {
/* Length (squared) of the edge, used for sorting. */
double len_squared = 0.0;
/* v1 and v2 are the ends of the edge, ordered so that v1->id < v2->id */
- Vertp v1 = nullptr;
- Vertp v2 = nullptr;
+ const Vert *v1 = nullptr;
+ const Vert *v2 = nullptr;
/* left_face and right_face are indices into FaceMergeState->face. */
int left_face = -1;
int right_face = -1;
@@ -2581,7 +2585,7 @@ struct MergeEdge {
MergeEdge() = default;
- MergeEdge(Vertp va, Vertp vb)
+ MergeEdge(const Vert *va, const Vert *vb)
{
if (va->id < vb->id) {
this->v1 = va;
@@ -2596,7 +2600,7 @@ struct MergeEdge {
struct MergeFace {
/* The current sequence of Verts forming this face. */
- Vector<Vertp> vert;
+ Vector<const Vert *> vert;
/* For each position in face, what is index in FaceMergeState of edge for that position? */
Vector<int> edge;
/* If not -1, merge_to gives a face index in FaceMergeState that this is merged to. */
@@ -2611,7 +2615,7 @@ struct FaceMergeState {
* information (their left and right faces) and whether or not they are dissolvable.
*/
Vector<MergeEdge> edge;
- /* edge_map maps a pair of Vertp ids (in canonical order: smaller id first)
+ /* edge_map maps a pair of const Vert * ids (in canonical order: smaller id first)
* to the index in the above edge vector in which to find the corresonding MergeEdge.
*/
Map<std::pair<int, int>, int> edge_map;
@@ -2623,7 +2627,7 @@ static std::ostream &operator<<(std::ostream &os, const FaceMergeState &fms)
for (int f : fms.face.index_range()) {
const MergeFace &mf = fms.face[f];
std::cout << f << ": orig=" << mf.orig << " verts ";
- for (Vertp v : mf.vert) {
+ for (const Vert *v : mf.vert) {
std::cout << v << " ";
}
std::cout << "\n";
@@ -2646,7 +2650,7 @@ static std::ostream &operator<<(std::ostream &os, const FaceMergeState &fms)
*/
static void init_face_merge_state(FaceMergeState *fms,
const Vector<int> &tris,
- const Mesh &tm,
+ const IMesh &tm,
const double3 &norm)
{
constexpr int dbg_level = 0;
@@ -2777,10 +2781,10 @@ static bool dissolve_leaves_valid_bmesh(FaceMergeState *fms,
* One could avoid this O(n^2) algorithm if had a structure saying which faces a vertex touches.
*/
for (int a_v_index = 0; ok && a_v_index < alen; ++a_v_index) {
- Vertp a_v = mf_left.vert[a_v_index];
+ const Vert *a_v = mf_left.vert[a_v_index];
if (a_v != me.v1 && a_v != me.v2) {
for (int b_v_index = 0; b_v_index < blen; ++b_v_index) {
- Vertp b_v = mf_right.vert[b_v_index];
+ const Vert *b_v = mf_right.vert[b_v_index];
if (a_v == b_v) {
ok = false;
}
@@ -2804,7 +2808,7 @@ static void splice_faces(
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());
- Vector<Vertp> splice_vert;
+ Vector<const Vert *> splice_vert;
Vector<int> splice_edge;
splice_vert.reserve(alen + blen - 2);
splice_edge.reserve(alen + blen - 2);
@@ -2846,7 +2850,7 @@ static void splice_faces(
}
/* Given that fms has been properly initialized to contain a set of faces that
- * together form a face or part of a face of the original Mesh, and that
+ * together form a face or part of a face of the original IMesh, and that
* it has properly recorded with faces are dissolvable, dissolve as many edges as possible.
* We try to dissolve in decreasing order of edge length, so that it is more likely
* that the final output doesn't have awkward looking long edges with extreme angles.
@@ -2904,17 +2908,17 @@ static void do_dissolve(FaceMergeState *fms)
* Note: it is possible that some of the triangles in tris have reversed orientation
* to the rest, so we have to handle the two cases separately.
*/
-static Vector<Facep> merge_tris_for_face(Vector<int> tris,
- const Mesh &tm,
- const Mesh &pm_in,
- MArena *arena)
+static Vector<const Face *> merge_tris_for_face(Vector<int> tris,
+ const IMesh &tm,
+ const IMesh &pm_in,
+ IMeshArena *arena)
{
constexpr int dbg_level = 0;
if (dbg_level > 0) {
std::cout << "merge_tris_for_face\n";
std::cout << "tris: " << tris << "\n";
}
- Vector<Facep> ans;
+ Vector<const Face *> ans;
if (tris.size() <= 1) {
if (tris.size() == 1) {
ans.append(tm.face(tris[0]));
@@ -2930,7 +2934,7 @@ static Vector<Facep> merge_tris_for_face(Vector<int> tris,
*/
const Face &tri1 = *tm.face(tris[0]);
const Face &tri2 = *tm.face(tris[1]);
- Facep in_face = pm_in.face(tri1.orig);
+ const Face *in_face = pm_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) {
@@ -2975,7 +2979,7 @@ static Vector<Facep> merge_tris_for_face(Vector<int> tris,
e_orig[i] = fms.edge[mf.edge[i]].orig;
is_intersect[i] = fms.edge[mf.edge[i]].is_intersect;
}
- Facep facep = arena->add_face(mf.vert, mf.orig, e_orig, is_intersect);
+ const Face *facep = arena->add_face(mf.vert, mf.orig, e_orig, is_intersect);
ans.append(facep);
if (dbg_level > 0) {
std::cout << " " << facep << "\n";
@@ -2991,7 +2995,7 @@ static Vector<Facep> merge_tris_for_face(Vector<int> tris,
* 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(Mesh &pm_out, int *r_count_dissolve)
+static Array<bool> find_dissolve_verts(IMesh &pm_out, int *r_count_dissolve)
{
pm_out.populate_vert();
/* dissolve[i] will say whether pm_out.vert(i) can be dissolved. */
@@ -3004,19 +3008,19 @@ static Array<bool> find_dissolve_verts(Mesh &pm_out, int *r_count_dissolve)
* of the vertex v in position i of pm_out.vert.
* If we encounter a third, then v will not be dissolvable.
*/
- Array<std::pair<Vertp, Vertp>> neighbors(pm_out.vert_size(),
- std::pair<Vertp, Vertp>(nullptr, nullptr));
+ 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);
for (int i : face.index_range()) {
- Vertp v = face[i];
+ const Vert *v = face[i];
int v_index = pm_out.lookup_vert(v);
BLI_assert(v_index != NO_INDEX);
if (dissolve[v_index]) {
- Vertp n1 = face[face.next_pos(i)];
- Vertp n2 = face[face.prev_pos(i)];
- Vertp f_n1 = neighbors[v_index].first;
- Vertp f_n2 = neighbors[v_index].second;
+ const Vert *n1 = face[face.next_pos(i)];
+ const Vert *n2 = face[face.prev_pos(i)];
+ const Vert *f_n1 = neighbors[v_index].first;
+ const Vert *f_n2 = neighbors[v_index].second;
if (f_n1 != nullptr) {
/* Already has a neighbor in another face; can't dissolve unless they are the same. */
if (!((n1 == f_n2 && n2 == f_n1) || (n1 == f_n1 && n2 == f_n2))) {
@@ -3026,7 +3030,7 @@ static Array<bool> find_dissolve_verts(Mesh &pm_out, int *r_count_dissolve)
}
else {
/* These are the first-seen neighbors. */
- neighbors[v_index] = std::pair<Vertp, Vertp>(n1, n2);
+ neighbors[v_index] = std::pair<const Vert *, const Vert *>(n1, n2);
}
}
}
@@ -3035,7 +3039,7 @@ static Array<bool> find_dissolve_verts(Mesh &pm_out, int *r_count_dissolve)
for (int v_out : pm_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<Vertp, Vertp> &nbrs = neighbors[v_out];
+ const std::pair<const Vert *, const Vert *> &nbrs = neighbors[v_out];
if (nbrs.first != nullptr) {
BLI_assert(nbrs.second != nullptr);
const mpq3 &co1 = nbrs.first->co_exact;
@@ -3061,7 +3065,7 @@ static Array<bool> find_dissolve_verts(Mesh &pm_out, int *r_count_dissolve)
* 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.
*/
-static void dissolve_verts(Mesh *pm, const Array<bool> dissolve, MArena *arena)
+static void dissolve_verts(IMesh *pm, const Array<bool> dissolve, IMeshArena *arena)
{
constexpr int inline_face_size = 100;
Vector<bool, inline_face_size> face_pos_erase;
@@ -3069,7 +3073,7 @@ static void dissolve_verts(Mesh *pm, const Array<bool> dissolve, MArena *arena)
const Face &face = *pm->face(f);
face_pos_erase.clear();
int num_erase = 0;
- for (Vertp v : face) {
+ for (const Vert *v : face) {
int v_index = pm->lookup_vert(v);
BLI_assert(v_index != NO_INDEX);
if (dissolve[v_index]) {
@@ -3087,8 +3091,8 @@ static void dissolve_verts(Mesh *pm, const Array<bool> dissolve, MArena *arena)
pm->set_dirty_verts();
}
-/* The main boolean function operates on a triangle Mesh and produces a
- * Triangle Mesh as output.
+/* The main boolean function operates on a triangle IMesh and produces a
+ * Triangle IMesh as output.
* This function converts back into a general polygonal mesh by removing
* any possible triangulation edges (which can be identified because they
* will have an original edge that is NO_INDEX.
@@ -3097,9 +3101,9 @@ static void dissolve_verts(Mesh *pm, const Array<bool> dissolve, MArena *arena)
* the "valid BMesh" property: we can't produce output faces that have repeated vertices in them,
* or have several disconnected boundaries (e.g., faces with holes).
*/
-static Mesh polymesh_from_trimesh_with_dissolve(const Mesh &tm_out,
- const Mesh &pm_in,
- MArena *arena)
+static IMesh polymesh_from_trimesh_with_dissolve(const IMesh &tm_out,
+ const IMesh &pm_in,
+ IMeshArena *arena)
{
const int dbg_level = 0;
if (dbg_level > 1) {
@@ -3124,10 +3128,10 @@ static Mesh polymesh_from_trimesh_with_dissolve(const Mesh &tm_out,
}
/* Merge triangles that we can from face_output_tri to make faces for output.
- * face_output_face[f] will be new original Facep's that
+ * face_output_face[f] will be new original const Face *'s that
* make up whatever part of the boolean output remains of input face f.
*/
- Array<Vector<Facep>> face_output_face(tot_in_face);
+ Array<Vector<const Face *>> face_output_face(tot_in_face);
int tot_out_face = 0;
for (int in_f : pm_in.face_index_range()) {
if (dbg_level > 1) {
@@ -3140,16 +3144,16 @@ static Mesh polymesh_from_trimesh_with_dissolve(const Mesh &tm_out,
face_output_face[in_f] = merge_tris_for_face(face_output_tris[in_f], tm_out, pm_in, arena);
tot_out_face += face_output_face[in_f].size();
}
- Array<Facep> face(tot_out_face);
+ Array<const Face *> face(tot_out_face);
int out_f_index = 0;
for (int in_f : pm_in.face_index_range()) {
- const Vector<Facep> &f_faces = face_output_face[in_f];
+ 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();
}
}
- Mesh pm_out(face);
+ IMesh pm_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.
@@ -3172,12 +3176,12 @@ static Mesh polymesh_from_trimesh_with_dissolve(const Mesh &tm_out,
* The shape_fn function should take a triangle index in tm_in and return
* a number in the range 0 to nshapes-1, to say which shape that triangle is in.
*/
-Mesh boolean_trimesh(Mesh &tm_in,
- bool_optype op,
- int nshapes,
- std::function<int(int)> shape_fn,
- bool use_self,
- MArena *arena)
+IMesh boolean_trimesh(IMesh &tm_in,
+ bool_optype op,
+ int nshapes,
+ std::function<int(int)> shape_fn,
+ bool use_self,
+ IMeshArena *arena)
{
constexpr int dbg_level = 0;
if (dbg_level > 0) {
@@ -3190,9 +3194,9 @@ Mesh boolean_trimesh(Mesh &tm_in,
}
}
if (tm_in.face_size() == 0) {
- return Mesh(tm_in);
+ return IMesh(tm_in);
}
- Mesh tm_si;
+ IMesh tm_si;
if (use_self) {
tm_si = trimesh_self_intersect(tm_in, arena);
}
@@ -3210,7 +3214,7 @@ Mesh boolean_trimesh(Mesh &tm_in,
auto si_shape_fn = [shape_fn, tm_si](int t) { return shape_fn(tm_si.face(t)->orig); };
TriMeshTopology tm_si_topo(tm_si);
PatchesInfo pinfo = find_patches(tm_si, tm_si_topo);
- Mesh tm_out;
+ IMesh tm_out;
if (!is_pwn(tm_si, tm_si_topo)) {
if (dbg_level > 0) {
std::cout << "Input is not PWN, using gwn method\n";
@@ -3227,14 +3231,14 @@ Mesh boolean_trimesh(Mesh &tm_in,
if (!pc_ok) {
/* TODO: if bad input can lead to this, diagnose the problem. */
std::cout << "Something funny about input or a bug in boolean\n";
- return Mesh(tm_in);
+ return IMesh(tm_in);
}
cinfo.init_windings(nshapes);
int c_ambient = find_ambient_cell(tm_si, nullptr, tm_si_topo, pinfo, arena);
if (c_ambient == NO_INDEX) {
/* TODO: find a way to propagate this error to user properly. */
std::cout << "Could not find an ambient cell; input not valid?\n";
- return Mesh(tm_si);
+ 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);
@@ -3253,15 +3257,15 @@ Mesh boolean_trimesh(Mesh &tm_in,
return tm_out;
}
-static void dump_test_spec(Mesh &pm)
+static void dump_test_spec(IMesh &pm)
{
std::cout << "test spec = " << pm.vert_size() << " " << pm.face_size() << "\n";
- for (Vertp v : pm.vertices()) {
+ for (const Vert *v : pm.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 (Facep f : pm.faces()) {
- for (Vertp fv : *f) {
+ for (const Face *f : pm.faces()) {
+ for (const Vert *fv : *f) {
std::cout << pm.lookup_vert(fv) << " ";
}
std::cout << "\n";
@@ -3271,13 +3275,13 @@ static void dump_test_spec(Mesh &pm)
/* Do the boolean operation op on the polygon mesh pm_in.
* See the header file for a complete description.
*/
-Mesh boolean_mesh(Mesh &pm,
- bool_optype op,
- int nshapes,
- std::function<int(int)> shape_fn,
- bool use_self,
- Mesh *pm_triangulated,
- MArena *arena)
+IMesh boolean_mesh(IMesh &pm,
+ bool_optype op,
+ int nshapes,
+ std::function<int(int)> shape_fn,
+ bool use_self,
+ IMesh *pm_triangulated,
+ IMeshArena *arena)
{
constexpr int dbg_level = 0;
if (dbg_level > 0) {
@@ -3292,18 +3296,18 @@ Mesh boolean_mesh(Mesh &pm,
}
}
}
- Mesh *tm_in = pm_triangulated;
- Mesh our_triangulation;
+ IMesh *tm_in = pm_triangulated;
+ IMesh our_triangulation;
if (tm_in == nullptr) {
our_triangulation = triangulate_polymesh(pm, arena);
tm_in = &our_triangulation;
}
- Mesh tm_out = boolean_trimesh(*tm_in, op, nshapes, shape_fn, use_self, arena);
+ IMesh tm_out = boolean_trimesh(*tm_in, op, nshapes, shape_fn, use_self, arena);
if (dbg_level > 1) {
std::cout << "bool_trimesh_output:\n" << tm_out;
write_obj_mesh(tm_out, "bool_trimesh_output");
}
- Mesh ans = polymesh_from_trimesh_with_dissolve(tm_out, pm, arena);
+ IMesh ans = polymesh_from_trimesh_with_dissolve(tm_out, pm, 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 d0def5c06a2..50f7bb2a4ca 100644
--- a/source/blender/blenlib/intern/mesh_intersect.cc
+++ b/source/blender/blenlib/intern/mesh_intersect.cc
@@ -101,7 +101,7 @@ uint64_t Vert::hash() const
return co_exact.hash();
}
-std::ostream &operator<<(std::ostream &os, Vertp v)
+std::ostream &operator<<(std::ostream &os, const Vert *v)
{
os << "v" << v->id;
if (v->orig != NO_INDEX) {
@@ -177,7 +177,8 @@ std::ostream &operator<<(std::ostream &os, const Plane &plane)
return os;
}
-Face::Face(Span<Vertp> verts, int id, int orig, Span<int> edge_origs, Span<bool> is_intersect)
+Face::Face(
+ Span<const Vert *> verts, int id, int orig, Span<int> edge_origs, Span<bool> is_intersect)
: vert(verts), edge_orig(edge_origs), is_intersect(is_intersect), id(id), orig(orig)
{
mpq3 normal;
@@ -197,7 +198,7 @@ Face::Face(Span<Vertp> verts, int id, int orig, Span<int> edge_origs, Span<bool>
plane = Plane(normal, d);
}
-Face::Face(Span<Vertp> verts, int id, int orig) : vert(verts), id(id), orig(orig)
+Face::Face(Span<const Vert *> verts, int id, int orig) : vert(verts), id(id), orig(orig)
{
mpq3 normal;
if (vert.size() > 3) {
@@ -300,10 +301,10 @@ bool Face::cyclic_equal(const Face &other) const
return false;
}
-std::ostream &operator<<(std::ostream &os, Facep f)
+std::ostream &operator<<(std::ostream &os, const Face *f)
{
os << "f" << f->id << "o" << f->orig << "[";
- for (Vertp v : *f) {
+ for (const Vert *v : *f) {
os << "v" << v->id;
if (v->orig != NO_INDEX) {
os << "o" << v->orig;
@@ -330,7 +331,7 @@ std::ostream &operator<<(std::ostream &os, Facep f)
return os;
}
-/* MArena is the owner of the Vert and Face resources used
+/* IMeshArena is the owner of the Vert and Face resources used
* during a run of one of the meshintersect main functions.
* It also keeps has a hash table of all Verts created so that it can
* ensure that only one instance of a Vert with a given co_exact will
@@ -338,11 +339,11 @@ std::ostream &operator<<(std::ostream &os, Facep f)
*/
// #define USE_SPINLOCK
-class MArena::MArenaImpl {
+class IMeshArena::IMeshArenaImpl {
/* Don't use Vert itself as key since resizing may move
* pointers to the Vert around, and we need to have those pointers
- * stay the same throughout the lifetime of the MArena.
+ * stay the same throughout the lifetime of the IMeshArena.
*/
struct VSetKey {
Vert *vert;
@@ -381,7 +382,7 @@ class MArena::MArenaImpl {
# endif
public:
- MArenaImpl()
+ IMeshArenaImpl()
{
if (intersect_use_threading) {
# ifdef USE_SPINLOCK
@@ -391,9 +392,9 @@ class MArena::MArenaImpl {
# endif
}
}
- MArenaImpl(const MArenaImpl &) = delete;
- MArenaImpl(MArenaImpl &&) = delete;
- ~MArenaImpl()
+ IMeshArenaImpl(const IMeshArenaImpl &) = delete;
+ IMeshArenaImpl(IMeshArenaImpl &&) = delete;
+ ~IMeshArenaImpl()
{
if (intersect_use_threading) {
# ifdef USE_SPINLOCK
@@ -421,19 +422,22 @@ class MArena::MArenaImpl {
return allocated_faces_.size();
}
- Vertp add_or_find_vert(const mpq3 &co, int orig)
+ const Vert *add_or_find_vert(const mpq3 &co, int orig)
{
double3 dco(co[0].get_d(), co[1].get_d(), co[2].get_d());
return add_or_find_vert(co, dco, orig);
}
- Vertp add_or_find_vert(const double3 &co, int orig)
+ const Vert *add_or_find_vert(const double3 &co, int orig)
{
mpq3 mco(co[0], co[1], co[2]);
return add_or_find_vert(mco, co, orig);
}
- Facep add_face(Span<Vertp> verts, int orig, Span<int> edge_origs, Span<bool> is_intersect)
+ const Face *add_face(Span<const Vert *> verts,
+ int orig,
+ Span<int> edge_origs,
+ Span<bool> is_intersect)
{
Face *f = new Face(verts, next_face_id_++, orig, edge_origs, is_intersect);
if (intersect_use_threading) {
@@ -454,22 +458,22 @@ class MArena::MArenaImpl {
return f;
}
- Facep add_face(Span<Vertp> verts, int orig, Span<int> edge_origs)
+ const Face *add_face(Span<const Vert *> verts, int orig, Span<int> edge_origs)
{
Array<bool> is_intersect(verts.size(), false);
return add_face(verts, orig, edge_origs, is_intersect);
}
- Facep add_face(Span<Vertp> verts, int orig)
+ const Face *add_face(Span<const Vert *> verts, int orig)
{
Array<int> edge_origs(verts.size(), NO_INDEX);
Array<bool> is_intersect(verts.size(), false);
return add_face(verts, orig, edge_origs, is_intersect);
}
- Vertp find_vert(const mpq3 &co)
+ const Vert *find_vert(const mpq3 &co)
{
- Vertp ans;
+ const Vert *ans;
Vert vtry(co, double3(), NO_INDEX, NO_INDEX);
VSetKey vskey(&vtry);
if (intersect_use_threading) {
@@ -500,7 +504,7 @@ class MArena::MArenaImpl {
* Since it is only used for that purpose, access is not lock-protected.
* The argument vs can be a cyclic shift of the actual stored Face.
*/
- Facep find_face(Span<Vertp> vs)
+ const Face *find_face(Span<const Vert *> vs)
{
Array<int> eorig(vs.size(), NO_INDEX);
Array<bool> is_intersect(vs.size(), false);
@@ -514,11 +518,11 @@ class MArena::MArenaImpl {
}
private:
- Vertp add_or_find_vert(const mpq3 &mco, const double3 &dco, int orig)
+ const Vert *add_or_find_vert(const mpq3 &mco, const double3 &dco, int orig)
{
/* Don't allocate Vert yet, in case it is already there. */
Vert vtry(mco, dco, NO_INDEX, NO_INDEX);
- Vertp ans;
+ const Vert *ans;
VSetKey vskey(&vtry);
if (intersect_use_threading) {
# ifdef USE_SPINLOCK
@@ -555,77 +559,80 @@ class MArena::MArenaImpl {
};
};
-MArena::MArena()
+IMeshArena::IMeshArena()
{
- pimpl_ = std::unique_ptr<MArenaImpl>(new MArenaImpl());
+ pimpl_ = std::unique_ptr<IMeshArenaImpl>(new IMeshArenaImpl());
}
-MArena::~MArena()
+IMeshArena::~IMeshArena()
{
}
-void MArena::reserve(int vert_num_hint, int face_num_hint)
+void IMeshArena::reserve(int vert_num_hint, int face_num_hint)
{
pimpl_->reserve(vert_num_hint, face_num_hint);
}
-int MArena::tot_allocated_verts() const
+int IMeshArena::tot_allocated_verts() const
{
return pimpl_->tot_allocated_verts();
}
-int MArena::tot_allocated_faces() const
+int IMeshArena::tot_allocated_faces() const
{
return pimpl_->tot_allocated_faces();
}
-Vertp MArena::add_or_find_vert(const mpq3 &co, int orig)
+const Vert *IMeshArena::add_or_find_vert(const mpq3 &co, int orig)
{
return pimpl_->add_or_find_vert(co, orig);
}
-Facep MArena::add_face(Span<Vertp> verts, int orig, Span<int> edge_origs, Span<bool> is_intersect)
+const Face *IMeshArena::add_face(Span<const Vert *> verts,
+ int orig,
+ Span<int> edge_origs,
+ Span<bool> is_intersect)
{
return pimpl_->add_face(verts, orig, edge_origs, is_intersect);
}
-Facep MArena::add_face(Span<Vertp> verts, int orig, Span<int> edge_origs)
+const Face *IMeshArena::add_face(Span<const Vert *> verts, int orig, Span<int> edge_origs)
{
return pimpl_->add_face(verts, orig, edge_origs);
}
-Facep MArena::add_face(Span<Vertp> verts, int orig)
+const Face *IMeshArena::add_face(Span<const Vert *> verts, int orig)
{
return pimpl_->add_face(verts, orig);
}
-Vertp MArena::add_or_find_vert(const double3 &co, int orig)
+const Vert *IMeshArena::add_or_find_vert(const double3 &co, int orig)
{
return pimpl_->add_or_find_vert(co, orig);
}
-Vertp MArena::find_vert(const mpq3 &co) const
+const Vert *IMeshArena::find_vert(const mpq3 &co) const
{
return pimpl_->find_vert(co);
}
-Facep MArena::find_face(Span<Vertp> verts) const
+const Face *IMeshArena::find_face(Span<const Vert *> verts) const
{
return pimpl_->find_face(verts);
}
-void Mesh::set_faces(Span<Facep> faces)
+void IMesh::set_faces(Span<const Face *> faces)
{
face_ = faces;
}
-int Mesh::lookup_vert(Vertp v) const
+int IMesh::lookup_vert(const Vert *v) const
{
BLI_assert(vert_populated_);
return vert_to_index_.lookup_default(v, NO_INDEX);
}
-void Mesh::populate_vert()
+void IMesh::populate_vert()
{
/* This is likely an overestimate, since verts are shared between
* faces. It is ok if estimate is over or even under.
@@ -635,15 +642,15 @@ void Mesh::populate_vert()
populate_vert(estimate_num_verts);
}
-void Mesh::populate_vert(int max_verts)
+void IMesh::populate_vert(int max_verts)
{
if (vert_populated_) {
return;
}
vert_to_index_.reserve(max_verts);
int next_allocate_index = 0;
- for (Facep f : face_) {
- for (Vertp v : *f) {
+ for (const Face *f : face_) {
+ for (const Vert *v : *f) {
if (v->id == 1) {
}
int index = vert_to_index_.lookup_default(v, NO_INDEX);
@@ -654,7 +661,7 @@ void Mesh::populate_vert(int max_verts)
}
}
int tot_v = next_allocate_index;
- vert_ = Array<Vertp>(tot_v);
+ vert_ = Array<const Vert *>(tot_v);
for (auto item : vert_to_index_.items()) {
int index = item.value;
BLI_assert(index < tot_v);
@@ -666,7 +673,7 @@ void Mesh::populate_vert(int max_verts)
*/
const bool fix_order = true;
if (fix_order) {
- std::sort(vert_.begin(), vert_.end(), [](Vertp a, Vertp b) {
+ std::sort(vert_.begin(), vert_.end(), [](const Vert *a, const Vert *b) {
if (a->orig != NO_INDEX && b->orig != NO_INDEX) {
return a->orig < b->orig;
}
@@ -679,16 +686,16 @@ void Mesh::populate_vert(int max_verts)
return a->id < b->id;
});
for (int i : vert_.index_range()) {
- Vertp v = vert_[i];
+ const Vert *v = vert_[i];
vert_to_index_.add_overwrite(v, i);
}
}
vert_populated_ = true;
}
-void Mesh::erase_face_positions(int f_index, Span<bool> face_pos_erase, MArena *arena)
+void IMesh::erase_face_positions(int f_index, Span<bool> face_pos_erase, IMeshArena *arena)
{
- Facep cur_f = this->face(f_index);
+ const Face *cur_f = this->face(f_index);
int cur_len = static_cast<int>(cur_f->size());
int num_to_erase = 0;
for (int i : cur_f->index_range()) {
@@ -704,7 +711,7 @@ void Mesh::erase_face_positions(int f_index, Span<bool> face_pos_erase, MArena *
/* Invalid erase. Don't do anything. */
return;
}
- Array<Vertp> new_vert(new_len);
+ Array<const Vert *> new_vert(new_len);
Array<int> new_edge_orig(new_len);
Array<bool> new_is_intersect(new_len);
int new_index = 0;
@@ -720,19 +727,19 @@ void Mesh::erase_face_positions(int f_index, Span<bool> face_pos_erase, MArena *
this->face_[f_index] = arena->add_face(new_vert, cur_f->orig, new_edge_orig, new_is_intersect);
}
-std::ostream &operator<<(std::ostream &os, const Mesh &mesh)
+std::ostream &operator<<(std::ostream &os, const IMesh &mesh)
{
if (mesh.has_verts()) {
os << "Verts:\n";
int i = 0;
- for (Vertp v : mesh.vertices()) {
+ for (const Vert *v : mesh.vertices()) {
os << i << ": " << v << "\n";
++i;
}
}
os << "\nFaces:\n";
int i = 0;
- for (Facep f : mesh.faces()) {
+ for (const Face *f : mesh.faces()) {
os << i << ": " << f << "\n";
os << " plane=" << f->plane << " eorig=[";
for (Face::FacePos p = 0; p < f->size(); ++p) {
@@ -828,14 +835,14 @@ static bool bbs_might_intersect(const BoundingBox &bb_a, const BoundingBox &bb_b
* the "less than" tests in isect_aabb_aabb_v3 are sufficient to detect
* touching or overlap.
*/
-static Array<BoundingBox> calc_face_bounding_boxes(const Mesh &m)
+static Array<BoundingBox> calc_face_bounding_boxes(const IMesh &m)
{
double max_abs_val = 0.0;
Array<BoundingBox> ans(m.face_size());
for (int f : m.face_index_range()) {
const Face &face = *m.face(f);
BoundingBox &bb = ans[f];
- for (Vertp v : face) {
+ for (const Vert *v : face) {
bb.combine(v->co);
for (int i = 0; i < 3; ++i) {
max_abs_val = max_dd(max_abs_val, fabs(v->co[i]));
@@ -1210,7 +1217,7 @@ static bool non_trivially_2d_intersect(const mpq2 *a[3], const mpq2 *b[3])
* the triangles in cl, and that proj_axis is a good axis to project down
* to solve this problem in 2d.
*/
-static bool non_trivially_coplanar_intersects(const Mesh &tm,
+static bool non_trivially_coplanar_intersects(const IMesh &tm,
int t,
const CoplanarCluster &cl,
int proj_axis)
@@ -1251,16 +1258,16 @@ static bool non_trivially_coplanar_intersects(const Mesh &tm,
* something other than a common vertex or a common edge?
* The itt value is the result of calling intersect_tri_tri on tri1, tri2.
*/
-static bool non_trivial_intersect(const ITT_value &itt, Facep tri1, Facep tri2)
+static bool non_trivial_intersect(const ITT_value &itt, const Face * tri1, const Face * tri2)
{
if (itt.kind == INONE) {
return false;
}
- Facep tris[2] = {tri1, tri2};
+ const Face * tris[2] = {tri1, tri2};
if (itt.kind == IPOINT) {
bool has_p_as_vert[2] {false, false};
for (int i = 0; i < 2; ++i) {
- for (Vertp v : *tris[i]) {
+ for (const Vert * v : *tris[i]) {
if (itt.p1 == v->co_exact) {
has_p_as_vert[i] = true;
break;
@@ -1433,7 +1440,7 @@ static int filter_orient3d(const double3 &a, const double3 &b, const double3 &c,
* mpq3 test would also have returned that value.
* When the return value is 0, we are not sure of the sign.
*/
-static int filter_tri_plane_vert_orient3d(const Face &tri, Vertp v)
+static int filter_tri_plane_vert_orient3d(const Face &tri, const Vert *v)
{
return filter_orient3d(tri[0]->co, tri[1]->co, tri[2]->co, v->co);
}
@@ -1512,7 +1519,7 @@ static int filter_plane_side(const double3 &p,
* where triangles share an edge or a vertex, but don't
* otherwise intersect.
*/
-static bool may_non_trivially_intersect(Facep t1, Facep t2)
+static bool may_non_trivially_intersect(const Face *t1, const Face *t2)
{
const Face &tri1 = *t1;
const Face &tri2 = *t2;
@@ -1520,9 +1527,9 @@ static bool may_non_trivially_intersect(Facep t1, Facep t2)
Face::FacePos share2_pos[3];
int n_shared = 0;
for (Face::FacePos p1 = 0; p1 < 3; ++p1) {
- Vertp v1 = tri1[p1];
+ const Vert *v1 = tri1[p1];
for (Face::FacePos p2 = 0; p2 < 3; ++p2) {
- Vertp v2 = tri2[p2];
+ const Vert *v2 = tri2[p2];
if (v1 == v2) {
share1_pos[n_shared] = p1;
share2_pos[n_shared] = p2;
@@ -1555,16 +1562,16 @@ static bool may_non_trivially_intersect(Facep t1, Facep t2)
* they are more expensive to check).
*/
Face::FacePos p = share2_pos[0];
- Vertp v2a = p == 0 ? tri2[1] : tri2[0];
- Vertp v2b = (p == 0 || p == 1) ? tri2[2] : tri2[1];
+ const Vert *v2a = p == 0 ? tri2[1] : tri2[0];
+ const Vert *v2b = (p == 0 || p == 1) ? tri2[2] : tri2[1];
int o1 = filter_tri_plane_vert_orient3d(tri1, v2a);
int o2 = filter_tri_plane_vert_orient3d(tri1, v2b);
if (o1 == o2 && o1 != 0) {
return false;
}
p = share1_pos[0];
- Vertp v1a = p == 0 ? tri1[1] : tri1[0];
- Vertp v1b = (p == 0 || p == 1) ? tri1[2] : tri1[1];
+ const Vert *v1a = p == 0 ? tri1[1] : tri1[0];
+ const Vert *v1b = (p == 0 || p == 1) ? tri1[2] : tri1[1];
o1 = filter_tri_plane_vert_orient3d(tri2, v1a);
o2 = filter_tri_plane_vert_orient3d(tri2, v1b);
if (o1 == o2 && o1 != 0) {
@@ -1599,7 +1606,7 @@ static inline mpq3 tti_interp(const mpq3 &a, const mpq3 &b, const mpq3 &c, const
/* Return +1, 0, -1 as a + ad is above, on, or below the oriented plane containing a, b, c in CCW
* order. This is the same as -oriented(a, b, c, a + ad), but uses fewer arithmetic operations.
- * TODO: change arguments to Vertp and use floating filters.
+ * TODO: change arguments to const Vert * and use floating filters.
*/
static inline int tti_above(const mpq3 &a, const mpq3 &b, const mpq3 &c, const mpq3 &ad)
{
@@ -1783,7 +1790,7 @@ static ITT_value itt_canon1(const mpq3 &p1,
return ITT_value(ICOPLANAR);
}
-static ITT_value intersect_tri_tri(const Mesh &tm, int t1, int t2)
+static ITT_value intersect_tri_tri(const IMesh &tm, int t1, int t2)
{
constexpr int dbg_level = 0;
# ifdef PERFDEBUG
@@ -1791,12 +1798,12 @@ static ITT_value intersect_tri_tri(const Mesh &tm, int t1, int t2)
# endif
const Face &tri1 = *tm.face(t1);
const Face &tri2 = *tm.face(t2);
- Vertp vp1 = tri1[0];
- Vertp vq1 = tri1[1];
- Vertp vr1 = tri1[2];
- Vertp vp2 = tri2[0];
- Vertp vq2 = tri2[1];
- Vertp vr2 = tri2[2];
+ const Vert *vp1 = tri1[0];
+ const Vert *vq1 = tri1[1];
+ const Vert *vr1 = tri1[2];
+ const Vert *vp2 = tri2[0];
+ const Vert *vq2 = tri2[1];
+ const Vert *vr2 = tri2[2];
if (dbg_level > 0) {
std::cout << "\nINTERSECT_TRI_TRI t1=" << t1 << ", t2=" << t2 << "\n";
std::cout << " p1 = " << vp1 << "\n";
@@ -1992,7 +1999,7 @@ struct CDT_data {
Vector<mpq2> vert;
Vector<std::pair<int, int>> edge;
Vector<Vector<int>> face;
- Vector<int> input_face; /* Parallels face, gives id from input Mesh of input face. */
+ Vector<int> input_face; /* Parallels face, gives id from input IMesh of input face. */
Vector<bool> is_reversed; /* Parallels face, says if input face orientation is opposite. */
CDT_result<mpq_class> cdt_out; /* Result of running CDT on input with (vert, edge, face). */
int proj_axis;
@@ -2053,7 +2060,7 @@ static void prepare_need_edge(CDT_data &cd, const mpq3 &p1, const mpq3 &p2)
cd.edge.append(std::pair<int, int>(v1, v2));
}
-static void prepare_need_tri(CDT_data &cd, const Mesh &tm, int t)
+static void prepare_need_tri(CDT_data &cd, const IMesh &tm, int t)
{
const Face &tri = *tm.face(t);
int v0 = prepare_need_vert(cd, tri[0]->co_exact);
@@ -2087,7 +2094,7 @@ static void prepare_need_tri(CDT_data &cd, const Mesh &tm, int t)
cd.is_reversed.append(rev);
}
-static CDT_data prepare_cdt_input(const Mesh &tm, int t, const Vector<ITT_value> itts)
+static CDT_data prepare_cdt_input(const IMesh &tm, int t, const Vector<ITT_value> itts)
{
CDT_data ans;
ans.t_plane = tm.face(t)->plane;
@@ -2112,7 +2119,7 @@ static CDT_data prepare_cdt_input(const Mesh &tm, int t, const Vector<ITT_value>
return ans;
}
-static CDT_data prepare_cdt_input_for_cluster(const Mesh &tm,
+static CDT_data prepare_cdt_input_for_cluster(const IMesh &tm,
const CoplanarClusterInfo &clinfo,
int c,
const Vector<ITT_value> itts)
@@ -2205,7 +2212,7 @@ static void do_cdt(CDT_data &cd)
}
static int get_cdt_edge_orig(
- int i0, int i1, const CDT_data &cd, const Mesh &in_tm, bool *r_is_intersect)
+ int i0, int i1, const CDT_data &cd, const IMesh &in_tm, bool *r_is_intersect)
{
int foff = cd.cdt_out.face_edge_offset;
*r_is_intersect = false;
@@ -2226,7 +2233,7 @@ static int get_cdt_edge_orig(
*/
int in_tm_face_index = cd.input_face[in_face_index];
BLI_assert(in_tm_face_index < in_tm.face_size());
- Facep facep = in_tm.face(in_tm_face_index);
+ const Face *facep = in_tm.face(in_tm_face_index);
BLI_assert(pos < facep->size());
bool is_rev = cd.is_reversed[in_face_index];
int eorig = is_rev ? facep->edge_orig[2 - pos] : facep->edge_orig[pos];
@@ -2252,10 +2259,13 @@ static int get_cdt_edge_orig(
return NO_INDEX;
}
-/* Using the result of CDT in cd.cdt_out, extract a Mesh representing the subdivision
+/* Using the result of CDT in cd.cdt_out, extract an IMesh representing the subdivision
* of input triangle t, which should be an element of cd.input_face.
*/
-static Mesh extract_subdivided_tri(const CDT_data &cd, const Mesh &in_tm, int t, MArena *arena)
+static IMesh extract_subdivided_tri(const CDT_data &cd,
+ const IMesh &in_tm,
+ int t,
+ IMeshArena *arena)
{
const CDT_result<mpq_class> &cdt_out = cd.cdt_out;
int t_in_cdt = -1;
@@ -2267,11 +2277,11 @@ static Mesh extract_subdivided_tri(const CDT_data &cd, const Mesh &in_tm, int t,
if (t_in_cdt == -1) {
std::cout << "Could not find " << t << " in cdt input tris\n";
BLI_assert(false);
- return Mesh();
+ return IMesh();
}
int t_orig = in_tm.face(t)->orig;
constexpr int inline_buf_size = 20;
- Vector<Facep, inline_buf_size> faces;
+ Vector<const Face *, inline_buf_size> faces;
for (int f : cdt_out.face.index_range()) {
if (cdt_out.face_orig[f].contains(t_in_cdt)) {
BLI_assert(cdt_out.face[f].size() == 3);
@@ -2285,10 +2295,10 @@ static Mesh extract_subdivided_tri(const CDT_data &cd, const Mesh &in_tm, int t,
* an original one, then it will already be in the arena
* with the correct orig field.
*/
- Vertp v0 = arena->add_or_find_vert(v0co, NO_INDEX);
- Vertp v1 = arena->add_or_find_vert(v1co, NO_INDEX);
- Vertp v2 = arena->add_or_find_vert(v2co, NO_INDEX);
- Facep facep;
+ const Vert *v0 = arena->add_or_find_vert(v0co, NO_INDEX);
+ const Vert *v1 = arena->add_or_find_vert(v1co, NO_INDEX);
+ const Vert *v2 = arena->add_or_find_vert(v2co, NO_INDEX);
+ const Face *facep;
bool is_isect0;
bool is_isect1;
bool is_isect2;
@@ -2309,13 +2319,13 @@ static Mesh extract_subdivided_tri(const CDT_data &cd, const Mesh &in_tm, int t,
faces.append(facep);
}
}
- return Mesh(faces);
+ return IMesh(faces);
}
-static Mesh extract_single_tri(const Mesh &tm, int t)
+static IMesh extract_single_tri(const IMesh &tm, int t)
{
- Facep f = tm.face(t);
- return Mesh({f});
+ const Face *f = tm.face(t);
+ return IMesh({f});
}
static bool bvhtreeverlap_cmp(const BVHTreeOverlap &a, const BVHTreeOverlap &b)
@@ -2335,14 +2345,14 @@ class TriOverlaps {
uint overlap_tot_{0};
struct CBData {
- const Mesh &tm;
+ const IMesh &tm;
std::function<int(int)> shape_fn;
int nshapes;
bool use_self;
};
public:
- TriOverlaps(const Mesh &tm,
+ TriOverlaps(const IMesh &tm,
const Array<BoundingBox> &tri_bb,
int nshapes,
std::function<int(int)> shape_fn,
@@ -2464,10 +2474,10 @@ class TriOverlaps {
struct OverlapIttsData {
Vector<std::pair<int, int>> intersect_pairs;
Map<std::pair<int, int>, ITT_value> &itt_map;
- const Mesh &tm;
- MArena *arena;
+ const IMesh &tm;
+ IMeshArena *arena;
- OverlapIttsData(Map<std::pair<int, int>, ITT_value> &itt_map, const Mesh &tm, MArena *arena)
+ OverlapIttsData(Map<std::pair<int, int>, ITT_value> &itt_map, const IMesh &tm, IMeshArena *arena)
: itt_map(itt_map), tm(tm), arena(arena)
{
}
@@ -2499,10 +2509,10 @@ static void calc_overlap_itts_range_func(void *__restrict userdata,
* intersection for those will be handled by CDT, later.
*/
static void calc_overlap_itts(Map<std::pair<int, int>, ITT_value> &itt_map,
- const Mesh &tm,
+ const IMesh &tm,
const CoplanarClusterInfo &clinfo,
const TriOverlaps &ov,
- MArena *arena)
+ IMeshArena *arena)
{
OverlapIttsData data(itt_map, tm, arena);
/* Put dummy values in itt_map intially, so map entries will exist when doing the range function.
@@ -2541,11 +2551,11 @@ struct OverlapTriRange {
int len;
};
struct SubdivideTrisData {
- Array<Mesh> &r_tri_subdivided;
- const Mesh &tm;
+ Array<IMesh> &r_tri_subdivided;
+ const IMesh &tm;
const Map<std::pair<int, int>, ITT_value> &itt_map;
Span<BVHTreeOverlap> overlap;
- MArena *arena;
+ IMeshArena *arena;
/* This vector gives, for each tri in tm that has an intersection
* we want to calculate: what the index of that tri in tm is,
@@ -2554,11 +2564,11 @@ struct SubdivideTrisData {
*/
Vector<OverlapTriRange> overlap_tri_range;
- SubdivideTrisData(Array<Mesh> &r_tri_subdivided,
- const Mesh &tm,
+ SubdivideTrisData(Array<IMesh> &r_tri_subdivided,
+ const IMesh &tm,
const Map<std::pair<int, int>, ITT_value> &itt_map,
Span<BVHTreeOverlap> overlap,
- MArena *arena)
+ IMeshArena *arena)
: r_tri_subdivided(r_tri_subdivided),
tm(tm),
itt_map(itt_map),
@@ -2618,12 +2628,12 @@ static void calc_subdivided_tri_range_func(void *__restrict userdata,
* But don't do this for triangles that are part of a cluster.
* Also, do nothing here if the answer is just the triangle itself.
*/
-static void calc_subdivided_tris(Array<Mesh> &r_tri_subdivided,
- const Mesh &tm,
+static void calc_subdivided_tris(Array<IMesh> &r_tri_subdivided,
+ const IMesh &tm,
const Map<std::pair<int, int>, ITT_value> &itt_map,
const CoplanarClusterInfo &clinfo,
const TriOverlaps &ov,
- MArena *arena)
+ IMeshArena *arena)
{
const int dbg_level = 0;
if (dbg_level > 0) {
@@ -2687,10 +2697,10 @@ static int find_first_overlap_index(const TriOverlaps &ov, int t)
static CDT_data calc_cluster_subdivided(const CoplanarClusterInfo &clinfo,
int c,
- const Mesh &tm,
+ const IMesh &tm,
const TriOverlaps &ov,
const Map<std::pair<int, int>, ITT_value> &itt_map,
- MArena *UNUSED(arena))
+ IMeshArena *UNUSED(arena))
{
constexpr int dbg_level = 0;
BLI_assert(c < clinfo.tot_cluster());
@@ -2743,23 +2753,23 @@ static CDT_data calc_cluster_subdivided(const CoplanarClusterInfo &clinfo,
return cd_data;
}
-static Mesh union_tri_subdivides(const blender::Array<Mesh> &tri_subdivided)
+static IMesh union_tri_subdivides(const blender::Array<IMesh> &tri_subdivided)
{
int tot_tri = 0;
- for (const Mesh &m : tri_subdivided) {
+ for (const IMesh &m : tri_subdivided) {
tot_tri += m.face_size();
}
- Array<Facep> faces(tot_tri);
+ Array<const Face *> faces(tot_tri);
int face_index = 0;
- for (const Mesh &m : tri_subdivided) {
- for (Facep f : m.faces()) {
+ for (const IMesh &m : tri_subdivided) {
+ for (const Face *f : m.faces()) {
faces[face_index++] = f;
}
}
- return Mesh(faces);
+ return IMesh(faces);
}
-static CoplanarClusterInfo find_clusters(const Mesh &tm, const Array<BoundingBox> &tri_bb)
+static CoplanarClusterInfo find_clusters(const IMesh &tm, const Array<BoundingBox> &tri_bb)
{
constexpr int dbg_level = 0;
if (dbg_level > 0) {
@@ -2849,12 +2859,12 @@ static CoplanarClusterInfo find_clusters(const Mesh &tm, const Array<BoundingBox
return ans;
}
-static bool face_is_degenerate(Facep f)
+static bool face_is_degenerate(const Face *f)
{
const Face &face = *f;
- Vertp v0 = face[0];
- Vertp v1 = face[1];
- Vertp v2 = face[2];
+ const Vert *v0 = face[0];
+ const Vert *v1 = face[1];
+ const Vert *v2 = face[2];
if (v0 == v1 || v0 == v2 || v1 == v2) {
return true;
}
@@ -2876,10 +2886,10 @@ static bool face_is_degenerate(Facep f)
return false;
}
-/* Does TriMesh tm have any triangles with zero area? */
-static bool has_degenerate_tris(const Mesh &tm)
+/* Does triangle IMesh tm have any triangles with zero area? */
+static bool has_degenerate_tris(const IMesh &tm)
{
- for (Facep f : tm.faces()) {
+ for (const Face *f : tm.faces()) {
if (face_is_degenerate(f)) {
return true;
}
@@ -2887,12 +2897,12 @@ static bool has_degenerate_tris(const Mesh &tm)
return false;
}
-static Mesh remove_degenerate_tris(const Mesh &tm_in)
+static IMesh remove_degenerate_tris(const IMesh &tm_in)
{
- Mesh ans;
- Vector<Facep> new_faces;
+ IMesh ans;
+ Vector<const Face *> new_faces;
new_faces.reserve(tm_in.face_size());
- for (Facep f : tm_in.faces()) {
+ for (const Face *f : tm_in.faces()) {
if (!face_is_degenerate(f)) {
new_faces.append(f);
}
@@ -2902,20 +2912,23 @@ static Mesh remove_degenerate_tris(const Mesh &tm_in)
}
/* This is the main routine for calculating the self_intersection of a triangle mesh. */
-Mesh trimesh_self_intersect(const Mesh &tm_in, MArena *arena)
+IMesh trimesh_self_intersect(const IMesh &tm_in, IMeshArena *arena)
{
return trimesh_nary_intersect(
tm_in, 1, [](int) { return 0; }, true, arena);
}
-Mesh trimesh_nary_intersect(
- const Mesh &tm_in, int nshapes, std::function<int(int)> shape_fn, bool use_self, MArena *arena)
+IMesh trimesh_nary_intersect(const IMesh &tm_in,
+ int nshapes,
+ std::function<int(int)> shape_fn,
+ bool use_self,
+ IMeshArena *arena)
{
constexpr int dbg_level = 0;
if (dbg_level > 0) {
std::cout << "\nTRIMESH_NARY_INTERSECT nshapes=" << nshapes << " use_self=" << use_self
<< "\n";
- for (Facep f : tm_in.faces()) {
+ for (const Face *f : tm_in.faces()) {
BLI_assert(f->is_tri());
UNUSED_VARS_NDEBUG(f);
}
@@ -2929,8 +2942,8 @@ Mesh trimesh_nary_intersect(
/* Usually can use tm_in but if it has degenerate or illegal triangles,
* then need to work on a copy of it without those triangles.
*/
- const Mesh *tm_clean = &tm_in;
- Mesh tm_cleaned;
+ const IMesh *tm_clean = &tm_in;
+ IMesh tm_cleaned;
if (has_degenerate_tris(tm_in)) {
if (dbg_level > 0) {
std::cout << "cleaning degenerate triangles\n";
@@ -2959,7 +2972,7 @@ Mesh trimesh_nary_intersect(
Map<std::pair<int, int>, ITT_value> itt_map;
itt_map.reserve(tri_ov.overlap().size());
calc_overlap_itts(itt_map, *tm_clean, clinfo, tri_ov, arena);
- Array<Mesh> tri_subdivided(tm_clean->face_size());
+ Array<IMesh> tri_subdivided(tm_clean->face_size());
calc_subdivided_tris(tri_subdivided, *tm_clean, itt_map, clinfo, tri_ov, arena);
Array<CDT_data> cluster_subdivided(clinfo.tot_cluster());
for (int c : clinfo.index_range()) {
@@ -2975,7 +2988,7 @@ Mesh trimesh_nary_intersect(
tri_subdivided[t] = extract_single_tri(*tm_clean, t);
}
}
- Mesh combined = union_tri_subdivides(tri_subdivided);
+ IMesh combined = union_tri_subdivides(tri_subdivided);
if (dbg_level > 1) {
std::cout << "TRIMESH_NARY_INTERSECT answer:\n";
std::cout << combined;
@@ -3032,7 +3045,7 @@ static std::ostream &operator<<(std::ostream &os, const ITT_value &itt)
}
/* Writing the obj_mesh has the side effect of populating verts. */
-void write_obj_mesh(Mesh &m, const std::string &objname)
+void write_obj_mesh(IMesh &m, const std::string &objname)
{
/* Would like to use BKE_tempdir_base() here, but that brings in dependence on kernel library.
* This is just for developer debugging anyway, and should never be called in production Blender.
@@ -3057,15 +3070,15 @@ void write_obj_mesh(Mesh &m, const std::string &objname)
if (!m.has_verts()) {
m.populate_vert();
}
- for (Vertp v : m.vertices()) {
+ for (const Vert *v : m.vertices()) {
const double3 dv = v->co;
f << "v " << dv[0] << " " << dv[1] << " " << dv[2] << "\n";
}
int i = 0;
- for (Facep face : m.faces()) {
+ for (const Face *face : m.faces()) {
/* OBJ files use 1-indexing for vertices. */
f << "f ";
- for (Vertp v : *face) {
+ for (const Vert *v : *face) {
int i = m.lookup_vert(v);
BLI_assert(i != NO_INDEX);
/* OBJ files use 1-indexing for vertices. */
diff --git a/source/blender/blenlib/tests/BLI_mesh_boolean_test.cc b/source/blender/blenlib/tests/BLI_mesh_boolean_test.cc
index 2cd6fdc6b4f..397a86d98c3 100644
--- a/source/blender/blenlib/tests/BLI_mesh_boolean_test.cc
+++ b/source/blender/blenlib/tests/BLI_mesh_boolean_test.cc
@@ -19,11 +19,11 @@ namespace blender::meshintersect {
constexpr bool DO_OBJ = false;
-/* Build and hold a Mesh from a string spec. Also hold and own resources used by Mesh. */
-class MeshBuilder {
+/* Build and hold an IMesh from a string spec. Also hold and own resources used by IMesh. */
+class IMeshBuilder {
public:
- Mesh mesh;
- MArena arena;
+ IMesh imesh;
+ IMeshArena arena;
/* "Edge orig" indices are an encoding of <input face#, position in face of start of edge>. */
static constexpr int MAX_FACE_LEN = 1000; /* Used for forming "orig edge" indices only. */
@@ -44,7 +44,7 @@ class MeshBuilder {
* mpq_class mpq_class mpq_clas [#verts lines]
* int int int ... [#faces lines; indices into verts for given face]
*/
- MeshBuilder(const char *spec)
+ IMeshBuilder(const char *spec)
{
std::istringstream ss(spec);
std::string line;
@@ -56,8 +56,8 @@ class MeshBuilder {
return;
}
arena.reserve(nv, nf);
- Vector<Vertp> verts;
- Vector<Facep> faces;
+ Vector<const Vert *> verts;
+ Vector<const Face *> faces;
bool spec_ok = true;
int v_index = 0;
while (v_index < nv && spec_ok && getline(ss, line)) {
@@ -76,7 +76,7 @@ class MeshBuilder {
int f_index = 0;
while (f_index < nf && spec_ok && getline(ss, line)) {
std::istringstream fss(line);
- Vector<Vertp> face_verts;
+ Vector<const Vert *> face_verts;
Vector<int> edge_orig;
int fpos = 0;
while (spec_ok && fss >> v_index) {
@@ -88,7 +88,7 @@ class MeshBuilder {
edge_orig.append(edge_index(f_index, fpos));
++fpos;
}
- Facep facep = arena.add_face(face_verts, f_index, edge_orig);
+ const Face *facep = arena.add_face(face_verts, f_index, edge_orig);
faces.append(facep);
++f_index;
}
@@ -99,15 +99,15 @@ class MeshBuilder {
std::cout << "Bad spec: " << spec;
return;
}
- mesh = Mesh(faces);
+ imesh = IMesh(faces);
}
};
TEST(boolean_trimesh, Empty)
{
- MArena arena;
- Mesh in;
- Mesh out = boolean_trimesh(
+ IMeshArena arena;
+ IMesh in;
+ IMesh out = boolean_trimesh(
in, BOOLEAN_NONE, 1, [](int) { return 0; }, true, &arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 0);
@@ -135,9 +135,9 @@ TEST(boolean_trimesh, TetTetTrimesh)
6 4 7
)";
- MeshBuilder mb(spec);
- Mesh out = boolean_trimesh(
- mb.mesh, BOOLEAN_NONE, 1, [](int) { return 0; }, true, &mb.arena);
+ IMeshBuilder mb(spec);
+ IMesh out = boolean_trimesh(
+ mb.imesh, BOOLEAN_NONE, 1, [](int) { return 0; }, true, &mb.arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 11);
EXPECT_EQ(out.face_size(), 20);
@@ -145,9 +145,9 @@ TEST(boolean_trimesh, TetTetTrimesh)
write_obj_mesh(out, "tettet_tm");
}
- MeshBuilder mb2(spec);
- Mesh out2 = boolean_trimesh(
- mb2.mesh, BOOLEAN_UNION, 1, [](int) { return 0; }, true, &mb2.arena);
+ IMeshBuilder mb2(spec);
+ IMesh out2 = boolean_trimesh(
+ mb2.imesh, BOOLEAN_UNION, 1, [](int) { return 0; }, true, &mb2.arena);
out2.populate_vert();
EXPECT_EQ(out2.vert_size(), 10);
EXPECT_EQ(out2.face_size(), 16);
@@ -155,9 +155,9 @@ TEST(boolean_trimesh, TetTetTrimesh)
write_obj_mesh(out2, "tettet_union_tm");
}
- MeshBuilder mb3(spec);
- Mesh out3 = boolean_trimesh(
- mb3.mesh, BOOLEAN_UNION, 2, [](int t) { return t < 4 ? 0 : 1; }, false, &mb3.arena);
+ IMeshBuilder mb3(spec);
+ IMesh out3 = boolean_trimesh(
+ mb3.imesh, BOOLEAN_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);
@@ -165,9 +165,9 @@ TEST(boolean_trimesh, TetTetTrimesh)
write_obj_mesh(out3, "tettet_union_binary_tm");
}
- MeshBuilder mb4(spec);
- Mesh out4 = boolean_trimesh(
- mb4.mesh, BOOLEAN_UNION, 2, [](int t) { return t < 4 ? 0 : 1; }, true, &mb4.arena);
+ IMeshBuilder mb4(spec);
+ IMesh out4 = boolean_trimesh(
+ mb4.imesh, BOOLEAN_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);
@@ -175,9 +175,9 @@ TEST(boolean_trimesh, TetTetTrimesh)
write_obj_mesh(out4, "tettet_union_binary_self_tm");
}
- MeshBuilder mb5(spec);
- Mesh out5 = boolean_trimesh(
- mb5.mesh, BOOLEAN_ISECT, 2, [](int t) { return t < 4 ? 0 : 1; }, false, &mb5.arena);
+ IMeshBuilder mb5(spec);
+ IMesh out5 = boolean_trimesh(
+ mb5.imesh, BOOLEAN_ISECT, 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);
@@ -185,9 +185,9 @@ TEST(boolean_trimesh, TetTetTrimesh)
write_obj_mesh(out5, "tettet_intersect_binary_tm");
}
- MeshBuilder mb6(spec);
- Mesh out6 = boolean_trimesh(
- mb6.mesh, BOOLEAN_DIFFERENCE, 2, [](int t) { return t < 4 ? 0 : 1; }, false, &mb6.arena);
+ IMeshBuilder mb6(spec);
+ IMesh out6 = boolean_trimesh(
+ mb6.imesh, BOOLEAN_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);
@@ -195,9 +195,9 @@ TEST(boolean_trimesh, TetTetTrimesh)
write_obj_mesh(out6, "tettet_difference_binary_tm");
}
- MeshBuilder mb7(spec);
- Mesh out7 = boolean_trimesh(
- mb7.mesh, BOOLEAN_DIFFERENCE, 2, [](int t) { return t < 4 ? 1 : 0; }, false, &mb7.arena);
+ IMeshBuilder mb7(spec);
+ IMesh out7 = boolean_trimesh(
+ mb7.imesh, BOOLEAN_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);
@@ -227,9 +227,9 @@ TEST(boolean_trimesh, TetTet2Trimesh)
6 7 4
)";
- MeshBuilder mb(spec);
- Mesh out = boolean_trimesh(
- mb.mesh, BOOLEAN_UNION, 1, [](int) { return 0; }, true, &mb.arena);
+ IMeshBuilder mb(spec);
+ IMesh out = boolean_trimesh(
+ mb.imesh, BOOLEAN_UNION, 1, [](int) { return 0; }, true, &mb.arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 10);
EXPECT_EQ(out.face_size(), 16);
@@ -271,9 +271,9 @@ TEST(boolean_trimesh, CubeTetTrimesh)
10 11 8
)";
- MeshBuilder mb(spec);
- Mesh out = boolean_trimesh(
- mb.mesh, BOOLEAN_UNION, 1, [](int) { return 0; }, true, &mb.arena);
+ IMeshBuilder mb(spec);
+ IMesh out = boolean_trimesh(
+ mb.imesh, BOOLEAN_UNION, 1, [](int) { return 0; }, true, &mb.arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 14);
EXPECT_EQ(out.face_size(), 24);
@@ -303,9 +303,9 @@ TEST(boolean_trimesh, BinaryTetTetTrimesh)
6 4 7
)";
- MeshBuilder mb(spec);
- Mesh out = boolean_trimesh(
- mb.mesh, BOOLEAN_ISECT, 2, [](int t) { return t < 4 ? 0 : 1; }, false, &mb.arena);
+ IMeshBuilder mb(spec);
+ IMesh out = boolean_trimesh(
+ mb.imesh, BOOLEAN_ISECT, 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);
@@ -335,9 +335,9 @@ TEST(boolean_trimesh, TetTetCoplanarTrimesh)
6 4 7
)";
- MeshBuilder mb(spec);
- Mesh out = boolean_trimesh(
- mb.mesh, BOOLEAN_UNION, 1, [](int) { return 0; }, true, &mb.arena);
+ IMeshBuilder mb(spec);
+ IMesh out = boolean_trimesh(
+ mb.imesh, BOOLEAN_UNION, 1, [](int) { return 0; }, true, &mb.arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 5);
EXPECT_EQ(out.face_size(), 6);
@@ -367,9 +367,9 @@ TEST(boolean_trimesh, TetInsideTetTrimesh)
6 4 7
)";
- MeshBuilder mb(spec);
- Mesh out = boolean_trimesh(
- mb.mesh, BOOLEAN_UNION, 1, [](int) { return 0; }, true, &mb.arena);
+ IMeshBuilder mb(spec);
+ IMesh out = boolean_trimesh(
+ mb.imesh, BOOLEAN_UNION, 1, [](int) { return 0; }, true, &mb.arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 4);
EXPECT_EQ(out.face_size(), 4);
@@ -399,9 +399,9 @@ TEST(boolean_trimesh, TetBesideTetTrimesh)
6 4 7
)";
- MeshBuilder mb(spec);
- Mesh out = boolean_trimesh(
- mb.mesh, BOOLEAN_UNION, 1, [](int) { return 0; }, true, &mb.arena);
+ IMeshBuilder mb(spec);
+ IMesh out = boolean_trimesh(
+ mb.imesh, BOOLEAN_UNION, 1, [](int) { return 0; }, true, &mb.arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 8);
EXPECT_EQ(out.face_size(), 8);
@@ -435,9 +435,9 @@ TEST(boolean_trimesh, DegenerateTris)
0 1 9
)";
- MeshBuilder mb(spec);
- Mesh out = boolean_trimesh(
- mb.mesh, BOOLEAN_ISECT, 2, [](int t) { return t < 5 ? 0 : 1; }, false, &mb.arena);
+ IMeshBuilder mb(spec);
+ IMesh out = boolean_trimesh(
+ mb.imesh, BOOLEAN_ISECT, 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);
@@ -467,9 +467,9 @@ TEST(boolean_polymesh, TetTet)
6 4 7
)";
- MeshBuilder mb(spec);
- Mesh out = boolean_mesh(
- mb.mesh, BOOLEAN_NONE, 1, [](int) { return 0; }, true, nullptr, &mb.arena);
+ IMeshBuilder mb(spec);
+ IMesh out = boolean_mesh(
+ mb.imesh, BOOLEAN_NONE, 1, [](int) { return 0; }, true, nullptr, &mb.arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 11);
EXPECT_EQ(out.face_size(), 13);
@@ -477,9 +477,9 @@ TEST(boolean_polymesh, TetTet)
write_obj_mesh(out, "tettet");
}
- MeshBuilder mb2(spec);
- Mesh out2 = boolean_mesh(
- mb2.mesh, BOOLEAN_NONE, 2, [](int t) { return t < 4 ? 0 : 1; }, false, nullptr, &mb2.arena);
+ IMeshBuilder mb2(spec);
+ IMesh out2 = boolean_mesh(
+ mb2.imesh, BOOLEAN_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);
@@ -521,12 +521,12 @@ TEST(boolean_polymesh, CubeCube)
11 9 13 15
)";
- MeshBuilder mb(spec);
+ IMeshBuilder mb(spec);
if (DO_OBJ) {
- write_obj_mesh(mb.mesh, "cube_cube_in");
+ write_obj_mesh(mb.imesh, "cube_cube_in");
}
- Mesh out = boolean_mesh(
- mb.mesh, BOOLEAN_UNION, 1, [](int UNUSED(t)) { return 0; }, true, nullptr, &mb.arena);
+ IMesh out = boolean_mesh(
+ mb.imesh, BOOLEAN_UNION, 1, [](int UNUSED(t)) { return 0; }, true, nullptr, &mb.arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 20);
EXPECT_EQ(out.face_size(), 12);
@@ -534,9 +534,9 @@ TEST(boolean_polymesh, CubeCube)
write_obj_mesh(out, "cubecube_union");
}
- MeshBuilder mb2(spec);
- Mesh out2 = boolean_mesh(
- mb2.mesh, BOOLEAN_NONE, 2, [](int t) { return t < 6 ? 0 : 1; }, false, nullptr, &mb2.arena);
+ IMeshBuilder mb2(spec);
+ IMesh out2 = boolean_mesh(
+ mb2.imesh, BOOLEAN_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);
@@ -575,9 +575,9 @@ TEST(boolean_polymesh, CubeCone)
13 11 8
8 9 10 12 13)";
- MeshBuilder mb(spec);
- Mesh out = boolean_mesh(
- mb.mesh, BOOLEAN_UNION, 1, [](int UNUSED(t)) { return 0; }, true, nullptr, &mb.arena);
+ IMeshBuilder mb(spec);
+ IMesh out = boolean_mesh(
+ mb.imesh, BOOLEAN_UNION, 1, [](int UNUSED(t)) { return 0; }, true, nullptr, &mb.arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 14);
EXPECT_EQ(out.face_size(), 12);
@@ -619,9 +619,9 @@ TEST(boolean_polymesh, CubeCubeCoplanar)
15 11 9 13
)";
- MeshBuilder mb(spec);
- Mesh out = boolean_mesh(
- mb.mesh, BOOLEAN_UNION, 2, [](int t) { return t < 6 ? 0 : 1; }, false, nullptr, &mb.arena);
+ IMeshBuilder mb(spec);
+ IMesh out = boolean_mesh(
+ mb.imesh, BOOLEAN_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);
@@ -651,9 +651,9 @@ TEST(boolean_polymesh, TetTeTCoplanarDiff)
6 4 7
)";
- MeshBuilder mb(spec);
- Mesh out = boolean_mesh(
- mb.mesh,
+ IMeshBuilder mb(spec);
+ IMesh out = boolean_mesh(
+ mb.imesh,
BOOLEAN_DIFFERENCE,
2,
[](int t) { return t < 4 ? 0 : 1; },
@@ -701,9 +701,9 @@ TEST(boolean_polymesh, CubeCubeStep)
15 11 9 13
)";
- MeshBuilder mb(spec);
- Mesh out = boolean_mesh(
- mb.mesh,
+ IMeshBuilder mb(spec);
+ IMesh out = boolean_mesh(
+ mb.imesh,
BOOLEAN_DIFFERENCE,
2,
[](int t) { return t < 6 ? 0 : 1; },
@@ -751,9 +751,9 @@ TEST(boolean_polymesh, CubeCyl4)
15 11 9 13
)";
- MeshBuilder mb(spec);
- Mesh out = boolean_mesh(
- mb.mesh,
+ IMeshBuilder mb(spec);
+ IMesh out = boolean_mesh(
+ mb.imesh,
BOOLEAN_DIFFERENCE,
2,
[](int t) { return t < 6 ? 1 : 0; },
@@ -822,9 +822,9 @@ TEST(boolean_polymesh, CubeCubesubdivDiff)
23 25 21 19
)";
- MeshBuilder mb(spec);
- Mesh out = boolean_mesh(
- mb.mesh,
+ IMeshBuilder mb(spec);
+ IMesh out = boolean_mesh(
+ mb.imesh,
BOOLEAN_DIFFERENCE,
2,
[](int t) { return t < 16 ? 1 : 0; },
@@ -863,9 +863,9 @@ TEST(boolean_polymesh, CubePlane)
11 7 5 9
)";
- MeshBuilder mb(spec);
- Mesh out = boolean_mesh(
- mb.mesh,
+ IMeshBuilder mb(spec);
+ IMesh out = boolean_mesh(
+ mb.imesh,
BOOLEAN_DIFFERENCE,
2,
[](int t) { return t >= 1 ? 0 : 1; },
diff --git a/source/blender/blenlib/tests/BLI_mesh_intersect_test.cc b/source/blender/blenlib/tests/BLI_mesh_intersect_test.cc
index 014e0e29ade..bb5e213364f 100644
--- a/source/blender/blenlib/tests/BLI_mesh_intersect_test.cc
+++ b/source/blender/blenlib/tests/BLI_mesh_intersect_test.cc
@@ -22,11 +22,11 @@ namespace blender::meshintersect {
constexpr bool DO_OBJ = false;
-/* Build and hold a Mesh from a string spec. Also hold and own resources used by Mesh. */
-class MeshBuilder {
+/* Build and hold an IMesh from a string spec. Also hold and own resources used by IMesh. */
+class IMeshBuilder {
public:
- Mesh mesh;
- MArena arena;
+ IMesh imesh;
+ IMeshArena arena;
/* "Edge orig" indices are an encoding of <input face#, position in face of start of edge>. */
static constexpr int MAX_FACE_LEN = 1000; /* Used for forming "orig edge" indices only. */
@@ -47,7 +47,7 @@ class MeshBuilder {
* mpq_class mpq_class mpq_clas [#verts lines]
* int int int ... [#faces lines; indices into verts for given face]
*/
- MeshBuilder(const char *spec)
+ IMeshBuilder(const char *spec)
{
std::istringstream ss(spec);
std::string line;
@@ -59,8 +59,8 @@ class MeshBuilder {
return;
}
arena.reserve(nv, nf);
- Vector<Vertp> verts;
- Vector<Facep> faces;
+ Vector<const Vert *> verts;
+ Vector<const Face *> faces;
bool spec_ok = true;
int v_index = 0;
while (v_index < nv && spec_ok && getline(ss, line)) {
@@ -81,7 +81,7 @@ class MeshBuilder {
int f_index = 0;
while (f_index < nf && spec_ok && getline(ss, line)) {
std::istringstream fss(line);
- Vector<Vertp> face_verts;
+ Vector<const Vert *> face_verts;
Vector<int> edge_orig;
int fpos = 0;
while (spec_ok && fss >> v_index) {
@@ -97,7 +97,7 @@ class MeshBuilder {
spec_ok = false;
}
if (spec_ok) {
- Facep facep = arena.add_face(face_verts, f_index, edge_orig);
+ const Face *facep = arena.add_face(face_verts, f_index, edge_orig);
faces.append(facep);
}
++f_index;
@@ -109,17 +109,20 @@ class MeshBuilder {
std::cout << "Bad spec: " << spec;
return;
}
- mesh = Mesh(faces);
+ imesh = IMesh(faces);
}
};
-/* Return a Facep in mesh with verts equal to v0, v1, and v2, in
+/* Return a const Face * in mesh with verts equal to v0, v1, and v2, in
* some cyclic order; return nullptr if not found.
*/
-static Facep find_tri_with_verts(const Mesh &mesh, Vertp v0, Vertp v1, Vertp v2)
+static const Face *find_tri_with_verts(const IMesh &mesh,
+ const Vert *v0,
+ const Vert *v1,
+ const Vert *v2)
{
Face f_arg({v0, v1, v2}, 0, NO_INDEX);
- for (Facep f : mesh.faces()) {
+ for (const Face *f : mesh.faces()) {
if (f->cyclic_equal(f_arg)) {
return f;
}
@@ -128,11 +131,11 @@ static Facep find_tri_with_verts(const Mesh &mesh, Vertp v0, Vertp v1, Vertp v2)
}
/* How many instances of a triangle with v0, v1, v2 are in the mesh? */
-static int count_tris_with_verts(const Mesh &mesh, Vertp v0, Vertp v1, Vertp v2)
+static int count_tris_with_verts(const IMesh &mesh, const Vert *v0, const Vert *v1, const Vert *v2)
{
Face f_arg({v0, v1, v2}, 0, NO_INDEX);
int ans = 0;
- for (Facep f : mesh.faces()) {
+ for (const Face *f : mesh.faces()) {
if (f->cyclic_equal(f_arg)) {
++ans;
}
@@ -142,7 +145,7 @@ static int count_tris_with_verts(const Mesh &mesh, Vertp v0, Vertp v1, Vertp v2)
/* What is the starting position, if any, of the edge (v0, v1), in either order, in f? -1 if none.
*/
-static int find_edge_pos_in_tri(Vertp v0, Vertp v1, Facep f)
+static int find_edge_pos_in_tri(const Vert *v0, const Vert *v1, const Face *f)
{
for (int pos : f->index_range()) {
int nextpos = f->next_pos(pos);
@@ -156,17 +159,17 @@ static int find_edge_pos_in_tri(Vertp v0, Vertp v1, Facep f)
#if DO_REGULAR_TESTS
TEST(mesh_intersect, Mesh)
{
- Vector<Vertp> verts;
- Vector<Facep> faces;
- MArena arena;
+ Vector<const Vert *> verts;
+ Vector<const Face *> faces;
+ IMeshArena arena;
verts.append(arena.add_or_find_vert(mpq3(0, 0, 1), 0));
verts.append(arena.add_or_find_vert(mpq3(1, 0, 1), 1));
verts.append(arena.add_or_find_vert(mpq3(0.5, 1, 1), 2));
faces.append(arena.add_face(verts, 0, {10, 11, 12}));
- Mesh mesh(faces);
- Facep f = mesh.face(0);
+ IMesh mesh(faces);
+ const Face *f = mesh.face(0);
EXPECT_TRUE(f->is_tri());
EXPECT_EQ(f->plane.norm, double3(0.0, 0.0, 1.0));
EXPECT_EQ(f->plane.d, -1.0);
@@ -181,12 +184,12 @@ TEST(mesh_intersect, OneTri)
0 1 2
)";
- MeshBuilder mb(spec);
- Mesh imesh = trimesh_self_intersect(mb.mesh, &mb.arena);
+ IMeshBuilder mb(spec);
+ IMesh imesh = trimesh_self_intersect(mb.imesh, &mb.arena);
imesh.populate_vert();
EXPECT_EQ(imesh.vert_size(), 3);
EXPECT_EQ(imesh.face_size(), 1);
- const Face f_in = *mb.mesh.face(0);
+ const Face f_in = *mb.imesh.face(0);
const Face f_out = *imesh.face(0);
EXPECT_EQ(f_in.orig, f_out.orig);
for (int i = 0; i < 3; ++i) {
@@ -209,29 +212,29 @@ TEST(mesh_intersect, TriTri)
)";
/* Second triangle is smaller and congruent to first, resting on same base, partway along. */
- MeshBuilder mb(spec);
- Mesh out = trimesh_self_intersect(mb.mesh, &mb.arena);
+ IMeshBuilder mb(spec);
+ IMesh out = trimesh_self_intersect(mb.imesh, &mb.arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 6);
EXPECT_EQ(out.face_size(), 6);
if (out.vert_size() == 6 && out.face_size() == 6) {
- Vertp v0 = mb.arena.find_vert(mpq3(0, 0, 0));
- Vertp v1 = mb.arena.find_vert(mpq3(4, 0, 0));
- Vertp v2 = mb.arena.find_vert(mpq3(0, 4, 0));
- Vertp v3 = mb.arena.find_vert(mpq3(1, 0, 0));
- Vertp v4 = mb.arena.find_vert(mpq3(2, 0, 0));
- Vertp v5 = mb.arena.find_vert(mpq3(1, 1, 0));
+ const Vert *v0 = mb.arena.find_vert(mpq3(0, 0, 0));
+ const Vert *v1 = mb.arena.find_vert(mpq3(4, 0, 0));
+ const Vert *v2 = mb.arena.find_vert(mpq3(0, 4, 0));
+ const Vert *v3 = mb.arena.find_vert(mpq3(1, 0, 0));
+ const Vert *v4 = mb.arena.find_vert(mpq3(2, 0, 0));
+ const Vert *v5 = mb.arena.find_vert(mpq3(1, 1, 0));
EXPECT_TRUE(v0 != nullptr && v1 != nullptr && v2 != nullptr);
EXPECT_TRUE(v3 != nullptr && v4 != nullptr && v5 != nullptr);
if (v0 != nullptr && v1 != nullptr && v2 != nullptr && v3 != nullptr && v4 != nullptr &&
v5 != nullptr) {
EXPECT_EQ(v0->orig, 0);
EXPECT_EQ(v1->orig, 1);
- Facep f0 = find_tri_with_verts(out, v4, v1, v5);
- Facep f1 = find_tri_with_verts(out, v3, v4, v5);
- Facep f2 = find_tri_with_verts(out, v0, v3, v5);
- Facep f3 = find_tri_with_verts(out, v0, v5, v2);
- Facep f4 = find_tri_with_verts(out, v5, v1, v2);
+ const Face *f0 = find_tri_with_verts(out, v4, v1, v5);
+ const Face *f1 = find_tri_with_verts(out, v3, v4, v5);
+ const Face *f2 = find_tri_with_verts(out, v0, v3, v5);
+ const Face *f3 = find_tri_with_verts(out, v0, v5, v2);
+ const Face *f4 = find_tri_with_verts(out, v5, v1, v2);
EXPECT_TRUE(f0 != nullptr && f1 != nullptr && f2 != nullptr && f3 != nullptr &&
f4 != nullptr);
/* For boolean to work right, there need to be two copies of the smaller triangle in the
@@ -255,8 +258,8 @@ TEST(mesh_intersect, TriTri)
if (e03 != -1 && e34 != -1 && e45 != -1 && e05 != -1 && e15 != -1) {
EXPECT_EQ(f2->edge_orig[e03], 0);
EXPECT_TRUE(f1->edge_orig[e34] == 0 ||
- f1->edge_orig[e34] == 1 * MeshBuilder::MAX_FACE_LEN);
- EXPECT_EQ(f1->edge_orig[e45], 1 * MeshBuilder::MAX_FACE_LEN + 1);
+ f1->edge_orig[e34] == 1 * IMeshBuilder::MAX_FACE_LEN);
+ EXPECT_EQ(f1->edge_orig[e45], 1 * IMeshBuilder::MAX_FACE_LEN + 1);
EXPECT_EQ(f3->edge_orig[e05], NO_INDEX);
EXPECT_EQ(f0->edge_orig[e15], NO_INDEX);
}
@@ -283,29 +286,29 @@ TEST(mesh_intersect, TriTriReversed)
3 5 4
)";
- MeshBuilder mb(spec);
- Mesh out = trimesh_self_intersect(mb.mesh, &mb.arena);
+ IMeshBuilder mb(spec);
+ IMesh out = trimesh_self_intersect(mb.imesh, &mb.arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 6);
EXPECT_EQ(out.face_size(), 6);
if (out.vert_size() == 6 && out.face_size() == 6) {
- Vertp v0 = mb.arena.find_vert(mpq3(0, 0, 0));
- Vertp v1 = mb.arena.find_vert(mpq3(4, 0, 0));
- Vertp v2 = mb.arena.find_vert(mpq3(0, 4, 0));
- Vertp v3 = mb.arena.find_vert(mpq3(1, 0, 0));
- Vertp v4 = mb.arena.find_vert(mpq3(2, 0, 0));
- Vertp v5 = mb.arena.find_vert(mpq3(1, 1, 0));
+ const Vert *v0 = mb.arena.find_vert(mpq3(0, 0, 0));
+ const Vert *v1 = mb.arena.find_vert(mpq3(4, 0, 0));
+ const Vert *v2 = mb.arena.find_vert(mpq3(0, 4, 0));
+ const Vert *v3 = mb.arena.find_vert(mpq3(1, 0, 0));
+ const Vert *v4 = mb.arena.find_vert(mpq3(2, 0, 0));
+ const Vert *v5 = mb.arena.find_vert(mpq3(1, 1, 0));
EXPECT_TRUE(v0 != nullptr && v1 != nullptr && v2 != nullptr);
EXPECT_TRUE(v3 != nullptr && v4 != nullptr && v5 != nullptr);
if (v0 != nullptr && v1 != nullptr && v2 != nullptr && v3 != nullptr && v4 != nullptr &&
v5 != nullptr) {
EXPECT_EQ(v0->orig, 0);
EXPECT_EQ(v1->orig, 1);
- Facep f0 = find_tri_with_verts(out, v4, v5, v1);
- Facep f1 = find_tri_with_verts(out, v3, v5, v4);
- Facep f2 = find_tri_with_verts(out, v0, v5, v3);
- Facep f3 = find_tri_with_verts(out, v0, v2, v5);
- Facep f4 = find_tri_with_verts(out, v5, v2, v1);
+ const Face *f0 = find_tri_with_verts(out, v4, v5, v1);
+ const Face *f1 = find_tri_with_verts(out, v3, v5, v4);
+ const Face *f2 = find_tri_with_verts(out, v0, v5, v3);
+ const Face *f3 = find_tri_with_verts(out, v0, v2, v5);
+ const Face *f4 = find_tri_with_verts(out, v5, v2, v1);
EXPECT_TRUE(f0 != nullptr && f1 != nullptr && f2 != nullptr && f3 != nullptr &&
f4 != nullptr);
/* For boolean to work right, there need to be two copies of the smaller triangle in the
@@ -329,8 +332,8 @@ TEST(mesh_intersect, TriTriReversed)
if (e03 != -1 && e34 != -1 && e45 != -1 && e05 != -1 && e15 != -1) {
EXPECT_EQ(f2->edge_orig[e03], 2);
EXPECT_TRUE(f1->edge_orig[e34] == 2 ||
- f1->edge_orig[e34] == 1 * MeshBuilder::MAX_FACE_LEN + 2);
- EXPECT_EQ(f1->edge_orig[e45], 1 * MeshBuilder::MAX_FACE_LEN + 1);
+ f1->edge_orig[e34] == 1 * IMeshBuilder::MAX_FACE_LEN + 2);
+ EXPECT_EQ(f1->edge_orig[e45], 1 * IMeshBuilder::MAX_FACE_LEN + 1);
EXPECT_EQ(f3->edge_orig[e05], NO_INDEX);
EXPECT_EQ(f0->edge_orig[e15], NO_INDEX);
}
@@ -430,20 +433,20 @@ TEST(mesh_intersect, TwoTris)
if (do_all_perms && verbose) {
std::cout << "\nperms " << i << " " << j << "\n";
}
- MArena arena;
+ IMeshArena arena;
arena.reserve(2 * 3, 2);
- Array<Vertp> f0_verts(3);
- Array<Vertp> f1_verts(3);
+ Array<const Vert *> f0_verts(3);
+ Array<const Vert *> f1_verts(3);
for (int k = 0; k < 3; ++k) {
f0_verts[k] = arena.add_or_find_vert(verts[co1_i + perms[i][k]], k);
}
for (int k = 0; k < 3; ++k) {
f1_verts[k] = arena.add_or_find_vert(verts[co2_i + perms[i][k]], k + 3);
}
- Facep f0 = arena.add_face(f0_verts, 0, {0, 1, 2});
- Facep f1 = arena.add_face(f1_verts, 1, {3, 4, 5});
- Mesh in_mesh({f0, f1});
- Mesh out_mesh = trimesh_self_intersect(in_mesh, &arena);
+ const Face *f0 = arena.add_face(f0_verts, 0, {0, 1, 2});
+ const Face *f1 = arena.add_face(f1_verts, 1, {3, 4, 5});
+ IMesh in_mesh({f0, f1});
+ IMesh out_mesh = trimesh_self_intersect(in_mesh, &arena);
out_mesh.populate_vert();
EXPECT_EQ(out_mesh.vert_size(), test_tris[test].nv_out);
EXPECT_EQ(out_mesh.face_size(), test_tris[test].nf_out);
@@ -490,8 +493,8 @@ TEST(mesh_intersect, OverlapCluster)
6 7 8
)";
- MeshBuilder mb(spec);
- Mesh out = trimesh_self_intersect(mb.mesh, &mb.arena);
+ IMeshBuilder mb(spec);
+ IMesh out = trimesh_self_intersect(mb.imesh, &mb.arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 16);
EXPECT_EQ(out.face_size(), 18);
@@ -522,8 +525,8 @@ TEST(mesh_intersect, TriCornerCross1)
9 10 11
)";
- MeshBuilder mb(spec);
- Mesh out = trimesh_self_intersect(mb.mesh, &mb.arena);
+ IMeshBuilder mb(spec);
+ IMesh out = trimesh_self_intersect(mb.imesh, &mb.arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 10);
EXPECT_EQ(out.face_size(), 14);
@@ -554,8 +557,8 @@ TEST(mesh_intersect, TriCornerCross2)
9 10 11
)";
- MeshBuilder mb(spec);
- Mesh out = trimesh_self_intersect(mb.mesh, &mb.arena);
+ IMeshBuilder mb(spec);
+ IMesh out = trimesh_self_intersect(mb.imesh, &mb.arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 7);
EXPECT_EQ(out.face_size(), 8);
@@ -586,8 +589,8 @@ TEST(mesh_intersect, TriCornerCross3)
9 10 11
)";
- MeshBuilder mb(spec);
- Mesh out = trimesh_self_intersect(mb.mesh, &mb.arena);
+ IMeshBuilder mb(spec);
+ IMesh out = trimesh_self_intersect(mb.imesh, &mb.arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 10);
EXPECT_EQ(out.face_size(), 16);
@@ -617,18 +620,18 @@ TEST(mesh_intersect, TetTet)
6 7 4
)";
- MeshBuilder mb(spec);
- Mesh out = trimesh_self_intersect(mb.mesh, &mb.arena);
+ IMeshBuilder mb(spec);
+ IMesh out = trimesh_self_intersect(mb.imesh, &mb.arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 11);
EXPECT_EQ(out.face_size(), 20);
/* Expect there to be a triangle with these three verts, oriented this way, with original face 1.
*/
- Vertp v1 = mb.arena.find_vert(mpq3(2, 0, 0));
- Vertp v8 = mb.arena.find_vert(mpq3(0.5, 0.5, 1));
- Vertp v9 = mb.arena.find_vert(mpq3(1.5, 0.5, 1));
+ const Vert *v1 = mb.arena.find_vert(mpq3(2, 0, 0));
+ const Vert *v8 = mb.arena.find_vert(mpq3(0.5, 0.5, 1));
+ const Vert *v9 = mb.arena.find_vert(mpq3(1.5, 0.5, 1));
EXPECT_TRUE(v1 != nullptr && v8 != nullptr && v9 != nullptr);
- Facep f = mb.arena.find_face({v1, v8, v9});
+ const Face *f = mb.arena.find_face({v1, v8, v9});
EXPECT_NE(f, nullptr);
EXPECT_EQ(f->orig, 1);
int v1pos = f->vert[0] == v1 ? 0 : (f->vert[1] == v1 ? 1 : 2);
@@ -688,8 +691,8 @@ TEST(mesh_intersect, CubeCubeStep)
15 9 13
)";
- MeshBuilder mb(spec);
- Mesh out = trimesh_self_intersect(mb.mesh, &mb.arena);
+ IMeshBuilder mb(spec);
+ IMesh out = trimesh_self_intersect(mb.imesh, &mb.arena);
out.populate_vert();
EXPECT_EQ(out.vert_size(), 22);
EXPECT_EQ(out.face_size(), 56);
@@ -697,9 +700,9 @@ TEST(mesh_intersect, CubeCubeStep)
write_obj_mesh(out, "test_cubecubestep");
}
- MeshBuilder mb2(spec);
- Mesh out2 = trimesh_nary_intersect(
- mb2.mesh, 2, [](int t) { return t < 12 ? 0 : 1; }, false, &mb2.arena);
+ IMeshBuilder mb2(spec);
+ IMesh out2 = trimesh_nary_intersect(
+ mb2.imesh, 2, [](int t) { return t < 12 ? 0 : 1; }, false, &mb2.arena);
out2.populate_vert();
EXPECT_EQ(out2.vert_size(), 22);
EXPECT_EQ(out2.face_size(), 56);
@@ -728,16 +731,16 @@ static void fill_sphere_data(int nrings,
const double3 &center,
double radius,
bool triangulate,
- MutableSpan<Facep> face,
+ MutableSpan<const Face *> face,
int vid_start,
int fid_start,
- MArena *arena)
+ IMeshArena *arena)
{
int num_verts;
int num_faces;
get_sphere_params(nrings, nsegs, triangulate, &num_verts, &num_faces);
BLI_assert(num_faces == face.size());
- Array<Vertp> vert(num_verts);
+ Array<const Vert *> vert(num_verts);
const bool nrings_even = (nrings % 2 == 0);
int half_nrings = nrings / 2;
const bool nsegs_even = (nsegs % 2) == 0;
@@ -820,12 +823,14 @@ static void fill_sphere_data(int nrings,
double x = r_sin_theta * cos_phi + center[0];
double y = r_sin_theta * sin_phi + center[1];
double z = r_cos_theta + center[2];
- Vertp v = arena->add_or_find_vert(mpq3(x, y, z), vid++);
+ const Vert *v = arena->add_or_find_vert(mpq3(x, y, z), vid++);
vert[vert_index_fn(s, r)] = v;
}
}
- Vertp vtop = arena->add_or_find_vert(mpq3(center[0], center[1], center[2] + radius), vid++);
- Vertp vbot = arena->add_or_find_vert(mpq3(center[0], center[1], center[2] - radius), vid++);
+ const Vert *vtop = arena->add_or_find_vert(mpq3(center[0], center[1], center[2] + radius),
+ vid++);
+ const Vert *vbot = arena->add_or_find_vert(mpq3(center[0], center[1], center[2] - radius),
+ vid++);
vert[vert_index_fn(0, 0)] = vtop;
vert[vert_index_fn(0, nrings)] = vbot;
for (int s = 0; s < nsegs; ++s) {
@@ -836,8 +841,8 @@ static void fill_sphere_data(int nrings,
int i1 = vert_index_fn(s, rnext);
int i2 = vert_index_fn(snext, rnext);
int i3 = vert_index_fn(snext, r);
- Facep f;
- Facep f2 = nullptr;
+ const Face *f;
+ const Face *f2 = nullptr;
if (r == 0) {
f = arena->add_face({vert[i0], vert[i1], vert[i2]}, fid++, eid);
}
@@ -877,12 +882,12 @@ static void spheresphere_test(int nrings, double y_offset, bool use_self)
}
BLI_task_scheduler_init(); /* Without this, no parallelism. */
double time_start = PIL_check_seconds_timer();
- MArena arena;
+ IMeshArena arena;
int nsegs = 2 * nrings;
int num_sphere_verts;
int num_sphere_tris;
get_sphere_params(nrings, nsegs, true, &num_sphere_verts, &num_sphere_tris);
- Array<Facep> tris(2 * num_sphere_tris);
+ Array<const Face *> tris(2 * num_sphere_tris);
arena.reserve(2 * num_sphere_verts, 2 * num_sphere_tris);
double3 center1(0.0, 0.0, 0.0);
fill_sphere_data(nrings,
@@ -890,7 +895,7 @@ static void spheresphere_test(int nrings, double y_offset, bool use_self)
center1,
1.0,
true,
- MutableSpan<Facep>(tris.begin(), num_sphere_tris),
+ MutableSpan<const Face *>(tris.begin(), num_sphere_tris),
0,
0,
&arena);
@@ -900,14 +905,14 @@ static void spheresphere_test(int nrings, double y_offset, bool use_self)
center2,
1.0,
true,
- MutableSpan<Facep>(tris.begin() + num_sphere_tris, num_sphere_tris),
+ MutableSpan<const Face *>(tris.begin() + num_sphere_tris, num_sphere_tris),
num_sphere_verts,
num_sphere_verts,
&arena);
- Mesh mesh(tris);
+ IMesh mesh(tris);
double time_create = PIL_check_seconds_timer();
write_obj_mesh(mesh, "spheresphere_in");
- Mesh out;
+ IMesh out;
if (use_self) {
out = trimesh_self_intersect(mesh, &arena);
}
@@ -941,10 +946,10 @@ static void fill_grid_data(int x_subdiv,
bool triangulate,
double size,
const double3 &center,
- MutableSpan<Facep> face,
+ MutableSpan<const Face *> face,
int vid_start,
int fid_start,
- MArena *arena)
+ IMeshArena *arena)
{
if (x_subdiv <= 1 || y_subdiv <= 1) {
return;
@@ -953,7 +958,7 @@ static void fill_grid_data(int x_subdiv,
int num_faces;
get_grid_params(x_subdiv, y_subdiv, triangulate, &num_verts, &num_faces);
BLI_assert(face.size() == num_faces);
- Array<Vertp> vert(num_verts);
+ Array<const Vert *> vert(num_verts);
auto vert_index_fn = [x_subdiv](int ix, int iy) { return iy * x_subdiv + ix; };
auto face_index_fn = [x_subdiv](int ix, int iy) { return iy * (x_subdiv - 1) + ix; };
auto tri_index_fn = [x_subdiv](int ix, int iy, int tri) {
@@ -969,7 +974,7 @@ static void fill_grid_data(int x_subdiv,
double x = center[0] - r + ix * delta_x;
double y = center[1] - r + iy * delta_y;
double z = center[2];
- Vertp v = arena->add_or_find_vert(mpq3(x, y, z), vid++);
+ const Vert *v = arena->add_or_find_vert(mpq3(x, y, z), vid++);
vert[vert_index_fn(ix, iy)] = v;
}
}
@@ -981,13 +986,13 @@ static void fill_grid_data(int x_subdiv,
int i2 = vert_index_fn(ix + 1, iy + 1);
int i3 = vert_index_fn(ix + 1, iy);
if (triangulate) {
- Facep f = arena->add_face({vert[i0], vert[i1], vert[i2]}, fid++, eid);
- Facep f2 = arena->add_face({vert[i2], vert[i3], vert[i0]}, fid++, eid);
+ const Face *f = arena->add_face({vert[i0], vert[i1], vert[i2]}, fid++, eid);
+ const Face *f2 = arena->add_face({vert[i2], vert[i3], vert[i0]}, fid++, eid);
face[tri_index_fn(ix, iy, 0)] = f;
face[tri_index_fn(ix, iy, 1)] = f2;
}
else {
- Facep f = arena->add_face({vert[i0], vert[i1], vert[i2], vert[i3]}, fid++, eid);
+ const Face *f = arena->add_face({vert[i0], vert[i1], vert[i2], vert[i3]}, fid++, eid);
face[face_index_fn(ix, iy)] = f;
}
}
@@ -1007,7 +1012,7 @@ static void spheregrid_test(int nrings, int grid_level, double z_offset, bool us
}
BLI_task_scheduler_init(); /* Without this, no parallelism. */
double time_start = PIL_check_seconds_timer();
- MArena arena;
+ IMeshArena arena;
int num_sphere_verts;
int num_sphere_tris;
int nsegs = 2 * nrings;
@@ -1016,7 +1021,7 @@ static void spheregrid_test(int nrings, int grid_level, double z_offset, bool us
int subdivs = 1 << grid_level;
get_sphere_params(nrings, nsegs, true, &num_sphere_verts, &num_sphere_tris);
get_grid_params(subdivs, subdivs, true, &num_grid_verts, &num_grid_tris);
- Array<Facep> tris(num_sphere_tris + num_grid_tris);
+ Array<const Face *> tris(num_sphere_tris + num_grid_tris);
arena.reserve(num_sphere_verts + num_grid_verts, num_sphere_tris + num_grid_tris);
double3 center(0.0, 0.0, z_offset);
fill_sphere_data(nrings,
@@ -1024,7 +1029,7 @@ static void spheregrid_test(int nrings, int grid_level, double z_offset, bool us
center,
1.0,
true,
- MutableSpan<Facep>(tris.begin(), num_sphere_tris),
+ MutableSpan<const Face *>(tris.begin(), num_sphere_tris),
0,
0,
&arena);
@@ -1033,14 +1038,14 @@ static void spheregrid_test(int nrings, int grid_level, double z_offset, bool us
true,
4.0,
double3(0, 0, 0),
- MutableSpan<Facep>(tris.begin() + num_sphere_tris, num_grid_tris),
+ MutableSpan<const Face *>(tris.begin() + num_sphere_tris, num_grid_tris),
num_sphere_verts,
num_sphere_tris,
&arena);
- Mesh mesh(tris);
+ IMesh mesh(tris);
double time_create = PIL_check_seconds_timer();
// write_obj_mesh(mesh, "spheregrid_in");
- Mesh out;
+ IMesh out;
if (use_self) {
out = trimesh_self_intersect(mesh, &arena);
}