38static IMesh mesh_from_bm(BMesh *
bm,
39 const Span<std::array<BMLoop *, 3>> looptris,
40 IMesh *r_triangulated,
47 const int estimate_num_outv = 3 *
bm->
totvert;
48 const int estimate_num_outf = 4 *
bm->
totface;
49 arena->reserve(estimate_num_outv, estimate_num_outf);
53 vert[
v] = arena->add_or_find_vert(mpq3(bmv->
co[0], bmv->
co[1], bmv->
co[2]),
v);
56 constexpr int estimated_max_facelen = 100;
57 Vector<const Vert *, estimated_max_facelen> face_vert;
58 Vector<int, estimated_max_facelen> face_edge_orig;
63 face_edge_orig.
clear();
65 for (
int i = 0;
i < flen; ++
i) {
69 face_edge_orig.
append(e_index);
72 face[f] = arena->add_face(face_vert, f, face_edge_orig);
78 Array<Face *> tri_face(looptris.size());
81 for (
const int i : looptris.index_range()) {
82 BMFace *bmf = looptris[
i][0]->f;
84 for (
int j = 0; j < 3; ++j) {
85 BMLoop *
l = looptris[
i][j];
88 if (
l->
next->
v == looptris[
i][(j + 1) % 3]->v) {
94 face_vert[j] = vert[v_index];
95 face_edge_orig[j] = e_index;
97 tri_face[
i] = arena->add_face(face_vert, f, face_edge_orig);
99 r_triangulated->set_faces(tri_face);
103static bool bmvert_attached_to_wire(
const BMVert *bmv)
111static bool bmvert_attached_to_hidden_face(BMVert *bmv)
116 bmf =
static_cast<BMFace *
>(BM_iter_step(&iter)))
125static bool face_has_verts_in_order(BMesh *
bm, BMFace *bmf,
const BMVert *v1,
const BMVert *
v2)
129 while (
l !=
nullptr) {
133 l =
static_cast<BMLoop *
>(BM_iter_step(&liter));
139constexpr uint KEEP_FLAG = (1 << 6);
148static bool apply_mesh_output_to_bmesh(BMesh *
bm, IMesh &m_out,
bool keep_hidden)
150 bool any_change =
false;
152 m_out.populate_vert();
160 bmvert_attached_to_wire(bmv))
173 Array<BMVert *> new_bmvs(m_out.vert_size());
174 for (
int v : m_out.vert_index_range()) {
175 const Vert *vertp = m_out.vert(
v);
176 int orig = vertp->orig;
177 if (orig != NO_INDEX) {
184 new_bmvs[
v] =
nullptr;
187 for (
int v : m_out.vert_index_range()) {
188 const Vert *vertp = m_out.vert(
v);
189 if (new_bmvs[
v] ==
nullptr) {
191 const double3 &d_co = vertp->co;
192 for (
int i = 0;
i < 3; ++
i) {
225 for (
const Face *f : m_out.faces()) {
226 maxflen =
max_ii(maxflen, f->size());
228 Array<BMVert *> face_bmverts(maxflen);
229 Array<BMEdge *> face_bmedges(maxflen);
230 for (
const Face *f : m_out.faces()) {
231 const Face &face = *f;
232 int flen = face.size();
233 for (
int i = 0;
i < flen; ++
i) {
234 const Vert *
v = face[
i];
235 int v_index = m_out.lookup_vert(
v);
237 face_bmverts[
i] = new_bmvs[v_index];
242 if (bmf !=
nullptr && face_has_verts_in_order(
bm, bmf, face_bmverts[0], face_bmverts[1])) {
246 int orig = face.orig;
249 if (orig != NO_INDEX) {
250 orig_face = old_bmfs[orig];
256 for (
int i = 0;
i < flen; ++
i) {
257 BMVert *bmv1 = face_bmverts[
i];
258 BMVert *bmv2 = face_bmverts[(
i + 1) % flen];
260 if (bme ==
nullptr) {
261 BMEdge *orig_edge =
nullptr;
262 if (face.edge_orig[
i] != NO_INDEX) {
263 orig_edge = old_edges[face.edge_orig[
i]];
266 if (orig_edge !=
nullptr) {
270 face_bmedges[
i] = bme;
271 if (face.is_intersect[
i]) {
279 bm, face_bmverts.data(), face_bmedges.data(), flen, orig_face,
BM_CREATE_NOP);
280 if (orig_face !=
nullptr) {
285 if (orig_face !=
nullptr) {
288 while (
l !=
nullptr) {
290 l =
static_cast<BMLoop *
>(BM_iter_step(&liter));
302 while (bmf !=
nullptr) {
306 BMFace *bmf_next =
static_cast<BMFace *
>(BM_iter_step(&iter));
320 while (bmv !=
nullptr) {
324 BMVert *bmv_next =
static_cast<BMVert *
>(BM_iter_step(&iter));
338static bool bmesh_boolean(BMesh *
bm,
339 const Span<std::array<BMLoop *, 3>> looptris,
340 int (*test_fn)(BMFace *f,
void *user_data),
344 const bool use_separate_all,
345 const bool keep_hidden,
346 const bool hole_tolerant,
347 const BoolOpType boolean_mode)
350 IMesh m_triangulated;
354 IMesh m_in = mesh_from_bm(
bm, looptris, &m_triangulated, &arena);
357 std::cout <<
"bmesh_boolean, imesh_from_bm done, time = " << mesh_time - start_time <<
"\n";
359 std::function<int(
int)> shape_fn;
360 if (use_self && boolean_mode == BoolOpType::None) {
363 shape_fn = [
bm, test_fn, user_data](
int f) {
365 if (test_fn(bmf, user_data) != -1) {
372 shape_fn = [
bm, test_fn, user_data](
int f) {
374 int test_val = test_fn(bmf, user_data);
381 IMesh m_out = boolean_mesh(
382 m_in, boolean_mode, nshapes, shape_fn, use_self, hole_tolerant, &m_triangulated, &arena);
385 std::cout <<
"boolean done, time = " << boolean_time - mesh_time <<
"\n";
387 bool any_change = apply_mesh_output_to_bmesh(
bm, m_out, keep_hidden);
390 std::cout <<
"applied boolean output to bmesh, time = " << apply_mesh_time - boolean_time
393 if (use_separate_all) {
423 int (*test_fn)(
BMFace *f,
void *user_data),
427 const bool keep_hidden,
428 const bool hole_tolerant,
429 const int boolean_mode)
431 return blender::meshintersect::bmesh_boolean(
441 static_cast<blender::meshintersect::BoolOpType
>(boolean_mode));
446 int (*test_fn)(
BMFace *f,
void *user_data),
450 const bool use_separate_all,
451 const bool hole_tolerant,
452 const bool keep_hidden)
454 return blender::meshintersect::bmesh_boolean(
bm,
463 blender::meshintersect::BoolOpType::None);
468 int (*test_fn)(
BMFace *,
void *),
490 int (*test_fn)(
BMFace *,
void *),
MINLINE int max_ii(int a, int b)
double BLI_time_now_seconds(void)
bool BM_mesh_boolean_knife(BMesh *, blender::Span< std::array< BMLoop *, 3 > > looptris, int(*test_fn)(BMFace *, void *), void *, const int, const bool, const bool, const bool, const bool)
bool BM_mesh_boolean(BMesh *, blender::Span< std::array< BMLoop *, 3 > > looptris, int(*test_fn)(BMFace *, void *), void *, const int, const bool, const bool, const bool, const int)
void BM_elem_select_copy(BMesh *bm_dst, void *ele_dst_v, const void *ele_src_v)
void BM_vert_kill(BMesh *bm, BMVert *v)
void BM_face_kill(BMesh *bm, BMFace *f)
void BM_face_kill_loose(BMesh *bm, BMFace *f)
BMFace * BM_face_create(BMesh *bm, BMVert *const *verts, BMEdge *const *edges, const int len, const BMFace *f_example, const eBMCreateFlag create_flag)
BMVert * BM_vert_create(BMesh *bm, const float co[3], const BMVert *v_example, const eBMCreateFlag create_flag)
Main function for creating a new vertex.
BMEdge * BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *e_example, const eBMCreateFlag create_flag)
Main function for creating a new edge.
void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only, const bool copy_select)
#define BM_elem_index_get(ele)
#define BM_elem_flag_disable(ele, hflag)
#define BM_elem_flag_test(ele, hflag)
#define BM_elem_flag_enable(ele, hflag)
void BM_loop_interp_from_face(BMesh *bm, BMLoop *l_dst, const BMFace *f_src, const bool do_vertex, const bool do_multires)
int BM_iter_mesh_count(const char itype, BMesh *bm)
#define BM_iter_new(iter, bm, itype, data)
void BM_mesh_elem_table_ensure(BMesh *bm, const char htype)
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
BLI_INLINE BMVert * BM_vert_at_index(BMesh *bm, const int index)
BLI_INLINE BMFace * BM_face_at_index(BMesh *bm, const int index)
bool BM_vert_is_wire(const BMVert *v)
BMFace * BM_face_exists(BMVert *const *varr, int len)
BMEdge * BM_edge_exists(BMVert *v_a, BMVert *v_b)
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert * v
void append(const T &value)
void resize(const int64_t new_size)
VecBase< double, 3 > double3