31 #define BM_EDGELOOP_IS_CLOSED (1 << 0)
34 #define EDGELOOP_EPS 1e-10f
48 if (v_other != v_prev) {
92 else if (
count == 0) {
142 for (
uint i = 0; i < edges_len; i += 1) {
159 for (
uint i = 0; i < edges_len; i += 1) {
209 for (vs = lb->
first; vs; vs = vs_next) {
214 const int vs_iter_next = vs_iter_tot + dir;
224 if (v_next_index == 0) {
225 vs_add(vs_pool, &lb_tmp, v_next,
e, vs_iter_next);
227 else if ((dir < 0) == (v_next_index < 0)) {
299 edges =
MEM_mallocN(
sizeof(*edges) * edges_len, __func__);
306 edges =
MEM_mallocN(
sizeof(*edges) * edges_len, __func__);
324 vs_add(vs_pool, &lb_src, v_src, v_src->
e, 1);
325 vs_add(vs_pool, &lb_dst, v_dst, v_dst->
e, -1);
374 for (
uint i = 0; i < edges_len; i += 1) {
399 for (el_store = eloops->
first; el_store; el_store = el_store->
next) {
407 for (el_store = eloops->
first; el_store; el_store = el_store->
next) {
415 for (el_store = eloops->
first; el_store; el_store = el_store->
next) {
428 for (el_store = eloops->
first; el_store; el_store = el_store->
next, tot++) {
436 float len_best_sq = -1.0f;
437 for (el_store = eloops->
first; el_store; el_store = el_store->
next) {
439 if (len_sq > len_best_sq) {
440 len_best_sq = len_sq;
441 el_store_best = el_store;
450 while (eloops->
first) {
454 float len_best_sq = FLT_MAX;
460 for (el_store = eloops->
first; el_store; el_store = el_store->
next) {
474 if (len_sq < len_best_sq) {
475 len_best_sq = len_sq;
476 el_store_best = el_store;
484 *eloops = eloops_ordered;
493 *el_store_copy = *el_store;
495 return el_store_copy;
502 for (i = 0; i < v_arr_tot; i++) {
504 node->data = v_arr[i];
507 el_store->
len = v_arr_tot;
527 return &el_store->
verts;
532 return el_store->
len;
545 #define NODE_AS_V(n) ((BMVert *)((LinkData *)n)->data)
546 #define NODE_AS_CO(n) ((BMVert *)((LinkData *)n)->data)->co
582 const float w_curr =
len_v3v3(v_curr, v_next);
583 const float w = (w_curr + w_prev);
588 node_prev = node_curr;
589 node_curr = node_next;
590 node_next = node_next->
next;
592 if (node_next ==
NULL) {
617 if ((node_curr = node_curr->
next)) {
627 el_store->
no[2] = 1.0f;
635 const float no_align[3])
645 float cross[3], no[3], dir[3];
651 if ((node_curr = node_curr->
next)) {
661 el_store->
no[2] = 1.0f;
676 bool split_swap =
true;
678 #define EDGE_SPLIT(node_copy, node_other) \
680 BMVert *v_split, *v_other = (node_other)->data; \
681 BMEdge *e_split, *e_other = BM_edge_exists((node_copy)->data, v_other); \
682 v_split = BM_edge_split( \
683 bm, e_other, split_swap ? (node_copy)->data : v_other, &e_split, 0.0f); \
684 v_split->e = e_split; \
685 BLI_assert(v_split == e_split->v2); \
686 BLI_gset_insert(split_edges, e_split); \
687 (node_copy)->data = v_split; \
692 while ((el_store->
len * 2) < el_store_len) {
696 if (
split ==
false) {
698 node_curr = node_curr_copy->
next;
705 node_curr = node_curr_copy->
next;
710 node_curr = node_curr->
next;
712 split_swap = !split_swap;
716 split_swap = !split_swap;
719 if (el_store->
len < el_store_len) {
724 while (iter_prev < iter) {
725 node_curr = node_curr->
next;
731 if (
split ==
false) {
733 node_curr = node_curr_copy->
next;
740 node_curr = node_curr_copy->
next;
745 node_curr = node_curr->
next;
747 split_swap = !split_swap;
754 #undef BKE_FOREACH_SUBSET_OF_RANGE
766 if (el_store_a->
len > el_store_b->
len) {
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
void * BLI_pophead(ListBase *listbase) ATTR_NONNULL(1)
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void void void void void BLI_duplicatelist(struct ListBase *dst, const struct ListBase *src) ATTR_NONNULL(1
void BLI_insertlinkafter(struct ListBase *listbase, void *vprevlink, void *vnewlink) ATTR_NONNULL(1)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void BLI_insertlinkbefore(struct ListBase *listbase, void *vnextlink, void *vnewlink) ATTR_NONNULL(1)
void void void void void void BLI_listbase_reverse(struct ListBase *lb) ATTR_NONNULL(1)
#define BLI_ASSERT_UNIT_V3(v)
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
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 add_newell_cross_v3_v3v3(float n[3], const float v_prev[3], const float v_curr[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void negate_v3(float r[3])
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
void BLI_mempool_free(BLI_mempool *pool, void *addr) ATTR_NONNULL(1
BLI_mempool * BLI_mempool_create(unsigned int esize, unsigned int elem_num, unsigned int pchunk, unsigned int flag) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL
void * BLI_mempool_alloc(BLI_mempool *pool) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(1)
void BLI_mempool_destroy(BLI_mempool *pool) ATTR_NONNULL(1)
void BLI_stack_pop_n_reverse(BLI_Stack *stack, void *dst, unsigned int n) ATTR_NONNULL()
size_t BLI_stack_count(const BLI_Stack *stack) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
void BLI_stack_push(BLI_Stack *stack, const void *src) ATTR_NONNULL()
void BLI_stack_free(BLI_Stack *stack) ATTR_NONNULL()
#define BLI_stack_new(esize, descr)
#define BLI_FOREACH_SPARSE_RANGE(src, dst, i)
Read Guarded memory(de)allocation.
#define BM_EDGELOOP_IS_CLOSED
BMEdgeLoopStore * BM_edgeloop_copy(BMEdgeLoopStore *el_store)
struct BMEdgeLoopStore BMEdgeLoopStore
const float * BM_edgeloop_center_get(struct BMEdgeLoopStore *el_store)
static bool bm_loop_path_build_step(BLI_mempool *vs_pool, ListBase *lb, const int dir, BMVert *v_match[2])
void BM_edgeloop_expand(BMesh *bm, BMEdgeLoopStore *el_store, int el_store_len, bool split, GSet *split_edges)
void BM_mesh_edgeloops_free(ListBase *eloops)
void BM_edgeloop_free(BMEdgeLoopStore *el_store)
BMEdgeLoopStore * BM_edgeloop_from_verts(BMVert **v_arr, const int v_arr_tot, bool is_closed)
int BM_mesh_edgeloops_find(BMesh *bm, ListBase *r_eloops, bool(*test_fn)(BMEdge *, void *user_data), void *user_data)
bool BM_mesh_edgeloops_find_path(BMesh *bm, ListBase *r_eloops, bool(*test_fn)(BMEdge *, void *user_data), void *user_data, BMVert *v_src, BMVert *v_dst)
int BM_edgeloop_length_get(BMEdgeLoopStore *el_store)
void BM_mesh_edgeloops_calc_order(BMesh *UNUSED(bm), ListBase *eloops, const bool use_normals)
static bool bm_loop_build(BMEdgeLoopStore *el_store, BMVert *v_prev, BMVert *v, int dir)
bool BM_edgeloop_is_closed(BMEdgeLoopStore *el_store)
void BM_edgeloop_edges_get(struct BMEdgeLoopStore *el_store, BMEdge **e_arr)
ListBase * BM_edgeloop_verts_get(BMEdgeLoopStore *el_store)
void BM_mesh_edgeloops_calc_normal_aligned(BMesh *bm, ListBase *eloops, const float no_align[3])
static int bm_vert_other_tag(BMVert *v, BMVert *v_prev, BMEdge **r_e)
bool BM_edgeloop_calc_normal(BMesh *UNUSED(bm), BMEdgeLoopStore *el_store)
bool BM_edgeloop_overlap_check(struct BMEdgeLoopStore *el_store_a, struct BMEdgeLoopStore *el_store_b)
bool BM_edgeloop_calc_normal_aligned(BMesh *UNUSED(bm), BMEdgeLoopStore *el_store, const float no_align[3])
const float * BM_edgeloop_normal_get(struct BMEdgeLoopStore *el_store)
void BM_edgeloop_flip(BMesh *UNUSED(bm), BMEdgeLoopStore *el_store)
static void vs_add(BLI_mempool *vs_pool, ListBase *lb, BMVert *v, BMEdge *e_prev, const int iter_tot)
void BM_mesh_edgeloops_calc_normal(BMesh *bm, ListBase *eloops)
#define EDGE_SPLIT(node_copy, node_other)
void BM_edgeloop_calc_center(BMesh *UNUSED(bm), BMEdgeLoopStore *el_store)
void BM_mesh_edgeloops_calc_center(BMesh *bm, ListBase *eloops)
#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)
#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
BMEdge * BM_edge_exists(BMVert *v_a, BMVert *v_b)
BLI_INLINE BMVert * BM_edge_other_vert(BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
BLI_INLINE bool BM_vert_in_edge(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
SyclQueue void void size_t num_bytes void
void(* MEM_freeN)(void *vmemh)
void *(* MEM_dupallocN)(const void *vmemh)
void *(* MEM_callocN)(size_t len, const char *str)
void *(* MEM_mallocN)(size_t len, const char *str)
void split(const std::string &s, const char delim, std::vector< std::string > &tokens)
vec_base< T, 3 > cross(const vec_base< T, 3 > &a, const vec_base< T, 3 > &b)
struct BMEdgeLoopStore * next
struct BMEdgeLoopStore * prev