45#define USE_NET_ISLAND_CONNECT
111 params.calc_looptris =
true;
112 params.calc_normals =
true;
113 params.is_destructive =
true;
143 bool use_separate_all =
false;
144 bool use_separate_cut =
false;
153 const bool exact =
false;
169 switch (separate_mode) {
171 use_separate_all =
true;
174 if (use_self ==
false) {
175 use_separate_cut =
true;
180 use_separate_all =
true;
191 for (
Object *obedit : objects) {
199 int nshapes = use_self ? 1 : 2;
225 if (use_separate_cut) {
238 if (isect_len == objects.size()) {
272 {
ISECT_SEL,
"SELECT", 0,
"Self Intersect",
"Self intersect selected faces"},
276 "Selected/Unselected",
277 "Intersect selected with unselected faces"},
278 {0,
nullptr, 0,
nullptr,
nullptr},
287 "Cut into geometry keeping each side separate (Selected/Unselected only)"},
289 {0,
nullptr, 0,
nullptr,
nullptr},
294 {
ISECT_SOLVER_EXACT,
"EXACT", 0,
"Exact",
"Exact solver, slower, handles more cases"},
295 {0,
nullptr, 0,
nullptr,
nullptr},
299 ot->
name =
"Intersect (Knife)";
313 ot->
srna,
"threshold", 0.000001f, 0.0, 0.01,
"Merge Threshold",
"", 0.0, 0.001);
316 isect_intersect_solver_items,
319 "Which Intersect solver to use");
345 const bool use_exact =
false;
357 for (
Object *obedit : objects) {
366 em->
bm, em->
looptris, test_fn,
nullptr, 2, use_self,
true,
false, boolean_operation);
390 if (isect_len == objects.size()) {
427 {0,
nullptr, 0,
nullptr,
nullptr},
432 {
ISECT_SOLVER_EXACT,
"EXACT", 0,
"Exact",
"Exact solver, slower, handles more cases"},
433 {0,
nullptr, 0,
nullptr,
nullptr},
437 ot->
name =
"Intersect (Boolean)";
438 ot->
description =
"Cut solid geometry from selected to unselected";
439 ot->
idname =
"MESH_OT_intersect_boolean";
449 isect_boolean_operation_items,
452 "Which boolean operation to apply");
457 "Use with difference intersection to swap which side is kept");
459 ot->
srna,
"use_self",
false,
"Self Intersection",
"Do self-union or self-intersection");
461 ot->
srna,
"threshold", 0.000001f, 0.0, 0.01,
"Merge Threshold",
"", 0.0, 0.001);
464 isect_boolean_solver_items,
467 "Which Boolean solver to use");
512 }
while ((l_iter = l_iter->
next) != l_first);
537 bm, f,
static_cast<BMEdge **
>(edge_net_temp_buf->
data), edge_net_temp_buf->
count, &face_arr);
541 for (
BMFace *face : face_arr) {
557 if (l_iter->
f != f_ignore) {
562 }
while ((l_iter = l_iter->
radial_next) != e_radial->
l);
567#ifdef USE_NET_ISLAND_CONNECT
586 ls_base->
list =
nullptr;
590 ls_base =
static_cast<LinkBase *
>(*ls_base_p);
619 int edge_arr_len = 0;
622 edge_arr[edge_arr_len++] =
static_cast<BMEdge *
>(e_link->
link);
623 e_link = e_link->
next;
627 uint edge_arr_holes_len;
636 &edge_arr_holes_len))
638 edge_arr_len = edge_arr_holes_len;
639 edge_arr = edge_arr_holes;
645 for (
int i = e_link_len; i < edge_arr_len; i++) {
649 if (e_link_len != edge_arr_len) {
653 for (
int i = e_link_len; i < edge_arr_len; i++) {
689 const int ftable_len,
690 float r_v_pivot_co[3],
691 float *r_v_pivot_fac)
694 bool found_other_self =
false;
695 int found_other_face = 0;
703 if (f_b_index == f_a_index) {
705 found_other_self =
true;
707 else if (f_b_index != -1) {
713 BMFace *f_b = ftable[f_b_index];
723 BMEdge *e_split =
nullptr;
727 if ((found_other_self ==
false) || found_other_face) {
734 float v_pivot_co_test[3];
736 CLAMP(v_pivot_fac, 0.0f, 1.0f);
740 if ((dist_test_sq < dist_best_sq) || (e_split ==
nullptr)) {
750 else if (found_other_face) {
755 int other_face_shared = 0;
756 if (l_radial_iter != l_iter) {
761 }
while ((l_radial_iter = l_radial_iter->
radial_next) != l_iter);
763 if (other_face_shared != found_other_face) {
770 dist_best_sq = dist_test_sq;
772 *r_v_pivot_fac = v_pivot_fac;
775 }
while ((l_iter = l_iter->
next) != l_first);
804 for (
Object *obedit : objects) {
871 if (loop_stack_len == 0) {
874 else if (loop_stack_len == 1) {
895 if (dot_test < dot_best) {
930#ifdef USE_NET_ISLAND_CONNECT
941 params.calc_looptris =
true;
942 params.calc_normals =
true;
943 params.is_destructive =
true;
946#ifdef USE_NET_ISLAND_CONNECT
995 for (
int j = 0; j < 2; j++) {
1000 float v_pivot_co[3];
1021 }
while ((e_link = e_link->
next));
1048 params.calc_looptris =
true;
1049 params.calc_normals =
true;
1050 params.is_destructive =
true;
1063 ot->
name =
"Weld Edges into Faces";
1064 ot->
description =
"Weld loose edges into faces (splitting them into new faces)";
1065 ot->
idname =
"MESH_OT_face_split_by_edges";
Scene * CTX_data_scene(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
BMEditMesh * BKE_editmesh_from_object(Object *ob)
Return the BMEditMesh for a given object.
struct BMFace * BKE_bmbvh_find_face_closest(const BMBVHTree *tree, const float co[3], float dist_max)
BMBVHTree * BKE_bmbvh_new(struct BMesh *bm, blender::Span< std::array< BMLoop *, 3 > > looptris, int flag, const blender::float3 *cos_cage, bool cos_cage_free)
void BKE_bmbvh_free(BMBVHTree *tree)
blender::Vector< Object * > BKE_view_layer_array_from_objects_in_edit_mode_unique_data(const Scene *scene, ViewLayer *view_layer, const View3D *v3d)
void BKE_report(ReportList *reports, eReportType type, const char *message)
#define BLI_buffer_append(buffer_, type_, val_)
#define BLI_buffer_declare_static(type_, name_, flag_, static_count_)
#define BLI_buffer_clear(buffer_)
#define BLI_buffer_free(name_)
BLI_INLINE void * BLI_ghashIterator_getKey(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
BLI_INLINE void * BLI_ghashIterator_getValue(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
#define GHASH_ITER(gh_iter_, ghash_)
GHash * BLI_ghash_ptr_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) ATTR_WARN_UNUSED_RESULT
BLI_LINKSTACK_*** wrapper macros for using a LinkNode to store a stack of pointers,...
#define BLI_SMALLSTACK_DECLARE(var, type)
#define BLI_SMALLSTACK_POP(var)
#define BLI_SMALLSTACK_PUSH(var, data)
#define BLI_SMALLSTACK_POP_EX(var_src, var_dst)
#define BLI_SMALLSTACK_IS_EMPTY(var)
#define BLI_SMALLSTACK_SWAP(var_a, var_b)
float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3])
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
float angle_signed_on_axis_v3v3v3_v3(const float v1[3], const float v2[3], const float v3[3], const float axis[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE float normalize_v3(float n[3])
void * BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
void BLI_memarena_free(struct MemArena *ma) ATTR_NONNULL(1)
struct MemArena * BLI_memarena_new(size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(2) ATTR_MALLOC
#define BLI_MEMARENA_STD_BUFSIZE
void void BLI_memarena_clear(MemArena *ma) ATTR_NONNULL(1)
void BLI_stack_pop(BLI_Stack *stack, void *dst) ATTR_NONNULL()
void BLI_stack_push(BLI_Stack *stack, const void *src) ATTR_NONNULL()
bool BLI_stack_is_empty(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
void BLI_stack_free(BLI_Stack *stack) ATTR_NONNULL()
#define BLI_stack_new(esize, descr)
#define UNUSED_VARS_NDEBUG(...)
Object is a sort of wrapper for general info.
void EDBM_update(Mesh *mesh, const EDBMUpdate_Params *params)
void EDBM_selectmode_flush(BMEditMesh *em)
bool ED_operator_editmesh(bContext *C)
Read Guarded memory(de)allocation.
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiItemS(uiLayout *layout)
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
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)
#define BM_elem_cb_check_hflag_enabled_simple(type, hflag_p)
#define BM_DISK_EDGE_NEXT(e, v)
#define BM_FACE_FIRST_LOOP(p)
BMFace * BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del)
Join Connected Faces.
bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src)
Splice Vert.
#define BM_elem_index_get(ele)
#define BM_elem_flag_disable(ele, hflag)
#define BM_elem_index_set(ele, index)
#define BM_elem_flag_test(ele, hflag)
#define BM_elem_flag_enable(ele, hflag)
bool BM_mesh_intersect(BMesh *bm, const blender::Span< std::array< BMLoop *, 3 > > looptris, int(*test_fn)(BMFace *f, void *user_data), void *user_data, const bool use_self, const bool use_separate, const bool use_dissolve, const bool use_island_connect, const bool use_partial_connect, const bool use_edge_tag, const int boolean_mode, const float eps)
@ BMESH_ISECT_BOOLEAN_DIFFERENCE
@ BMESH_ISECT_BOOLEAN_UNION
@ BMESH_ISECT_BOOLEAN_ISECT
#define BM_ITER_ELEM(ele, iter, data, itype)
#define BM_ITER_MESH(ele, iter, bm, itype)
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar)
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_face_select_set(BMesh *bm, BMFace *f, const bool select)
Select Face.
void BM_edge_select_set(BMesh *bm, BMEdge *e, const bool select)
Select Edge.
void BM_mesh_elem_hflag_disable_all(BMesh *bm, const char htype, const char hflag, const bool respecthide)
void BM_mesh_elem_table_ensure(BMesh *bm, const char htype)
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
BMVert * BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac)
Edge Split.
bool BM_face_split_edgenet_connect_islands(BMesh *bm, BMFace *f, BMEdge **edge_net_init, const uint edge_net_init_len, bool use_partial_connect, MemArena *mem_arena, BMEdge ***r_edge_net_new, uint *r_edge_net_new_len)
bool BM_face_split_edgenet(BMesh *bm, BMFace *f, BMEdge **edge_net, const int edge_net_len, blender::Vector< BMFace * > *r_face_arr)
int BM_face_share_vert_count(BMFace *f_a, BMFace *f_b)
float BM_edge_calc_length_squared(const BMEdge *e)
bool BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb)
BMEdge * BM_edge_exists(BMVert *v_a, BMVert *v_b)
bool BM_vert_in_face(BMVert *v, BMFace *f)
BLI_INLINE BMVert * BM_edge_other_vert(BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
BLI_INLINE bool BM_edge_is_wire(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
void BM_mesh_separate_faces(BMesh *bm, BMFaceFilterFunc filter_fn, void *user_data)
void MESH_OT_intersect(wmOperatorType *ot)
static bool bm_vert_in_faces_radial(BMVert *v, BMEdge *e_radial, BMFace *f_ignore)
void MESH_OT_intersect_boolean(wmOperatorType *ot)
static int edbm_intersect_boolean_exec(bContext *C, wmOperator *op)
static void bm_face_split_by_edges(BMesh *bm, BMFace *f, const char hflag, BLI_Buffer *edge_net_temp_buf)
static BMEdge * bm_face_split_edge_find(BMEdge *e_a, BMFace *f_a, BMVert *v_pivot, BMFace **ftable, const int ftable_len, float r_v_pivot_co[3], float *r_v_pivot_fac)
static void bm_face_split_by_edges_island_connect(BMesh *bm, BMFace *f, LinkNode *e_link, const int e_link_len, MemArena *mem_arena_edgenet)
static int bm_face_isect_self(BMFace *f, void *)
static void edbm_intersect_ui(bContext *, wmOperator *op)
static void ghash_insert_face_edge_link(GHash *gh, BMFace *f_key, BMEdge *e_val, MemArena *mem_arena)
static void edbm_intersect_select(BMEditMesh *em, Mesh *mesh, bool do_select)
void MESH_OT_face_split_by_edges(wmOperatorType *ot)
static int edbm_face_split_by_edges_exec(bContext *C, wmOperator *)
static int bm_face_isect_pair_swap(BMFace *f, void *)
static void edbm_intersect_boolean_ui(bContext *, wmOperator *op)
static int edbm_intersect_exec(bContext *C, wmOperator *op)
static int bm_edge_sort_length_cb(const void *e_a_v, const void *e_b_v)
static int bm_face_isect_pair(BMFace *f, void *)
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
static MemArena * mem_arena
float RNA_float_get(PointerRNA *ptr, const char *name)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_float_distance(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
blender::Array< std::array< BMLoop *, 3 > > looptris
struct BMLoop * radial_next
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
void(* ui)(bContext *C, wmOperator *op)
struct ReportList * reports