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
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;
478 MEM_mallocN(
sizeof(*edge_order) * edge_order_len, __func__));
481 face_verts =
static_cast<BMVert **
>(
482 MEM_mallocN(
sizeof(*face_verts) * (edge_net_len + f->
len), __func__));
484 vert_queue =
static_cast<BMVert **
>(
485 MEM_mallocN(
sizeof(vert_queue) * (edge_net_len + f->
len), __func__));
492 for (i = 0; i < edge_net_len; i++) {
499 }
while ((l_iter = l_iter->
next) != l_first);
508 for (i = 0; i < edge_net_len; i++) {
517 }
while ((l_iter = l_iter->
next) != l_first);
519 float face_normal_matrix[3][3];
530 v, f->
no, face_normal_matrix, edge_order, edge_order_len, face_verts, &face_verts_len))
536 for (i = 0; i < edge_net_len; i++) {
564 }
while ((l_iter = l_iter->
next) != l_first);
578 float axis_mat[3][3];
599 }
while ((
void)i++, (l_iter = l_iter->
next) != l_first);
601 for (i = 0; i < edge_net_len; i++) {
613 if (l_first ==
nullptr) {
631 for (i = 0; i < edge_net_len; i++) {
642 }
while ((l_iter = l_iter->
next) != l_first);
653 for (
BMFace *face : face_arr) {
658 *r_face_arr = std::move(face_arr);
688#define USE_PARTIAL_CONNECT
690#define VERT_IS_VALID BM_ELEM_INTERNAL_TAG
702 const float endpoint_bias = 1e-4f;
704 v_a->
co, v_b->
co,
e->v1->
co,
e->v2->
co, endpoint_bias, r_isect) == 1) &&
705 ((
e->v1 != v_a) && (
e->v2 != v_a) && (
e->v1 != v_b) && (
e->v2 != v_b)));
710 if (pt_a[0] < pt_b[0]) {
713 if (pt_a[0] > pt_b[0]) {
716 if (pt_a[1] < pt_b[1]) {
719 if (pt_a[1] > pt_b[1]) {
786 const BMEdge *
e = data->edge_arr[index];
792 const float dist_new = data->dist_orig * t;
796 if (
LIKELY((dist_new < hit->dist) && (dist_new > 0.0f))) {
798 if (v1_index <
int(data->vert_range[0]) || v1_index >=
int(data->vert_range[1])) {
799 hit->dist = dist_new;
812 const BMEdge *
e = data->edge_arr[index];
817 data->v_origin->co, ray->direction,
e->v1->
co,
e->v2->
co, &dist_new,
nullptr))
822 if (
LIKELY(dist_new < hit->dist && (dist_new > 0.0f))) {
823 if (
e->v1 != data->v_origin &&
e->v2 != data->v_origin) {
826 if (v1_index <
int(data->vert_range[0]) || v1_index >=
int(data->vert_range[1])) {
827 hit->dist = dist_new;
885 if (
LIKELY(index == -1)) {
892 if (t_test < t_best) {
937 if (
LIKELY(index != -1)) {
942 if (
e->v1 != v_origin &&
e->v2 != v_origin) {
944 if (
LIKELY(dist_new < hit.dist)) {
976 float dir[3] = {0, 0, 0};
977 dir[
SORT_AXIS] = direction_sign ? 1.0f : -1.0f;
979 BMVert *v_other =
nullptr;
982 BMVert *v_other_fallback =
nullptr;
1001 for (
int j = 0; j < 2; j++) {
1002 BMVert *v_iter = v_pair[j];
1013 v_other_fallback = v_other;
1018 if (v_other ==
nullptr) {
1019 printf(
"Using fallback\n");
1020 v_other = v_other_fallback;
1038#ifdef USE_PARTIAL_CONNECT
1064 LinkNode *e_delimit_list =
nullptr;
1065 uint e_delimit_list_len = 0;
1067# define EDGE_NOT_IN_STACK BM_ELEM_INTERNAL_TAG
1068# define VERT_NOT_IN_STACK BM_ELEM_INTERNAL_TAG
1070# define FOREACH_VERT_EDGE(v_, e_, body_) \
1072 BMEdge *e_ = v_->e; \
1075 } while ((e_ = BM_DISK_EDGE_NEXT(e_, v_)) != v_->e); \
1080 BMEdge *e_face_init =
nullptr;
1086 e_delimit_list_len++;
1088 e_face_init = e_iter;
1094 if (
LIKELY(e_delimit_list_len <= 2)) {
1135 bool is_delimit =
false;
1147# undef FOREACH_VERT_EDGE
1150 BMVert *v_split =
nullptr;
1162 if (
UNLIKELY(v_split->e ==
nullptr)) {
1172 }
while ((vert_stack = vert_stack->
next));
1176 }
while ((e_delimit_list = e_delimit_list->
next));
1178# undef EDGE_NOT_IN_STACK
1179# undef VERT_NOT_IN_STACK
1188 const int v_a_index,
1189 const int v_b_index)
1192 if (
UNLIKELY((remap[v_a_index] == v_b_index) || (remap[v_b_index] == v_a_index))) {
1203 const uint edge_net_init_len,
1204 bool use_partial_connect,
1206 BMEdge ***r_edge_net_new,
1207 uint *r_edge_net_new_len)
1226 uint edge_net_new_len =
uint(edge_net_init_len);
1228 memcpy(edge_arr, edge_net_init,
sizeof(*edge_arr) *
size_t(edge_net_init_len));
1231#define EDGE_NOT_IN_STACK BM_ELEM_INTERNAL_TAG
1232#define VERT_NOT_IN_STACK BM_ELEM_INTERNAL_TAG
1235 uint i = edge_net_init_len;
1236 BMLoop *l_iter, *l_first;
1241 edge_arr[i++] = l_iter->
e;
1242 }
while ((l_iter = l_iter->
next) != l_first);
1246 for (
uint i = 0; i < edge_arr_len; i++) {
1252#ifdef USE_PARTIAL_CONNECT
1254 struct TempVertPair {
1264 } temp_vert_pairs = {
nullptr};
1266 if (use_partial_connect) {
1267 for (
uint i = 0; i < edge_net_init_len; i++) {
1268 for (
uint j = 0; j < 2; j++) {
1269 BMVert *v_delimit = (&edge_arr[i]->
v1)[j];
1274 TempVertPair *tvp =
static_cast<TempVertPair *
>(
1276 tvp->next = temp_vert_pairs.list;
1277 tvp->v_orig = v_delimit;
1278 tvp->v_temp = v_other;
1279 temp_vert_pairs.list = tvp;
1280 temp_vert_pairs.len++;
1285 if (temp_vert_pairs.len == 0) {
1286 use_partial_connect =
false;
1291 uint group_arr_len = 0;
1296 uint edge_index = (edge_arr_len - 1);
1297 uint edge_in_group_tot = 0;
1303 uint unique_verts_in_group = 0, unique_edges_in_group = 0;
1312 unique_verts_in_group++;
1318 unique_edges_in_group++;
1333 g->
vert_len = unique_verts_in_group;
1334 g->
edge_len = unique_edges_in_group;
1335 edge_in_group_tot += unique_edges_in_group;
1341 if (edge_in_group_tot == edge_arr_len) {
1354 BMEdge **edge_net_new =
nullptr;
1356 float(*vert_coords_backup)[3] =
nullptr;
1357 uint *verts_group_table =
nullptr;
1358 BMVert **vert_arr =
nullptr;
1359 uint vert_arr_len = 0;
1363 if (group_arr_len == 1) {
1373 float axis_mat[3][3];
1376#define VERT_IN_ARRAY BM_ELEM_INTERNAL_TAG
1391 g->vert_span.min = ((
BMEdge *)edge_links->
link)->v1;
1392 g->vert_span.max = ((
BMEdge *)edge_links->
link)->v2;
1400 for (
int j = 0; j < 2; j++) {
1405 const float axis_value[2] = {
1416 g->vert_span.min = v_iter;
1420 g->vert_span.max = v_iter;
1424 }
while ((edge_links = edge_links->
next));
1429 g->has_prev_edge =
false;
1431 vert_arr_len += g->vert_len;
1433 *(--group_arr_p) = g;
1440 vert_arr =
static_cast<BMVert **
>(
1443 verts_group_table =
static_cast<uint *
>(
1446 vert_coords_backup =
static_cast<float(*)[3]
>(
1454 for (
uint g_index = 0; g_index < group_arr_len; g_index++) {
1458 for (
int j = 0; j < 2; j++) {
1472 v_iter->
co[0] = co_2d[0];
1473 v_iter->
co[1] = co_2d[1];
1474 v_iter->
co[2] = 0.0f;
1479 vert_arr[v_index] = v_iter;
1480 verts_group_table[v_index] = g_index;
1484 }
while ((edge_links = edge_links->
next));
1495 for (
uint i = 0; i < edge_arr_len; i++) {
1496 const float e_cos[2][3] = {
1497 {
UNPACK2(edge_arr[i]->v1->co), 0.0f},
1504#ifdef USE_PARTIAL_CONNECT
1505 if (use_partial_connect) {
1507 temp_vert_pairs.remap =
static_cast<int *
>(
1509 copy_vn_i(temp_vert_pairs.remap, vert_arr_len, -1);
1511 TempVertPair *tvp = temp_vert_pairs.list;
1514 }
while ((tvp = tvp->next));
1521 edge_net_new_len =
uint(edge_net_init_len) + ((group_arr_len - 1) * 2);
1522 edge_net_new =
static_cast<BMEdge **
>(
1524 memcpy(edge_net_new, edge_net_init,
sizeof(*edge_net_new) *
size_t(edge_net_init_len));
1527 uint edge_net_new_index = edge_net_init_len;
1533 vert_range[1] = group_arr[0]->
vert_len;
1539 args.edge_arr = edge_arr;
1540 args.edge_arr_len = edge_arr_len;
1543 args.edge_arr_new = edge_net_new + edge_net_init_len;
1544 args.edge_arr_new_len = 0;
1546 args.vert_range = vert_range;
1548 for (
uint g_index = 1; g_index < group_arr_len; g_index++) {
1552 vert_range[0] = vert_range[1];
1562 if (index_other != -1) {
1563#ifdef USE_PARTIAL_CONNECT
1564 if ((use_partial_connect ==
false) ||
1569 BMVert *v_end = vert_arr[index_other];
1573#ifdef USE_PARTIAL_CONNECT
1576 edge_net_new_index++;
1577 args.edge_arr_new_len++;
1589 if (index_other != -1) {
1590#ifdef USE_PARTIAL_CONNECT
1591 if ((use_partial_connect ==
false) ||
1596 BMVert *v_end = vert_arr[index_other];
1599#ifdef USE_PARTIAL_CONNECT
1602 edge_net_new_index++;
1603 args.edge_arr_new_len++;
1607 uint g_index_other = verts_group_table[index_other];
1612 BLI_assert(edge_net_new_len >= edge_net_new_index);
1613 edge_net_new_len = edge_net_new_index;
1618 *r_edge_net_new = edge_net_new;
1619 *r_edge_net_new_len = edge_net_new_len;
1622 for (
uint i = 0; i < vert_arr_len; i++) {
1623 copy_v3_v3(vert_arr[i]->co, vert_coords_backup[i]);
1628#ifdef USE_PARTIAL_CONNECT
1630 if (use_partial_connect) {
1635 TempVertPair *tvp = temp_vert_pairs.list;
1640 }
while ((tvp = tvp->next));
1644 TempVertPair *tvp = temp_vert_pairs.list;
1651 }
while ((tvp = tvp->next));
1655 for (
uint i = edge_net_init_len; i < edge_net_new_len; i++) {
1659 if (i == edge_net_new_len) {
1662 edge_net_new[i] = edge_net_new[edge_net_new_len];
1666 *r_edge_net_new_len = edge_net_new_len;
1670 for (
uint i = 0; i < edge_arr_len; i++) {
1677#undef VERT_NOT_IN_STACK
1678#undef EDGE_NOT_IN_STACK
CustomData interface, see also DNA_customdata_types.h.
void CustomData_bmesh_interp(CustomData *data, const void **src_blocks, const float *weights, const float *sub_weights, int count, void *dst_block)
void CustomData_bmesh_copy_block(CustomData &data, void *src_block, void **dst_block)
bool CustomData_has_math(const CustomData *data)
#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(struct 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)
ATTR_WARN_UNUSED_RESULT BMesh * bm
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)
draw_view in_light_buf[] float
static MemArena * mem_arena
void *(* MEM_mallocN)(size_t len, const char *str)
void MEM_freeN(void *vmemh)
struct BMLoop * radial_next
struct EdgeGroupIsland::@156 vert_span