57 #define USE_NET_ISLAND_CONNECT
148 int (*test_fn)(
BMFace *,
void *);
149 bool use_separate_all =
false;
150 bool use_separate_cut =
false;
159 const bool exact =
false;
175 switch (separate_mode) {
177 use_separate_all =
true;
180 if (use_self ==
false) {
181 use_separate_cut =
true;
186 use_separate_all =
true;
193 uint objects_len = 0;
197 for (
uint ob_index = 0; ob_index < objects_len; ob_index++) {
198 Object *obedit = objects[ob_index];
206 int nshapes = use_self ? 1 : 2;
234 if (use_separate_cut) {
248 if (isect_len == objects_len) {
286 {
ISECT_SEL,
"SELECT", 0,
"Self Intersect",
"Self intersect selected faces"},
290 "Selected/Unselected",
291 "Intersect selected with unselected faces"},
301 "Cut into geometry keeping each side separate (Selected/Unselected only)"},
308 {
ISECT_SOLVER_EXACT,
"EXACT", 0,
"Exact",
"Exact solver, slower, handles more cases"},
313 ot->
name =
"Intersect (Knife)";
327 ot->
srna,
"threshold", 0.000001f, 0.0, 0.01,
"Merge Threshold",
"", 0.0, 0.001);
330 isect_intersect_solver_items,
333 "Which Intersect solver to use");
359 const bool use_exact =
false;
362 int (*test_fn)(
BMFace *,
void *);
367 uint objects_len = 0;
371 for (
uint ob_index = 0; ob_index < objects_len; ob_index++) {
372 Object *obedit = objects[ob_index];
415 if (isect_len == objects_len) {
461 {
ISECT_SOLVER_EXACT,
"EXACT", 0,
"Exact",
"Exact solver, slower, handles more cases"},
466 ot->
name =
"Intersect (Boolean)";
467 ot->
description =
"Cut solid geometry from selected to unselected";
468 ot->
idname =
"MESH_OT_intersect_boolean";
478 isect_boolean_operation_items,
481 "Which boolean operation to apply");
486 "Use with difference intersection to swap which side is kept");
489 ot->
srna,
"threshold", 0.000001f, 0.0, 0.01,
"Merge Threshold",
"", 0.0, 0.001);
492 isect_boolean_solver_items,
495 "Which Boolean solver to use");
544 }
while ((l_iter = l_iter->
next) != l_first);
568 bm, f, edge_net_temp_buf->
data, edge_net_temp_buf->
count, &face_arr, &face_arr_len);
574 for (i = 0; i < face_arr_len; i++) {
595 if (l_iter->
f != f_ignore) {
600 }
while ((l_iter = l_iter->
radial_next) != e_radial->
l);
605 #ifdef USE_NET_ISLAND_CONNECT
627 ls_base = *ls_base_p;
655 int edge_arr_len = 0;
658 edge_arr[edge_arr_len++] = e_link->
link;
659 e_link = e_link->
next;
663 uint edge_arr_holes_len;
672 &edge_arr_holes_len)) {
673 edge_arr_len = edge_arr_holes_len;
674 edge_arr = edge_arr_holes;
680 for (
int i = e_link_len; i < edge_arr_len; i++) {
684 if (e_link_len != edge_arr_len) {
688 for (
int i = e_link_len; i < edge_arr_len; i++) {
724 const int ftable_len,
725 float r_v_pivot_co[3],
726 float *r_v_pivot_fac)
729 bool found_other_self =
false;
730 int found_other_face = 0;
738 if (f_b_index == f_a_index) {
740 found_other_self =
true;
742 else if (f_b_index != -1) {
748 BMFace *f_b = ftable[f_b_index];
762 if ((found_other_self ==
false) || found_other_face) {
766 float dist_best_sq = FLT_MAX;
769 float v_pivot_co_test[3];
771 CLAMP(v_pivot_fac, 0.0f, 1.0f);
775 if ((dist_test_sq < dist_best_sq) || (e_split ==
NULL)) {
784 else if (found_other_face) {
789 int other_face_shared = 0;
790 if (l_radial_iter != l_iter) {
795 }
while ((l_radial_iter = l_radial_iter->
radial_next) != l_iter);
797 if (other_face_shared != found_other_face) {
804 dist_best_sq = dist_test_sq;
806 *r_v_pivot_fac = v_pivot_fac;
809 }
while ((l_iter = l_iter->
next) != l_first);
835 uint objects_len = 0;
838 for (
uint ob_index = 0; ob_index < objects_len; ob_index++) {
839 Object *obedit = objects[ob_index];
906 if (loop_stack_len == 0) {
909 else if (loop_stack_len == 1) {
919 float dot_best = FLT_MAX;
930 if (dot_test < dot_best) {
964 #ifdef USE_NET_ISLAND_CONNECT
977 #ifdef USE_NET_ISLAND_CONNECT
1027 for (
int j = 0; j < 2; j++) {
1028 BMVert *v_pivot = (&
e->v1)[j];
1032 float v_pivot_co[3];
1053 }
while ((e_link = e_link->
next));
1093 ot->
name =
"Weld Edges into Faces";
1094 ot->
description =
"Weld loose edges into faces (splitting them into new faces)";
1095 ot->
idname =
"MESH_OT_face_split_by_edges";
struct wmWindowManager * CTX_wm_manager(const bContext *C)
struct ViewLayer * CTX_data_view_layer(const bContext *C)
struct View3D * CTX_wm_view3d(const bContext *C)
BMEditMesh * BKE_editmesh_from_object(struct Object *ob)
Return the BMEditMesh for a given object.
BMBVHTree * BKE_bmbvh_new(struct BMesh *bm, struct BMLoop *(*looptris)[3], int looptris_tot, int flag, const float(*cos_cage)[3], const bool cos_cage_free)
struct BMFace * BKE_bmbvh_find_face_closest(BMBVHTree *tree, const float co[3], const float dist_max)
void BKE_bmbvh_free(BMBVHTree *tree)
#define BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, v3d, r_len)
void BKE_report(ReportList *reports, ReportType 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_)
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
GHash * BLI_ghash_ptr_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
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])
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], const float t)
MINLINE float normalize_v3(float r[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 mid_v3_v3v3(float r[3], const float a[3], const float b[3])
void BLI_memarena_free(struct MemArena *ma) ATTR_NONNULL(1)
#define BLI_MEMARENA_STD_BUFSIZE
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_clear(MemArena *ma) ATTR_NONNULL(1)
struct MemArena * BLI_memarena_new(const size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2) ATTR_MALLOC
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.
#define SCE_SELECT_VERTEX
void EDBM_update_generic(struct Mesh *me, const bool do_tessellation, const bool is_destructive)
void EDBM_mesh_normals_update(struct BMEditMesh *em)
bool ED_operator_editmesh(struct bContext *C)
Read Guarded memory(de)allocation.
Group RGB to Bright Vector Camera CLAMP
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiItemS(uiLayout *layout)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
bool BM_mesh_boolean(BMesh *UNUSED(bm), struct BMLoop *(*looptris)[3], const int UNUSED(looptris_tot), int(*test_fn)(BMFace *, void *), void *UNUSED(user_data), const int UNUSED(nshapes), const bool UNUSED(use_self), const bool UNUSED(keep_hidden), const bool UNUSED(hole_tolerant), const int UNUSED(boolean_mode))
bool BM_mesh_boolean_knife(BMesh *UNUSED(bm), struct BMLoop *(*looptris)[3], const int UNUSED(looptris_tot), int(*test_fn)(BMFace *, void *), void *UNUSED(user_data), const int UNUSED(nshapes), const bool UNUSED(use_self), const bool UNUSED(use_separate_all), const bool UNUSED(hole_tolerant), const bool UNUSED(keep_hidden))
#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, struct BMLoop *(*looptris)[3], const int looptris_tot, 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, BMFace ***r_face_arr, int *r_face_arr_len)
BMEdge * BM_edge_exists(BMVert *v_a, BMVert *v_b)
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)
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_boolean(struct wmOperatorType *ot)
static int bm_face_isect_pair_swap(BMFace *f, void *UNUSED(user_data))
static int edbm_face_split_by_edges_exec(bContext *C, wmOperator *UNUSED(op))
static bool bm_vert_in_faces_radial(BMVert *v, BMEdge *e_radial, BMFace *f_ignore)
static int edbm_intersect_boolean_exec(bContext *C, wmOperator *op)
static int bm_face_isect_self(BMFace *f, void *UNUSED(user_data))
static void bm_face_split_by_edges(BMesh *bm, BMFace *f, const char hflag, BLI_Buffer *edge_net_temp_buf)
static void edbm_intersect_select(BMEditMesh *em, struct Mesh *me, bool do_select)
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 void edbm_intersect_ui(bContext *C, wmOperator *op)
void MESH_OT_face_split_by_edges(struct wmOperatorType *ot)
static void ghash_insert_face_edge_link(GHash *gh, BMFace *f_key, BMEdge *e_val, MemArena *mem_arena)
void MESH_OT_intersect(struct wmOperatorType *ot)
static int edbm_intersect_exec(bContext *C, wmOperator *op)
static void edbm_intersect_boolean_ui(bContext *C, wmOperator *op)
static int bm_face_isect_pair(BMFace *f, void *UNUSED(user_data))
static int bm_edge_sort_length_cb(const void *e_a_v, const void *e_b_v)
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 MemArena * mem_arena
void(* MEM_freeN)(void *vmemh)
void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
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_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_float_distance(StructOrFunctionRNA *cont_, const char *identifier, float default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
struct BMLoop *(* looptris)[3]
struct BMLoop * radial_next
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
void(* ui)(struct bContext *, struct wmOperator *)
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
struct ReportList * reports
struct wmOperatorType * type