45#define FACE_NET _FLAG_WALK
47#define EDGE_NET _FLAG_WALK
49#define VERT_VISIT _FLAG_WALK
50#define VERT_IN_QUEUE _FLAG_WALK_ALT
67 }
while ((
l =
l->radial_next) !=
e->l);
81 }
while ((
l =
l->radial_next) !=
e->l);
87 const float axis_mat[3][3],
102 const float face_normal[3],
103 const float face_normal_matrix[3][3],
116 int edges_boundary_len = 0;
117 int edges_wire_len = 0;
121 e = e_first = v_init->
e;
127 edges_boundary_len++;
129 else if (
count == 0) {
138 if (edges_boundary_len == 0) {
147 if (edges_wire_len == 0) {
148 if (edges_boundary_len > 1) {
151 if (edges_boundary_len > 2) {
162 if (edges_wire_len > 1) {
173 float dir_prev[2], dir_next[2];
177 float angle_best_cos =
dot_v2v2(dir_next, dir_prev);
185 const float angle_test_cos =
dot_v2v2(dir_prev, dir_test);
187 if (angle_test_cos > angle_best_cos) {
188 angle_best_cos = angle_test_cos;
197 if (face_normal == l_walk->
f->
no) {
200 if (l_walk->
v != v_init) {
204 std::swap(e_pair[0], e_pair[1]);
220 int edges_boundary_len = 0;
221 int edges_wire_len = 0;
225 e = e_first = v_init->
e;
230 edges_boundary_len++;
232 else if (
count == 0) {
240 if (edges_boundary_len == 0) {
245 if (edges_wire_len == 0) {
246 if (edges_boundary_len >= 2) {
262 const float face_normal[3],
265 const uint edge_order_len,
273#define USE_FASTPATH_NOFORK
310#ifdef USE_FASTPATH_NOFORK
330 if (e_next != e_first) {
346 printf(
"vert %d -> %d (add=%d)\n",
363#ifdef USE_FASTPATH_NOFORK
377 for (j = 0; j <
STACK_SIZE(edge_order); j++) {
379 v_prev->
co,
v->co, edge_order[j].
v->
co, face_normal);
383#ifdef USE_FASTPATH_NOFORK
407#undef USE_FASTPATH_NOFORK
411 const float face_normal[3],
412 const float face_normal_matrix[3][3],
415 const uint edge_order_len,
417 int *r_face_verts_len)
430 v_init, face_normal, edge_order, edge_order_len, e_pair))
434 r_face_verts[
i++] = v_init;
437 r_face_verts[
i++] =
v;
439 *r_face_verts_len =
i;
440 return (
i > 2) ?
true :
false;
448 const int edge_net_len,
460 const uint edge_order_len = edge_net_len + 2;
480 face_verts =
static_cast<BMVert **
>(
481 MEM_mallocN(
sizeof(*face_verts) * (edge_net_len + f->
len), __func__));
483 vert_queue =
static_cast<BMVert **
>(
484 MEM_mallocN(
sizeof(vert_queue) * (edge_net_len + f->
len), __func__));
491 for (
i = 0;
i < edge_net_len;
i++) {
498 }
while ((l_iter = l_iter->
next) != l_first);
507 for (
i = 0;
i < edge_net_len;
i++) {
516 }
while ((l_iter = l_iter->
next) != l_first);
518 float face_normal_matrix[3][3];
529 v, f->
no, face_normal_matrix, edge_order, edge_order_len, face_verts, &face_verts_len))
535 for (
i = 0;
i < edge_net_len;
i++) {
563 }
while ((l_iter = l_iter->
next) != l_first);
577 float axis_mat[3][3];
598 }
while ((
void)
i++, (l_iter = l_iter->
next) != l_first);
600 for (
i = 0;
i < edge_net_len;
i++) {
612 if (l_first ==
nullptr) {
630 for (
i = 0;
i < edge_net_len;
i++) {
641 }
while ((l_iter = l_iter->
next) != l_first);
652 for (
BMFace *face : face_arr) {
657 *r_face_arr = std::move(face_arr);
687#define USE_PARTIAL_CONNECT
689#define VERT_IS_VALID BM_ELEM_INTERNAL_TAG
701 const float endpoint_bias = 1e-4f;
703 v_a->
co, v_b->
co,
e->v1->co,
e->v2->co, endpoint_bias, r_isect) == 1) &&
704 ((
e->v1 != v_a) && (
e->v2 != v_a) && (
e->v1 != v_b) && (
e->v2 != v_b)));
709 if (pt_a[0] < pt_b[0]) {
712 if (pt_a[0] > pt_b[0]) {
715 if (pt_a[1] < pt_b[1]) {
718 if (pt_a[1] > pt_b[1]) {
791 const float dist_new =
data->dist_orig * t;
795 if (
LIKELY((dist_new < hit->dist) && (dist_new > 0.0f))) {
797 if (v1_index <
int(
data->vert_range[0]) || v1_index >=
int(
data->vert_range[1])) {
798 hit->
dist = dist_new;
816 data->v_origin->co, ray->
direction,
e->v1->co,
e->v2->co, &dist_new,
nullptr))
821 if (
LIKELY(dist_new < hit->dist && (dist_new > 0.0f))) {
822 if (
e->v1 !=
data->v_origin &&
e->v2 !=
data->v_origin) {
825 if (v1_index <
int(
data->vert_range[0]) || v1_index >=
int(
data->vert_range[1])) {
826 hit->
dist = dist_new;
884 if (
LIKELY(index == -1)) {
891 if (t_test < t_best) {
936 if (
LIKELY(index != -1)) {
941 if (
e->v1 != v_origin &&
e->v2 != v_origin) {
975 float dir[3] = {0, 0, 0};
976 dir[
SORT_AXIS] = direction_sign ? 1.0f : -1.0f;
978 BMVert *v_other =
nullptr;
981 BMVert *v_other_fallback =
nullptr;
1000 for (
int j = 0; j < 2; j++) {
1001 BMVert *v_iter = v_pair[j];
1012 v_other_fallback = v_other;
1017 if (v_other ==
nullptr) {
1018 printf(
"Using fallback\n");
1019 v_other = v_other_fallback;
1037#ifdef USE_PARTIAL_CONNECT
1063 LinkNode *e_delimit_list =
nullptr;
1064 uint e_delimit_list_len = 0;
1066# define EDGE_NOT_IN_STACK BM_ELEM_INTERNAL_TAG
1067# define VERT_NOT_IN_STACK BM_ELEM_INTERNAL_TAG
1069# define FOREACH_VERT_EDGE(v_, e_, body_) \
1071 BMEdge *e_ = v_->e; \
1074 } while ((e_ = BM_DISK_EDGE_NEXT(e_, v_)) != v_->e); \
1079 BMEdge *e_face_init =
nullptr;
1085 e_delimit_list_len++;
1087 e_face_init = e_iter;
1093 if (
LIKELY(e_delimit_list_len <= 2)) {
1134 bool is_delimit =
false;
1146# undef FOREACH_VERT_EDGE
1149 BMVert *v_split =
nullptr;
1161 if (
UNLIKELY(v_split->e ==
nullptr)) {
1171 }
while ((vert_stack = vert_stack->
next));
1175 }
while ((e_delimit_list = e_delimit_list->
next));
1177# undef EDGE_NOT_IN_STACK
1178# undef VERT_NOT_IN_STACK
1187 const int v_a_index,
1188 const int v_b_index)
1191 if (
UNLIKELY((remap[v_a_index] == v_b_index) || (remap[v_b_index] == v_a_index))) {
1202 const uint edge_net_init_len,
1203 bool use_partial_connect,
1205 BMEdge ***r_edge_net_new,
1206 uint *r_edge_net_new_len)
1225 uint edge_net_new_len =
uint(edge_net_init_len);
1227 memcpy(edge_arr, edge_net_init,
sizeof(*edge_arr) *
size_t(edge_net_init_len));
1230#define EDGE_NOT_IN_STACK BM_ELEM_INTERNAL_TAG
1231#define VERT_NOT_IN_STACK BM_ELEM_INTERNAL_TAG
1234 uint i = edge_net_init_len;
1235 BMLoop *l_iter, *l_first;
1240 edge_arr[
i++] = l_iter->
e;
1241 }
while ((l_iter = l_iter->
next) != l_first);
1245 for (
uint i = 0;
i < edge_arr_len;
i++) {
1251#ifdef USE_PARTIAL_CONNECT
1253 struct TempVertPair {
1263 } temp_vert_pairs = {
nullptr};
1265 if (use_partial_connect) {
1266 for (
uint i = 0;
i < edge_net_init_len;
i++) {
1267 for (
uint j = 0; j < 2; j++) {
1268 BMVert *v_delimit = (&edge_arr[
i]->
v1)[j];
1273 TempVertPair *tvp =
static_cast<TempVertPair *
>(
1275 tvp->next = temp_vert_pairs.list;
1276 tvp->v_orig = v_delimit;
1277 tvp->v_temp = v_other;
1278 temp_vert_pairs.list = tvp;
1279 temp_vert_pairs.len++;
1284 if (temp_vert_pairs.len == 0) {
1285 use_partial_connect =
false;
1290 uint group_arr_len = 0;
1295 uint edge_index = (edge_arr_len - 1);
1296 uint edge_in_group_tot = 0;
1302 uint unique_verts_in_group = 0, unique_edges_in_group = 0;
1311 unique_verts_in_group++;
1317 unique_edges_in_group++;
1332 g->
vert_len = unique_verts_in_group;
1333 g->
edge_len = unique_edges_in_group;
1334 edge_in_group_tot += unique_edges_in_group;
1340 if (edge_in_group_tot == edge_arr_len) {
1353 BMEdge **edge_net_new =
nullptr;
1355 float (*vert_coords_backup)[3] =
nullptr;
1356 uint *verts_group_table =
nullptr;
1357 BMVert **vert_arr =
nullptr;
1358 uint vert_arr_len = 0;
1362 if (group_arr_len == 1) {
1372 float axis_mat[3][3];
1375#define VERT_IN_ARRAY BM_ELEM_INTERNAL_TAG
1390 g->vert_span.min = ((
BMEdge *)edge_links->
link)->v1;
1391 g->vert_span.max = ((
BMEdge *)edge_links->
link)->v2;
1399 for (
int j = 0; j < 2; j++) {
1404 const float axis_value[2] = {
1415 g->vert_span.min = v_iter;
1419 g->vert_span.max = v_iter;
1423 }
while ((edge_links = edge_links->
next));
1428 g->has_prev_edge =
false;
1430 vert_arr_len += g->vert_len;
1432 *(--group_arr_p) = g;
1439 vert_arr =
static_cast<BMVert **
>(
1442 verts_group_table =
static_cast<uint *
>(
1445 vert_coords_backup =
static_cast<float (*)[3]
>(
1453 for (
uint g_index = 0; g_index < group_arr_len; g_index++) {
1457 for (
int j = 0; j < 2; j++) {
1471 v_iter->
co[0] = co_2d[0];
1472 v_iter->
co[1] = co_2d[1];
1473 v_iter->
co[2] = 0.0f;
1478 vert_arr[v_index] = v_iter;
1479 verts_group_table[v_index] = g_index;
1483 }
while ((edge_links = edge_links->
next));
1494 for (
uint i = 0;
i < edge_arr_len;
i++) {
1495 const float e_cos[2][3] = {
1496 {
UNPACK2(edge_arr[
i]->v1->co), 0.0f},
1503#ifdef USE_PARTIAL_CONNECT
1504 if (use_partial_connect) {
1506 temp_vert_pairs.remap =
static_cast<int *
>(
1508 copy_vn_i(temp_vert_pairs.remap, vert_arr_len, -1);
1510 TempVertPair *tvp = temp_vert_pairs.list;
1513 }
while ((tvp = tvp->next));
1520 edge_net_new_len =
uint(edge_net_init_len) + ((group_arr_len - 1) * 2);
1521 edge_net_new =
static_cast<BMEdge **
>(
1523 memcpy(edge_net_new, edge_net_init,
sizeof(*edge_net_new) *
size_t(edge_net_init_len));
1526 uint edge_net_new_index = edge_net_init_len;
1532 vert_range[1] = group_arr[0]->
vert_len;
1547 for (
uint g_index = 1; g_index < group_arr_len; g_index++) {
1551 vert_range[0] = vert_range[1];
1561 if (index_other != -1) {
1562#ifdef USE_PARTIAL_CONNECT
1563 if ((use_partial_connect ==
false) ||
1568 BMVert *v_end = vert_arr[index_other];
1572#ifdef USE_PARTIAL_CONNECT
1575 edge_net_new_index++;
1588 if (index_other != -1) {
1589#ifdef USE_PARTIAL_CONNECT
1590 if ((use_partial_connect ==
false) ||
1595 BMVert *v_end = vert_arr[index_other];
1598#ifdef USE_PARTIAL_CONNECT
1601 edge_net_new_index++;
1606 uint g_index_other = verts_group_table[index_other];
1611 BLI_assert(edge_net_new_len >= edge_net_new_index);
1612 edge_net_new_len = edge_net_new_index;
1617 *r_edge_net_new = edge_net_new;
1618 *r_edge_net_new_len = edge_net_new_len;
1621 for (
uint i = 0;
i < vert_arr_len;
i++) {
1627#ifdef USE_PARTIAL_CONNECT
1629 if (use_partial_connect) {
1634 TempVertPair *tvp = temp_vert_pairs.list;
1639 }
while ((tvp = tvp->next));
1643 TempVertPair *tvp = temp_vert_pairs.list;
1650 }
while ((tvp = tvp->next));
1654 for (
uint i = edge_net_init_len;
i < edge_net_new_len;
i++) {
1658 if (
i == edge_net_new_len) {
1661 edge_net_new[
i] = edge_net_new[edge_net_new_len];
1665 *r_edge_net_new_len = edge_net_new_len;
1669 for (
uint i = 0;
i < edge_arr_len;
i++) {
1676#undef VERT_NOT_IN_STACK
1677#undef EDGE_NOT_IN_STACK
CustomData interface, see also DNA_customdata_types.h.
void CustomData_bmesh_copy_block(CustomData &data, void *src_block, void **dst_block)
bool CustomData_has_math(const CustomData *data)
void CustomData_bmesh_interp(CustomData *data, const void **src_blocks, const float *weights, int count, void *dst_block)
#define BLI_array_alloca(arr, realsize)
MINLINE axis_t min_axis(axis_t a, axis_t b)
BVHTree * BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis)
#define BVH_RAYCAST_DIST_MAX
void BLI_bvhtree_balance(BVHTree *tree)
void BLI_bvhtree_free(BVHTree *tree)
void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints)
int BLI_bvhtree_ray_cast_ex(const BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata, int flag)
void BLI_linklist_prepend_nlink(LinkNode **listp, void *ptr, LinkNode *nlink) ATTR_NONNULL(1
void BLI_linklist_prepend_arena(LinkNode **listp, void *ptr, struct MemArena *ma) ATTR_NONNULL(1
#define BLI_linklist_prepend_alloca(listp, ptr)
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)
#define BLI_ASSERT_UNIT_V2(v)
int isect_seg_seg_v2_point_ex(const float v0[2], const float v1[2], const float v2[2], const float v3[2], float endpoint_bias, float r_vi[2])
bool isect_ray_seg_v2(const float ray_origin[2], const float ray_direction[2], const float v0[2], const float v1[2], float *r_lambda, float *r_u)
float line_point_factor_v2(const float p[2], const float l1[2], const float l2[2])
void axis_dominant_v3_to_m3(float r_mat[3][3], const float normal[3])
Normal to x,y matrix.
void interp_weights_poly_v2(float w[], float v[][2], int n, const float co[2])
void mul_v2_m3v3(float r[2], const float M[3][3], const float a[3])
MINLINE float len_squared_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE float dot_m3_v3_row_x(const float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT
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_m3_v3_row_y(const float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT
void copy_vn_i(int *array_tar, int size, int val)
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE float dot_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE float normalize_v2(float n[2])
void * BLI_memarena_alloc(MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
int BLI_sortutil_cmp_float_reverse(const void *a_, const void *b_)
#define ARRAY_SET_ITEMS(...)
#define UNUSED_VARS_NDEBUG(...)
#define STACK_POP_PTR(stack)
#define STACK_PUSH(stack, val)
#define STACK_DECLARE(stack)
#define STACK_SIZE(stack)
#define STACK_PUSH_RET_PTR(stack)
#define STACK_INIT(stack, stack_num)
Read Guarded memory(de)allocation.
#define BM_DISK_EDGE_NEXT(e, v)
#define BM_FACE_FIRST_LOOP(p)
void bmesh_face_swap_data(BMFace *f_a, BMFace *f_b)
bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src)
Splice Vert.
void BM_vert_kill(BMesh *bm, BMVert *v)
void BM_face_kill(BMesh *bm, BMFace *f)
BMFace * BM_face_create_verts(BMesh *bm, BMVert **vert_arr, const int len, const BMFace *f_example, const eBMCreateFlag create_flag, const bool create_edges)
void BM_edge_kill(BMesh *bm, BMEdge *e)
BMVert * BM_vert_create(BMesh *bm, const float co[3], const BMVert *v_example, const eBMCreateFlag create_flag)
Main function for creating a new vertex.
void BM_vert_separate_tested_edges(BMesh *, BMVert *v_dst, BMVert *v_src, bool(*testfn)(BMEdge *, void *arg), void *arg)
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.
#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)
BMesh const char void * data
static BMVert * bm_face_split_edgenet_partial_connect(BMesh *bm, BMVert *v_delimit, BMFace *f)
static BMLoop * bm_edge_flagged_radial_first(BMEdge *e)
static bool bm_face_split_edgenet_find_loop_pair(BMVert *v_init, const float face_normal[3], const float face_normal_matrix[3][3], BMEdge *e_pair[2])
static int bm_face_split_edgenet_find_connection(const EdgeGroup_FindConnection_Args *args, BMVert *v_origin, bool direction_sign)
static BMEdge * test_edges_isect_2d_ray(const EdgeGroup_FindConnection_Args *args, BMVert *v_origin, const float dir[3])
static bool bm_face_split_edgenet_find_loop_walk(BMVert *v_init, const float face_normal[3], VertOrder *edge_order, const uint edge_order_len, BMEdge *e_pair[2])
static bool bm_vert_partial_connect_check_overlap(const int *remap, const int v_a_index, const int v_b_index)
#define VERT_NOT_IN_STACK
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)
static void bvhtree_test_edges_isect_2d_ray_cb(void *user_data, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
static bool bm_face_split_edgenet_find_loop(BMVert *v_init, const float face_normal[3], const float face_normal_matrix[3][3], VertOrder *edge_order, const uint edge_order_len, BMVert **r_face_verts, int *r_face_verts_len)
static BMEdge * test_edges_isect_2d_vert(const EdgeGroup_FindConnection_Args *args, BMVert *v_origin, BMVert *v_other)
static void bvhtree_test_edges_isect_2d_vert_cb(void *user_data, int index, const BVHTreeRay *, BVHTreeRayHit *hit)
#define EDGE_NOT_IN_STACK
#define FOREACH_VERT_EDGE(v_, e_, body_)
static void normalize_v2_m3_v3v3(float out[2], const float axis_mat[3][3], const float v1[3], const float v2[3])
static bool bm_face_split_edgenet_find_loop_pair_exists(BMVert *v_init)
static bool test_tagged_and_notface(BMEdge *e, void *fptr)
BLI_INLINE bool edge_isect_verts_point_2d(const BMEdge *e, const BMVert *v_a, const BMVert *v_b, float r_isect[2])
static uint bm_edge_flagged_radial_count(BMEdge *e)
static int group_min_cmp_fn(const void *p1, const void *p2)
BLI_INLINE int axis_pt_cmp(const float pt_a[2], const float pt_b[2])
#define BM_ELEM_API_FLAG_DISABLE(element, f)
#define BM_ELEM_API_FLAG_TEST(element, f)
#define BM_ELEM_API_FLAG_ENABLE(element, f)
bool BM_edge_in_face(const BMEdge *e, const BMFace *f)
BMEdge * BM_edge_find_double(BMEdge *e)
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()
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
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
void append(const T &value)
static MemArena * mem_arena
void * MEM_mallocN(size_t len, const char *str)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)
struct EdgeGroupIsland::@103042325240010213160232253114225104227144076314 vert_span