35 BMVert *v_tar =
static_cast<BMVert *
>(BMO_slot_map_elem_get(slot_targetmap,
l->v));
92#define LOOP_MAP_VERT_INIT(l_init, v_map, is_del) \
94 is_del = BMO_vert_flag_test_bool(bm, v_map, ELE_DEL); \
96 v_map = static_cast<BMVert *>(BMO_slot_map_elem_get(slot_targetmap, v_map)); \
100 BMLoop *l_first, *l_curr, *l_next;
111 l_next = l_curr->
next;
115 if ((is_del_v_curr || is_del_v_next) == 0) {
118 else if (v_curr == v_next) {
140 is_del_v_curr = is_del_v_next;
141 }
while ((l_curr = l_next) != l_first);
143#undef LOOP_MAP_VERT_INIT
167 }
while ((
void)
i++, (l_iter = l_iter->
next) != l_first);
194 const bool use_targetmap_all = has_selected;
195 GHash *targetmap_all =
nullptr;
196 if (use_targetmap_all) {
205 BMVert *v_dst =
static_cast<BMVert *
>(BMO_slot_map_elem_get(slot_targetmap,
v));
206 if (v_dst ==
nullptr) {
215 if (use_targetmap_all) {
221 if (use_centroid &&
LIKELY(v_dst !=
v)) {
224 *cluster_p = MEM_new<blender::Vector<BMVert *>>(__func__);
243 for (
BMVert *v_duplicate : *cluster) {
269 if (is_del_v1 || is_del_v2) {
271 v1 =
static_cast<BMVert *
>(BMO_slot_map_elem_get(slot_targetmap, v1));
274 v2 =
static_cast<BMVert *
>(BMO_slot_map_elem_get(slot_targetmap,
v2));
283 if (e_new ==
nullptr) {
287 if (use_targetmap_all) {
300 bool vert_delete =
false;
301 int edge_collapse = 0;
313 bool use_in_place =
false;
317 if (f->
len - edge_collapse >= 3) {
325 if (
bm->use_toolflags) {
339 if ((use_in_place ==
false) && (f_new !=
nullptr)) {
341 if (use_targetmap_all) {
344 if (
bm->act_face && (f ==
bm->act_face)) {
345 bm->act_face = f_new;
355 if (use_targetmap_all) {
375 vert_snap =
static_cast<BMVert *
>(
385 if (l_first ==
nullptr) {
389 for (
i = 0;
i <
bm->ldata.totlayer;
i++) {
391 const int type =
bm->ldata.layers[
i].type;
392 const int offset =
bm->ldata.layers[
i].offset;
427 for (
i = 0;
i <
bm->ldata.totlayer;
i++) {
428 const int type =
bm->ldata.layers[
i].type;
429 const int offset =
bm->ldata.layers[
i].offset;
461 BMVert *
v, *vert_snap =
nullptr;
554 for (j = 0; j < 2; j++) {
555 BMVert *v_src = *((&
e->v1) + j);
578 const int type =
bm->ldata.layers[layer].type;
579 const int offset =
bm->ldata.layers[layer].offset;
654 for (
i = 0;
i <
bm->ldata.totlayer;
i++) {
676 const bool has_keep_vert)
679 bool found_duplicates =
false;
680 bool has_self_index =
false;
682 KDTree_3d *
tree = BLI_kdtree_3d_new(verts_len);
683 for (
int i = 0;
i < verts_len;
i++) {
687 has_self_index =
true;
694 BLI_kdtree_3d_balance(
tree);
697 auto deduplicate_target_calc_fn = [&
verts](
const int *cluster,
const int cluster_num) ->
int {
698 if (cluster_num == 2) {
701 return (cluster[0] < cluster[1]) ? 0 : 1;
706 for (
int i = 0;
i < cluster_num;
i++) {
709 centroid /=
float(cluster_num);
712 const int cluster_end = cluster_num - 1;
715 int i_best = cluster_end;
717 for (
int i = 0;
i < cluster_end;
i++) {
720 if (dist_sq_test > dist_sq_best) {
723 if (dist_sq_test == dist_sq_best) {
724 if (cluster[
i] > cluster[i_best]) {
729 dist_sq_best = dist_sq_test;
734 found_duplicates = BLI_kdtree_3d_calc_duplicates_cb_cpp(
735 tree, dist, duplicates, has_self_index, deduplicate_target_calc_fn) != 0;
737 BLI_kdtree_3d_free(
tree);
739 if (!found_duplicates) {
741 duplicates =
nullptr;
751 const bool has_keep_vert)
754 bool found_duplicates =
false;
759 for (
int i = 0;
i < verts_len;
i++) {
771 for (
int i = 0;
i < verts_len;
i++) {
772 if (!
ELEM(duplicates[
i], -1,
i)) {
775 const float *co_check =
verts[
i]->co;
782 e_first = e_iter = v_check->
e;
787 const int i_other = vert_to_index_map.
lookup_default(v_other, -1);
788 if ((i_other != -1) && (duplicates[i_other] == -1)) {
789 duplicates[i_other] =
i;
790 vert_stack.
push(i_other);
791 found_duplicates =
true;
798 l_radial_iter = e_iter->
l;
800 if (l_radial_iter->
v != v_check) {
804 if (l_radial_iter->
f->
len <= 3) {
816 const int i_other = vert_to_index_map.
lookup_default(v_other, -1);
817 if ((i_other != -1) && (duplicates[i_other] == -1)) {
818 duplicates[i_other] =
i;
819 vert_stack.
push(i_other);
820 found_duplicates =
true;
823 }
while ((l_iter = l_iter->
next) != l_end);
824 }
while ((l_radial_iter = l_radial_iter->
radial_next) != e_iter->
l);
829 }
while ((i_check = vert_stack.
is_empty() ? -1 : vert_stack.
pop()) != -1);
832 if (!found_duplicates) {
834 duplicates =
nullptr;
848 const int verts_len = slot_verts->
len;
850 bool has_keep_vert =
false;
865 int *duplicates =
nullptr;
868 bm,
verts, verts_len, dist, has_keep_vert);
876 for (
int i = 0;
i < verts_len;
i++) {
878 if (duplicates[
i] == -1) {
881 else if (duplicates[
i] ==
i) {
CustomData interface, see also DNA_customdata_types.h.
void CustomData_data_initminmax(eCustomDataType type, void *min, void *max)
bool CustomData_layer_has_math(const CustomData *data, int layer_n)
void CustomData_data_copy_value(eCustomDataType type, const void *source, void *dest)
void CustomData_bmesh_copy_block(CustomData &data, void *src_block, void **dst_block)
void CustomData_data_dominmax(eCustomDataType type, const void *data, void *min, void *max)
void CustomData_data_multiply(eCustomDataType type, void *data, float fac)
void CustomData_data_add(eCustomDataType type, void *data1, const void *data2)
bool CustomData_has_math(const CustomData *data)
#define BLI_array_alloca(arr, realsize)
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_insert(GHash *gh, void *key, void *val)
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
A KD-tree for nearest neighbor search.
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
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()
void * BLI_stack_peek(BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
#define BLI_stack_new(esize, descr)
#define STACK_CLEAR(stack)
#define STACK_PUSH(stack, val)
#define STACK_DECLARE(stack)
#define STACK_SIZE(stack)
#define STACK_INIT(stack, stack_num)
static void split(const char *text, const char *seps, char ***str, int *count)
Read Guarded memory(de)allocation.
#define BM_DISK_EDGE_NEXT(e, v)
#define BM_FACE_FIRST_LOOP(p)
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
void BM_elem_attrs_copy(BMesh *bm, const BMCustomDataCopyMap &map, const BMVert *src, BMVert *dst)
void bmesh_face_swap_data(BMFace *f_a, BMFace *f_b)
void BM_face_kill(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)
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 BMO_mesh_delete_oflag_context(BMesh *bm, const short oflag, const int type, blender::FunctionRef< void()> prepare_fn)
#define BM_elem_flag_merge_ex(ele_a, ele_b, hflag_and)
#define BM_elem_flag_disable(ele, hflag)
#define BM_elem_flag_test(ele, hflag)
#define BM_elem_flag_enable(ele, hflag)
int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const bool value)
Mesh Iter Flag Count.
#define BM_ITER_ELEM(ele, iter, data, itype)
#define BM_ITER_MESH(ele, iter, bm, itype)
void BM_select_history_merge_from_targetmap(BMesh *bm, GHash *vert_map, GHash *edge_map, GHash *face_map, const bool use_chain)
BMFace * BM_face_split(BMesh *bm, BMFace *f, BMLoop *l_a, BMLoop *l_b, BMLoop **r_l, BMEdge *example, const bool no_double)
Face Split.
void * BMO_slot_buffer_get_single(BMOpSlot *slot)
void BMO_slot_buffer_flag_enable(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, char htype, short oflag)
BMO_FLAG_BUFFER.
#define BMO_vert_flag_disable(bm, e, oflag)
#define BMO_edge_flag_test(bm, e, oflag)
void BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_vec[3])
#define BMO_edge_flag_enable(bm, e, oflag)
float BMO_slot_float_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
#define BMO_vert_flag_enable(bm, e, oflag)
void * BMO_iter_new(BMOIter *iter, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, char restrictmask)
New Iterator.
BMOpSlot * BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
BMESH OPSTACK GET SLOT.
void BMO_op_exec(BMesh *bm, BMOperator *op)
BMESH OPSTACK EXEC OP.
#define BMO_face_flag_enable(bm, e, oflag)
void BMO_op_init(BMesh *bm, BMOperator *op, int flag, const char *opname)
BMESH OPSTACK INIT OP.
#define BMO_ITER(ele, iter, slot_args, slot_name, restrict_flag)
#define BMO_vert_flag_test(bm, e, oflag)
void BMO_op_finish(BMesh *bm, BMOperator *op)
BMESH OPSTACK FINISH OP.
bool BMO_op_callf(BMesh *bm, int flag, const char *fmt,...)
#define BMO_vert_flag_test_bool(bm, e, oflag)
#define BMO_face_flag_disable(bm, e, oflag)
bool BMO_slot_exists(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier)
BMESH OPSTACK HAS SLOT.
bool BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name)
BLI_INLINE void BMO_slot_map_elem_insert(BMOperator *op, BMOpSlot *slot, const void *element, void *val)
ATTR_WARN_UNUSED_RESULT const BMFlagLayer const short oflag
ATTR_WARN_UNUSED_RESULT const BMFlagLayer * oflags
BMFace * BM_face_exists(BMVert *const *varr, int len)
BMEdge * BM_edge_exists(BMVert *v_a, BMVert *v_b)
int BM_vert_face_count(const BMVert *v)
BMLoop * BM_face_vert_share_loop(BMFace *f, BMVert *v)
Return the Loop Shared by Face and Vertex.
BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
BLI_INLINE BMVert * BM_edge_other_vert(BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
void * BMW_begin(BMWalker *walker, void *start)
void BMW_init(BMWalker *walker, BMesh *bm, int type, short mask_vert, short mask_edge, short mask_face, BMWFlag flag, int layer)
Initialize Walker.
void BMW_end(BMWalker *walker)
End Walker.
void * BMW_step(BMWalker *walker)
Step Walker.
static void bmesh_find_doubles_common(BMesh *bm, BMOperator *op, BMOperator *optarget, BMOpSlot *optarget_slot)
void bmo_collapse_exec(BMesh *bm, BMOperator *op)
void bmo_average_vert_facedata_exec(BMesh *bm, BMOperator *op)
void bmo_remove_doubles_exec(BMesh *bm, BMOperator *op)
#define LOOP_MAP_VERT_INIT(l_init, v_map, is_del)
static void remdoubles_splitface(BMFace *f, BMesh *bm, BMOperator *op, BMOpSlot *slot_targetmap)
static int * bmesh_find_doubles_by_distance_connected_impl(BMesh *bm, BMVert *const *verts, const int verts_len, const float dist, const bool has_keep_vert)
static BMFace * remdoubles_createface(BMesh *bm, BMFace *f, BMOpSlot *slot_targetmap, bool *r_created)
static int * bmesh_find_doubles_by_distance_impl(BMesh *bm, BMVert *const *verts, const int verts_len, const float dist, const bool has_keep_vert)
void bmo_pointmerge_exec(BMesh *bm, BMOperator *op)
void bmo_pointmerge_facedata_exec(BMesh *bm, BMOperator *op)
void bmo_find_doubles_exec(BMesh *bm, BMOperator *op)
static void bmo_collapsecon_do_layer(BMesh *bm, const int layer, const short oflag)
void bmo_collapse_uvs_exec(BMesh *bm, BMOperator *op)
void bmo_weld_verts_exec(BMesh *bm, BMOperator *op)
bool add(const Key &key, const Value &value)
Value lookup_default(const Key &key, const Value &default_value) const
void push(const T &value)
void append(const T &value)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)
VecBase< float, 3 > float3
struct BMLoop * radial_next
union BMOpSlot::@313121210037300127305053354046356312170117023254 data
struct BMOpSlot slots_out[BMO_OP_MAX_SLOTS]
struct BMOpSlot slots_in[BMO_OP_MAX_SLOTS]