59#define USE_NET_ISLAND_CONNECT
68static void tri_v3_scale(
float v1[3],
float v2[3],
float v3[3],
const float t)
139 ls_base->
list =
nullptr;
143 ls_base =
static_cast<LinkBase *
>(*ls_base_p);
173 for (i = 0, node = v_ls_base->
list; i < v_ls_base->
list_len; i++, node = node->next) {
182 for (i = 0, node = v_ls_base->
list; i < v_ls_base->
list_len; i++, node = node->next) {
183 node->link = vert_sort[i].
v;
209 bool use_island_connect,
210 bool use_partial_connect,
219 for (i = 0, node = e_ls_base->
list; i < e_ls_base->
list_len; i++, node = node->next) {
220 edge_arr[i] =
static_cast<BMEdge *
>(node->link);
228# ifdef USE_NET_ISLAND_CONNECT
229 if (use_island_connect) {
230 uint edge_arr_holes_len;
239 &edge_arr_holes_len))
241 edge_arr_len = edge_arr_holes_len;
242 edge_arr = edge_arr_holes;
246 UNUSED_VARS(use_island_connect, mem_arena_edgenet);
267 const float *t_cos[3],
268 const float t_nor[3],
279 for (i_t0 = 0; i_t0 < 3; i_t0++) {
280 const uint i_t1 = (i_t0 + 1) % 3;
293 p0, p1, t_cos[i_t0], t_cos[i_t1], ix_pair[0], ix_pair[1], 0.0f);
295 if (ix_pair_type != 0) {
296 if (ix_pair_type == 1) {
300 if ((ix_pair_type == 1) || (
len_squared_v3v3(ix_pair[0], ix_pair[1]) <=
e->eps_margin_sq))
303 if ((fac >=
e->eps_margin) && (fac <= 1.0f - e->eps_margin)) {
305 if ((fac >=
e->eps_margin) && (fac <= 1.0f - e->eps_margin)) {
318 p0, p1, t_cos[0], t_cos[1], t_cos[2], &fac,
nullptr, 0.0f))
320 if ((fac >=
e->eps_margin) && (fac <= 1.0f - e->eps_margin)) {
341 const float *t_cos[3],
342 const float t_nor[3],
352 std::swap(e_v0, e_v1);
364#define KEY_SET(k, i0, i1, i2, i3) \
374#define KEY_EDGE_TRI_ORDER(k) \
377 std::swap(k[2], k[3]); \
380 std::swap(k[0], k[2]); \
381 std::swap(k[1], k[3]); \
400#undef KEY_EDGE_TRI_ORDER
421 printf(
"# new vertex (%.6f, %.6f, %.6f) %d\n",
UNPACK3(ix), *r_side);
456 memcpy(k, k_arr[*r_side],
sizeof(
int[4]));
482 const int face_side = data->test_fn(
l->
f, data->user_data);
484 const int face_side_other = data->test_fn(l_iter->
f, data->user_data);
485 if (
UNLIKELY(face_side_other == -1)) {
488 else if (face_side_other != face_side) {
503 const std::array<BMLoop *, 3> &a,
504 const std::array<BMLoop *, 3> &
b,
511 const float *f_a_cos[3] = {
UNPACK3_EX(, fv_a, ->co)};
512 const float *f_b_cos[3] = {
UNPACK3_EX(, fv_b, ->co)};
539#define VERT_VISIT_A _FLAG_WALK
540#define VERT_VISIT_B _FLAG_WALK_ALT
542#define STACK_PUSH_TEST_A(ele) \
543 if (BM_ELEM_API_FLAG_TEST(ele, VERT_VISIT_A) == 0) { \
544 BM_ELEM_API_FLAG_ENABLE(ele, VERT_VISIT_A); \
545 STACK_PUSH(iv_ls_a, ele); \
549#define STACK_PUSH_TEST_B(ele) \
550 if (BM_ELEM_API_FLAG_TEST(ele, VERT_VISIT_B) == 0) { \
551 BM_ELEM_API_FLAG_ENABLE(ele, VERT_VISIT_B); \
552 STACK_PUSH(iv_ls_b, ele); \
563 for (i_a = 0; i_a < 3; i_a++) {
565 for (i_b = 0; i_b < 3; i_b++) {
566 if (
len_squared_v3v3(fv_a[i_a]->co, fv_b[i_b]->co) <= s->epsilon.eps2x_sq) {
586 for (i_a = 0; i_a < 3; i_a++) {
589 for (i_b_e0 = 0; i_b_e0 < 3; i_b_e0++) {
590 uint i_b_e1 = (i_b_e0 + 1) % 3;
599 fv_a[i_a]->co, fv_b[i_b_e0]->co, fv_b[i_b_e1]->co);
600 if ((fac > 0.0f - s->epsilon.eps) && (fac < 1.0f + s->epsilon.eps)) {
609 printf(
" ('VERT-EDGE-A', %d, %d),\n",
629 for (i_b = 0; i_b < 3; i_b++) {
632 for (i_a_e0 = 0; i_a_e0 < 3; i_a_e0++) {
633 uint i_a_e1 = (i_a_e0 + 1) % 3;
642 fv_b[i_b]->co, fv_a[i_a_e0]->co, fv_a[i_a_e1]->co);
643 if ((fac > 0.0f - s->epsilon.eps) && (fac < 1.0f + s->epsilon.eps)) {
652 printf(
" ('VERT-EDGE-B', %d, %d),\n",
683 for (i_a = 0; i_a < 3; i_a++) {
694 printf(
" 'VERT TRI-A',\n");
710 for (i_b = 0; i_b < 3; i_b++) {
721 printf(
" 'VERT TRI-B',\n");
741 for (
uint i_a_e0 = 0; i_a_e0 < 3; i_a_e0++) {
742 uint i_a_e1 = (i_a_e0 + 1) % 3;
753 s, fv_a[i_a_e0], fv_a[i_a_e1], fv_b, b_index, f_b_cos, f_b_nor, &side);
758 printf(
" ('EDGE-TRI-A', %d),\n", side);
763 for (
uint i_b_e0 = 0; i_b_e0 < 3; i_b_e0++) {
764 uint i_b_e1 = (i_b_e0 + 1) % 3;
775 s, fv_b[i_b_e0], fv_b[i_b_e1], fv_a, a_index, f_a_cos, f_a_nor, &side);
780 printf(
" ('EDGE-TRI-B', %d),\n", side);
787 for (i = 0; i < 2; i++) {
850# ifdef USE_KDOPBVH_WATERTIGHT
860 const float **looptris = raycast_data->
looptris;
861 const float *v0 = looptris[index * 3 + 0];
862 const float *v1 = looptris[index * 3 + 1];
863 const float *
v2 = looptris[index * 3 + 2];
871 ray->origin, ray->direction, v0, v1,
v2, &dist,
nullptr, FLT_EPSILON)
877 printf(
"%s:\n", __func__);
879 print_v3(
" direction", ray->direction);
880 printf(
" dist %f\n", dist);
887 printf(
"%s: Adding depth %f\n", __func__, dist);
903 const float dir[3] = {1.0f, 0.0f, 0.0f};
915 printf(
"%s: Total intersections: %zu\n", __func__, z_buffer.count);
920 if (z_buffer.count == 0) {
923 else if (z_buffer.count == 1) {
928 const float eps = FLT_EPSILON * 10;
933 const float *depth_arr =
static_cast<const float *
>(z_buffer.data);
934 float depth_last = depth_arr[0];
936 for (
uint i = 1; i < z_buffer.count; i++) {
937 if (depth_arr[i] - depth_last >
eps) {
938 depth_last = depth_arr[i];
954 int (*test_fn)(
BMFace *f,
void *user_data),
957 const bool use_separate,
958 const bool use_dissolve,
959 const bool use_island_connect,
960 const bool use_partial_connect,
961 const bool use_edge_tag,
962 const int boolean_mode,
969 bool has_edit_isect =
false, has_edit_boolean =
false;
972 const float **looptri_coords =
nullptr;
976 uint tree_overlap_tot;
990 s.vert_dissolve =
nullptr;
996 s.epsilon.eps2x =
eps * 2.0f;
997 s.epsilon.eps_margin = s.epsilon.eps2x * 10.0f;
999 s.epsilon.eps_sq = s.epsilon.eps * s.epsilon.eps;
1000 s.epsilon.eps2x_sq = s.epsilon.eps2x * s.epsilon.eps2x;
1001 s.epsilon.eps_margin_sq = s.epsilon.eps_margin * s.epsilon.eps_margin;
1036 cos =
static_cast<float **
>(
1037 MEM_mallocN(
size_t(looptris.size()) *
sizeof(*looptri_coords) * 3, __func__));
1038 for (i = 0, j = 0; i <
int(looptris.size()); i++) {
1039 cos[j++] = looptris[i][0]->v->co;
1040 cos[j++] = looptris[i][1]->v->co;
1041 cos[j++] = looptris[i][2]->v->co;
1043 looptri_coords = (
const float **)
cos;
1049 tree_a =
BLI_bvhtree_new(
int(looptris.size()), s.epsilon.eps_margin, 8, 8);
1050 for (i = 0; i <
int(looptris.size()); i++) {
1051 if (test_fn(looptris[i][0]->f, user_data) == 0) {
1052 const float t_cos[3][3] = {
1064 if (use_self ==
false) {
1066 tree_b =
BLI_bvhtree_new(
int(looptris.size()), s.epsilon.eps_margin, 8, 8);
1067 for (i = 0; i <
int(looptris.size()); i++) {
1068 if (test_fn(looptris[i][0]->f, user_data) == 1) {
1069 const float t_cos[3][3] = {
1094 if (looptris.size() < 1024) {
1095 flag &= ~BVH_OVERLAP_USE_THREADING;
1103 for (i = 0; i < tree_overlap_tot; i++) {
1105 printf(
" ((%d, %d), (\n", overlap[i].indexA, overlap[i].indexB);
1110 looptris[overlap[i].indexA],
1111 looptris[overlap[i].indexB],
1112 isect_tri_tri_no_shared);
1123 if (tree_a != tree_b) {
1130 for (i_a = 0; i_a < looptris.size(); i_a++) {
1131 const int t_a = test_fn(looptris[i_a][0]->f, user_data);
1132 for (i_b = i_a + 1; i_b < looptris.size(); i_b++) {
1133 const int t_b = test_fn(looptris[i_b][0]->f, user_data);
1136 if ((t_a != 0) || (t_b != 0)) {
1141 if ((t_a != t_b) && !
ELEM(-1, t_a, t_b)) {
1147 printf(
" ((%d, %d), (", i_a, i_b);
1149 bm_isect_tri_tri(&s, i_a, i_b, looptris[i_a], looptris[i_b], isect_tri_tri_no_shared);
1194 for (node = v_ls_base->
list;
node; node = node->next) {
1203 for (node = v_ls_base->
list;
node; node = node->next) {
1239 for (node = s.vert_dissolve;
node; node = node->next) {
1248 splice_ls =
static_cast<BMVert *(*)[2]
>(
1252 for (node = s.vert_dissolve;
node; node = node->next) {
1290 splice_pair[1] = v_b;
1292 printf(
"# Simple Case!\n");
1311 std::swap(v_a, v_b);
1335 splice_pair[1] = v_next;
1347 printf(
"# walk step %p %p\n", e_next, v_next);
1364 node_prev_p = &e_ls_base->
list;
1365 for (node = e_ls_base->
list;
node; node = node->next) {
1369 *node_prev_p = node->
next;
1373 node_prev_p = &node->
next;
1400 faces[f_index] =
nullptr;
1415 for (node = s.vert_dissolve;
node; node = node->next) {
1428 for (i = 0; i <
STACK_SIZE(splice_ls); i++) {
1463 BLI_assert(f_index >= 0 && f_index < totface_orig);
1473 bm, f, e_ls_base, use_island_connect, use_partial_connect, mem_arena_edgenet);
1513 BVHTree *tree_pair[2] = {tree_a, tree_b};
1517 int(*group_index)[2];
1527 user_data_wrap.
test_fn = test_fn;
1528 user_data_wrap.user_data = user_data;
1530 groups_array =
static_cast<int *
>(
1536 printf(
"%s: Total face-groups: %d\n", __func__, group_tot);
1540 for (i = 0; i < group_tot; i++) {
1541 int fg = group_index[i][0];
1542 int fg_end = group_index[i][1] + fg;
1543 bool do_remove, do_flip;
1547 BMFace *f = ftable[groups_array[fg]];
1550 int side = test_fn(f, user_data);
1563 switch (boolean_mode) {
1565 do_remove = ((hits & 1) != 1);
1569 do_remove = ((hits & 1) == 1);
1573 do_remove = ((hits & 1) == 1) == side;
1574 do_flip = (side == 0);
1580 for (; fg != fg_end; fg++) {
1583 ftable[groups_array[fg]]->
mat_nr = -1;
1587 for (; fg != fg_end; fg++) {
1592 has_edit_boolean |= (do_flip || do_remove);
1603 for (node = s.vert_dissolve;
node; node = node->next) {
1614 if (l_iter->
f->
len == 3) {
1631 for (i = 0; i < tot; i++) {
1632 if (ftable[i]->mat_nr == -1) {
1644 if (tree_a != tree_b) {
1664 return (has_edit_isect || has_edit_boolean);
#define BLI_array_alloca(arr, realsize)
#define BLI_buffer_append(buffer_, type_, val_)
#define BLI_buffer_declare_static(type_, name_, flag_, static_count_)
#define BLI_buffer_free(name_)
BLI_INLINE void * BLI_ghashIterator_getKey(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
GSet * BLI_gset_ptr_new(const char *info)
bool BLI_gset_haskey(const GSet *gs, const void *key) ATTR_WARN_UNUSED_RESULT
#define BLI_ghashutil_inthash_v4_cmp
BLI_INLINE void * BLI_ghashIterator_getValue(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
#define GHASH_ITER(gh_iter_, ghash_)
GHash * BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
GHash * BLI_ghash_ptr_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
unsigned int BLI_gset_len(const GSet *gs) ATTR_WARN_UNUSED_RESULT
void BLI_gset_insert(GSet *gs, void *key)
BLI_INLINE void * BLI_gsetIterator_getKey(GSetIterator *gsi)
unsigned int BLI_ghash_len(const GHash *gh) ATTR_WARN_UNUSED_RESULT
#define GSET_ITER(gs_iter_, gset_)
#define BLI_ghashutil_inthash_v4_p
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
void BLI_ghash_insert(GHash *gh, void *key, void *val)
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
GHash * BLI_ghash_int_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) ATTR_WARN_UNUSED_RESULT
bool BLI_gset_add(GSet *gs, void *key)
bool BLI_gset_remove(GSet *gs, const void *key, GSetKeyFreeFP keyfreefp)
BVHTree * BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis)
@ BVH_OVERLAP_USE_THREADING
@ BVH_OVERLAP_RETURN_PAIRS
#define BVH_RAYCAST_DIST_MAX
#define USE_KDOPBVH_WATERTIGHT
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)
BVHTreeOverlap * BLI_bvhtree_overlap_ex(const BVHTree *tree1, const BVHTree *tree2, uint *r_overlap_num, BVHTree_OverlapCallback callback, void *userdata, uint max_interactions, int flag)
int BLI_bvhtree_ray_cast(const BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata)
void BLI_linklist_prepend_arena(LinkNode **listp, void *ptr, struct MemArena *ma) ATTR_NONNULL(1
int BLI_linklist_index(const LinkNode *list, const void *ptr) ATTR_WARN_UNUSED_RESULT
BLI_LINKSTACK_*** wrapper macros for using a LinkNode to store a stack of pointers,...
MINLINE float clamp_f(float value, float min, float max)
MINLINE float min_fff(float a, float b, float c)
bool isect_line_segment_tri_epsilon_v3(const float p1[3], const float p2[3], const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2], float epsilon)
int isect_line_line_epsilon_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3], float r_i1[3], float r_i2[3], float epsilon)
bool isect_point_tri_v3(const float p[3], const float v1[3], const float v2[3], const float v3[3], float r_isect_co[3])
bool isect_ray_tri_watertight_v3(const float ray_origin[3], const struct IsectRayPrecalc *isect_precalc, const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2])
float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3])
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
bool isect_ray_tri_epsilon_v3(const float ray_origin[3], const float ray_direction[3], const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2], float epsilon)
void print_v3(const char *str, const float v[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])
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)
MINLINE float normalize_v3(float n[3])
void mid_v3_v3v3v3(float v[3], const float v1[3], const float v2[3], const float v3[3])
void * BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
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 void BLI_memarena_clear(MemArena *ma) ATTR_NONNULL(1)
int BLI_sortutil_cmp_float(const void *a_, const void *b_)
#define UNPACK3_EX(pre, a, post)
#define POINTER_FROM_INT(i)
#define UNUSED_VARS_NDEBUG(...)
#define POINTER_AS_INT(i)
#define STACK_DECLARE(stack)
#define STACK_SIZE(stack)
#define STACK_INIT(stack, stack_num)
#define STACK_PUSH_RET(stack)
Read Guarded memory(de)allocation.
#define BM_DISK_EDGE_NEXT(e, v)
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_loose(BMesh *bm, BMFace *f)
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.
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.
bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b)
void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only, const bool copy_select)
#define BM_elem_index_get(ele)
#define BM_elem_flag_disable(ele, hflag)
#define BM_elem_flag_test(ele, hflag)
#define BM_elem_flag_enable(ele, hflag)
#define KEY_EDGE_TRI_ORDER(k)
static bool bm_loop_filter_fn(const BMLoop *l, void *user_data)
static void raycast_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *)
static BMVert * bm_isect_edge_tri(ISectState *s, BMVert *e_v0, BMVert *e_v1, BMVert *t[3], const int t_index, const float *t_cos[3], const float t_nor[3], enum ISectType *r_side)
static void bm_isect_tri_tri(ISectState *s, int a_index, int b_index, const std::array< BMLoop *, 3 > &a, const std::array< BMLoop *, 3 > &b, bool no_shared)
static bool ghash_insert_link(GHash *gh, void *key, void *val, bool use_test, MemArena *mem_arena)
#define KEY_SET(k, i0, i1, i2, i3)
bool BM_mesh_intersect(BMesh *bm, const blender::Span< std::array< BMLoop *, 3 > > looptris, 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)
#define STACK_PUSH_TEST_B(ele)
static void face_edges_add(ISectState *s, const int f_index, BMEdge *e, const bool use_test)
static enum ISectType intersect_line_tri(const float p0[3], const float p1[3], const float *t_cos[3], const float t_nor[3], float r_ix[3], const ISectEpsilon *e)
#define STACK_PUSH_TEST_A(ele)
static void face_edges_split(BMesh *bm, BMFace *f, LinkBase *e_ls_base, bool use_island_connect, bool use_partial_connect, MemArena *mem_arena_edgenet)
static void tri_v3_scale(float v1[3], float v2[3], float v3[3], const float t)
static void edge_verts_sort(const float co[3], LinkBase *v_ls_base)
static void edge_verts_add(ISectState *s, BMEdge *e, BMVert *v, const bool use_test)
static void vert_dissolve_add(ISectState *s, BMVert *v)
static int isect_bvhtree_point_v3(BVHTree *tree, const float **looptris, const float co[3])
static BMEdge * bm_vert_other_edge(BMVert *v, BMEdge *e)
@ BMESH_ISECT_BOOLEAN_DIFFERENCE
@ BMESH_ISECT_BOOLEAN_NONE
@ BMESH_ISECT_BOOLEAN_UNION
@ BMESH_ISECT_BOOLEAN_ISECT
#define BM_ITER_MESH_MUTABLE(ele, ele_next, iter, bm, itype)
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_select_history_clear(BMesh *bm)
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.
BMEdge * BM_vert_collapse_edge(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, const bool do_del, const bool kill_degenerate_faces, const bool kill_duplicate_faces)
Vert Collapse Faces.
void BM_face_calc_point_in_face(const BMFace *f, float r_co[3])
void BM_face_normal_flip(BMesh *bm, BMFace *f)
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)
#define BM_ELEM_API_FLAG_DISABLE(element, f)
#define BM_ELEM_API_FLAG_TEST(element, f)
bool BM_vert_pair_share_face_check(BMVert *v_a, BMVert *v_b)
int BM_mesh_calc_face_groups(BMesh *bm, int *r_groups_array, int(**r_group_index)[2], BMLoopFilterFunc filter_fn, BMLoopPairFilterFunc filter_pair_fn, void *user_data, const char hflag_test, const char htype_step)
bool BM_edge_in_face(const BMEdge *e, const BMFace *f)
bool BM_face_share_edge_check(BMFace *f1, BMFace *f2)
BMEdge * BM_edge_exists(BMVert *v_a, BMVert *v_b)
bool BM_vert_is_edge_pair(const BMVert *v)
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 * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
local_group_size(16, 16) .push_constant(Type b
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
static MemArena * mem_arena
void *(* MEM_mallocN)(size_t len, const char *str)
void MEM_freeN(void *vmemh)
ccl_device_inline float3 cos(float3 v)
struct BMLoop * radial_next
int(* test_fn)(BMFace *f, void *user_data)