43 #define USE_NET_ISLAND_CONNECT
108 .calc_looptri =
true,
109 .calc_normals =
true,
110 .is_destructive =
true,
139 int (*test_fn)(
BMFace *,
void *);
140 bool use_separate_all =
false;
141 bool use_separate_cut =
false;
150 const bool exact =
false;
166 switch (separate_mode) {
168 use_separate_all =
true;
171 if (use_self ==
false) {
172 use_separate_cut =
true;
177 use_separate_all =
true;
184 uint objects_len = 0;
188 for (
uint ob_index = 0; ob_index < objects_len; ob_index++) {
189 Object *obedit = objects[ob_index];
197 int nshapes = use_self ? 1 : 2;
225 if (use_separate_cut) {
239 if (isect_len == objects_len) {
273 {
ISECT_SEL,
"SELECT", 0,
"Self Intersect",
"Self intersect selected faces"},
277 "Selected/Unselected",
278 "Intersect selected with unselected faces"},
288 "Cut into geometry keeping each side separate (Selected/Unselected only)"},
295 {
ISECT_SOLVER_EXACT,
"EXACT", 0,
"Exact",
"Exact solver, slower, handles more cases"},
300 ot->
name =
"Intersect (Knife)";
314 ot->
srna,
"threshold", 0.000001f, 0.0, 0.01,
"Merge Threshold",
"", 0.0, 0.001);
317 isect_intersect_solver_items,
320 "Which Intersect solver to use");
346 const bool use_exact =
false;
349 int (*test_fn)(
BMFace *,
void *);
354 uint objects_len = 0;
358 for (
uint ob_index = 0; ob_index < objects_len; ob_index++) {
359 Object *obedit = objects[ob_index];
402 if (isect_len == objects_len) {
444 {
ISECT_SOLVER_EXACT,
"EXACT", 0,
"Exact",
"Exact solver, slower, handles more cases"},
449 ot->
name =
"Intersect (Boolean)";
450 ot->
description =
"Cut solid geometry from selected to unselected";
451 ot->
idname =
"MESH_OT_intersect_boolean";
461 isect_boolean_operation_items,
464 "Which boolean operation to apply");
469 "Use with difference intersection to swap which side is kept");
471 ot->
srna,
"use_self",
false,
"Self Intersection",
"Do self-union or self-intersection");
473 ot->
srna,
"threshold", 0.000001f, 0.0, 0.01,
"Merge Threshold",
"", 0.0, 0.001);
476 isect_boolean_solver_items,
479 "Which Boolean solver to use");
528 }
while ((l_iter = l_iter->
next) != l_first);
552 bm, f, edge_net_temp_buf->
data, edge_net_temp_buf->
count, &face_arr, &face_arr_len);
558 for (i = 0; i < face_arr_len; i++) {
579 if (l_iter->
f != f_ignore) {
584 }
while ((l_iter = l_iter->
radial_next) != e_radial->
l);
589 #ifdef USE_NET_ISLAND_CONNECT
611 ls_base = *ls_base_p;
639 int edge_arr_len = 0;
642 edge_arr[edge_arr_len++] = e_link->
link;
643 e_link = e_link->
next;
647 uint edge_arr_holes_len;
656 &edge_arr_holes_len)) {
657 edge_arr_len = edge_arr_holes_len;
658 edge_arr = edge_arr_holes;
664 for (
int i = e_link_len; i < edge_arr_len; i++) {
668 if (e_link_len != edge_arr_len) {
672 for (
int i = e_link_len; i < edge_arr_len; i++) {
708 const int ftable_len,
709 float r_v_pivot_co[3],
710 float *r_v_pivot_fac)
713 bool found_other_self =
false;
714 int found_other_face = 0;
722 if (f_b_index == f_a_index) {
724 found_other_self =
true;
726 else if (f_b_index != -1) {
732 BMFace *f_b = ftable[f_b_index];
746 if ((found_other_self ==
false) || found_other_face) {
750 float dist_best_sq = FLT_MAX;
753 float v_pivot_co_test[3];
755 CLAMP(v_pivot_fac, 0.0f, 1.0f);
759 if ((dist_test_sq < dist_best_sq) || (e_split ==
NULL)) {
768 else if (found_other_face) {
773 int other_face_shared = 0;
774 if (l_radial_iter != l_iter) {
779 }
while ((l_radial_iter = l_radial_iter->
radial_next) != l_iter);
781 if (other_face_shared != found_other_face) {
788 dist_best_sq = dist_test_sq;
790 *r_v_pivot_fac = v_pivot_fac;
793 }
while ((l_iter = l_iter->
next) != l_first);
819 uint objects_len = 0;
822 for (
uint ob_index = 0; ob_index < objects_len; ob_index++) {
823 Object *obedit = objects[ob_index];
890 if (loop_stack_len == 0) {
893 else if (loop_stack_len == 1) {
903 float dot_best = FLT_MAX;
914 if (dot_test < dot_best) {
948 #ifdef USE_NET_ISLAND_CONNECT
960 .calc_looptri = true,
961 .calc_normals = true,
962 .is_destructive = true,
965 #ifdef USE_NET_ISLAND_CONNECT
1015 for (
int j = 0; j < 2; j++) {
1016 BMVert *v_pivot = (&
e->v1)[j];
1020 float v_pivot_co[3];
1041 }
while ((e_link = e_link->
next));
1069 .calc_looptri = true,
1070 .calc_normals = true,
1071 .is_destructive = true,
1085 ot->
name =
"Weld Edges into Faces";
1086 ot->
description =
"Weld loose edges into faces (splitting them into new faces)";
1087 ot->
idname =
"MESH_OT_face_split_by_edges";
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.
struct BMFace * BKE_bmbvh_find_face_closest(BMBVHTree *tree, const float co[3], float dist_max)
BMBVHTree * BKE_bmbvh_new(struct BMesh *bm, struct BMLoop *(*looptris)[3], int looptris_tot, int flag, const float(*cos_cage)[3], bool cos_cage_free)
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, 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_)
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])
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 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])
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 * BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
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.
#define SCE_SELECT_VERTEX
void EDBM_update(struct Mesh *me, const struct EDBMUpdate_Params *params)
void EDBM_selectmode_flush(struct BMEditMesh *em)
bool ED_operator_editmesh(struct bContext *C)
Read Guarded memory(de)allocation.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position 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 *UNUSED(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 *UNUSED(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)
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