33#define USE_EDGEQUEUE_EVEN_SUBDIV
34#ifdef USE_EDGEQUEUE_EVEN_SUBDIV
41#define USE_EDGEQUEUE_FRONTFACE
44#define USE_EDGEQUEUE_TAG
49#if defined(USE_EDGEQUEUE_TAG) && 0
51# define USE_EDGEQUEUE_TAG_VERIFY
58static void pbvh_bmesh_verify(Tree *pbvh);
77#define BM_LOOPS_OF_VERT_ITER_BEGIN(l_iter_radial_, v_) \
81 BMEdge *e_iter, *e_first; \
82 BMLoop *l_iter_radial; \
86 _iter.e_iter = _iter.e_first = _iter.v->e; \
88 if (_iter.e_iter->l) { \
89 _iter.l_iter_radial = _iter.e_iter->l; \
91 if (_iter.l_iter_radial->v == _iter.v) { \
92 l_iter_radial_ = _iter.l_iter_radial;
94#define BM_LOOPS_OF_VERT_ITER_END \
97 while ((_iter.l_iter_radial = _iter.l_iter_radial->radial_next) != _iter.e_iter->l) \
101 while ((_iter.e_iter = BM_DISK_EDGE_NEXT(_iter.e_iter, _iter.v)) != _iter.e_first) \
107#define BM_FACES_OF_VERT_ITER_BEGIN(f_iter_, v_) \
109 BMLoop *l_iter_radial_; \
110 BM_LOOPS_OF_VERT_ITER_BEGIN (l_iter_radial_, v_) { \
111 f_iter_ = l_iter_radial_->f;
113#define BM_FACES_OF_VERT_ITER_END \
115 BM_LOOPS_OF_VERT_ITER_END; \
121 return {
float3(std::numeric_limits<float>::max()),
float3(std::numeric_limits<float>::lowest())};
139 std::array<BMVert *, 3>
result;
168 !
ELEM(v_opposite, l_radial_first->
v, l_radial_first->
next->
v, l_radial_first->
prev->
v));
169 if (l_radial_first->
radial_next != l_radial_first) {
173 if (l_radial_iter->
prev->
v == v_opposite) {
174 return l_radial_iter->
f;
176 }
while ((l_radial_iter = l_radial_iter->
radial_next) != l_radial_first);
189 if (v_next_p ==
nullptr) {
193 if (*v_next_p ==
nullptr) {
209 const int node_index,
210 const int cd_vert_node_offset,
211 const int cd_face_node_offset)
213 bool has_visible =
false;
238 }
while ((l_iter = l_iter->
next) != l_first);
256 const int cd_vert_node_offset,
257 const int cd_face_node_offset,
282 const int children = nodes.size();
284 nodes.resize(nodes.size() + 2);
285 node_changed.
resize(node_changed.
size() + 2,
true);
288 n = &nodes[node_index];
291 BMeshNode *c1 = &nodes[children], *c2 = &nodes[children + 1];
304 c2->bm_faces_.add(f);
313 other = &c2->bm_faces_;
315 else if (c2->bm_faces_.is_empty()) {
316 empty = &c2->bm_faces_;
320 for (
BMFace *f : *other) {
340 n->
flag_ &= ~PBVH_Leaf;
341 node_changed[node_index] =
true;
345 nodes, node_changed, cd_vert_node_offset, cd_face_node_offset, face_bounds, children);
347 nodes, node_changed, cd_vert_node_offset, cd_face_node_offset, face_bounds, children + 1);
350 n = &nodes[node_index];
362 const int cd_vert_node_offset,
363 const int cd_face_node_offset,
377 for (
BMFace *f : node.bm_faces_) {
384 }
while ((l_iter = l_iter->
next) != l_first);
395 nodes, node_changed, cd_vert_node_offset, cd_face_node_offset, face_bounds, node_index);
417 const int cd_vert_node_offset,
424 const int cd_face_node_offset,
436 const int node_index,
439 const int cd_vert_node_offset,
440 const int cd_vert_mask_offset)
444 BLI_assert((nodes.size() == 1 || node_index) && node_index <= nodes.size());
454 node->bm_unique_verts_.add(
v);
458 node_changed[node_index] =
true;
472 const int cd_face_node_offset,
487 node->bm_faces_.add(f);
491 node_changed[node_index] =
true;
492 node->flag_ &= ~PBVH_FullyHidden;
500#define pbvh_bmesh_node_vert_use_count_is_equal(nodes, cd_face_node_offset, node, v, n) \
501 (pbvh_bmesh_node_vert_use_count_at_most(nodes, cd_face_node_offset, node, v, (n) + 1) == n)
504 const int cd_face_node_offset,
514 if (f_node == node) {
516 if (
count == count_max) {
528 const int cd_face_node_offset,
537 if (f_node != current_node) {
548 const int cd_vert_node_offset,
549 const int new_owner_index,
553 BMeshNode *current_owner = &nodes[current_owner_index];
555 node_changed[new_owner_index] =
true;
557 BMeshNode *new_owner = &nodes[new_owner_index];
571 node_changed[new_owner_index] =
true;
576 const int cd_vert_node_offset,
577 const int cd_face_node_offset,
593 if (f_node_index_prev != f_node_index) {
594 f_node_index_prev = f_node_index;
596 BMeshNode *f_node = &nodes[f_node_index];
598 node_changed[f_node_index] =
true;
612 const int cd_vert_node_offset,
613 const int cd_face_node_offset,
630 cd_vert_node_offset, cd_face_node_offset,
v);
635 nodes, node_changed, cd_vert_node_offset, *new_node,
v);
643 }
while ((l_iter = l_iter->
next) != l_first);
654 node_changed[node_index] =
true;
660 std::array<BMLoop *, 2> manifold_loops;
666 nullptr,
BM_LOOPS_OF_EDGE,
e,
reinterpret_cast<void **
>(loops.data()), loops.size());
672 node->orig_positions_ = {};
673 node->orig_tris_ = {};
674 node->orig_verts_ = {};
685#ifdef USE_EDGEQUEUE_EVEN_SUBDIV
692#ifdef USE_EDGEQUEUE_FRONTFACE
707#ifdef USE_EDGEQUEUE_TAG
708# define EDGE_QUEUE_TEST(e) BM_elem_flag_test((CHECK_TYPE_INLINE(e, BMEdge *), e), BM_ELEM_TAG)
709# define EDGE_QUEUE_ENABLE(e) \
710 BM_elem_flag_enable((CHECK_TYPE_INLINE(e, BMEdge *), e), BM_ELEM_TAG)
711# define EDGE_QUEUE_DISABLE(e) \
712 BM_elem_flag_disable((CHECK_TYPE_INLINE(e, BMEdge *), e), BM_ELEM_TAG)
715#ifdef USE_EDGEQUEUE_TAG_VERIFY
718static void pbvh_bmesh_edge_tag_verify(Tree *pbvh)
720 for (
int n = 0; n < pbvh->totnode; n++) {
721 Node *node = &pbvh->nodes_[n];
722 if (node->bm_faces_) {
731 e_tri[0] = l_iter->
e;
732 l_iter = l_iter->
next;
733 e_tri[1] = l_iter->
e;
734 l_iter = l_iter->
next;
735 e_tri[2] = l_iter->
e;
763 float tri_proj[3][3];
801#ifdef USE_EDGEQUEUE_TAG
830 BMEdge *first_edge = edge;
831 if (first_edge ==
nullptr) {
890#ifdef USE_EDGEQUEUE_TAG
901#ifdef USE_EDGEQUEUE_EVEN_SUBDIV
907# ifdef USE_EDGEQUEUE_FRONTFACE
915# ifdef USE_EDGEQUEUE_TAG
930# define EVEN_EDGELEN_THRESHOLD 1.2f
933# define EVEN_GENERATION_SCALE 1.6f
938 const float limit_len_sq =
square_f(limit_len);
943 for (
int i = 0; i <
ARRAY_SIZE(l_adjacent); i++) {
945 if (len_sq_other >
max_ff(len_sq_cmp, limit_len_sq)) {
948 eq_ctx, l_adjacent[i]->radial_next, l_adjacent[i], len_sq_other, limit_len);
953# undef EVEN_EDGELEN_THRESHOLD
954# undef EVEN_GENERATION_SCALE
961#ifdef USE_EDGEQUEUE_TAG
966 if (len_sq < eq_ctx->q->limit_len_squared) {
974#ifdef USE_EDGEQUEUE_FRONTFACE
987#ifdef USE_EDGEQUEUE_EVEN_SUBDIV
996 }
while ((l_iter = l_iter->
next) != l_first);
1002#ifdef USE_EDGEQUEUE_FRONTFACE
1018 }
while ((l_iter = l_iter->
next) != l_first);
1033 const float max_edge_len,
1035 const float center[3],
1036 const float view_normal[3],
1038 const bool use_frontface,
1039 const bool use_projected)
1045#ifdef USE_EDGEQUEUE_EVEN_SUBDIV
1051#ifdef USE_EDGEQUEUE_FRONTFACE
1057 if (use_projected) {
1065#ifdef USE_EDGEQUEUE_TAG_VERIFY
1066 pbvh_bmesh_edge_tag_verify(pbvh);
1074 for (
BMFace *f : node.bm_faces_) {
1092 const float min_edge_len,
1094 const float center[3],
1095 const float view_normal[3],
1097 const bool use_frontface,
1098 const bool use_projected)
1104#ifdef USE_EDGEQUEUE_EVEN_SUBDIV
1110#ifdef USE_EDGEQUEUE_FRONTFACE
1116 if (use_projected) {
1129 for (
BMFace *f : node.bm_faces_) {
1167 const int cd_vert_node_offset,
1168 const int cd_face_node_offset,
1172 float co_mid[3], no_mid[3];
1192 cd_vert_node_offset,
1197 BMLoop *l_adj = edge_loops[i];
1211 if (ni != node_index && i == 0) {
1241 const std::array<BMVert *, 3> first_tri({v1, v_new, v_opp});
1246 bm, nodes, node_changed, cd_face_node_offset, bm_log, ni, first_tri, first_edges, f_adj);
1250 const std::array<BMVert *, 3> second_tri({v_new,
v2, v_opp});
1251 const std::array<BMEdge *, 3> second_edges{
1259 bm, nodes, node_changed, cd_face_node_offset, bm_log, ni, second_tri, second_edges, f_adj);
1264 nodes, node_changed, cd_vert_node_offset, cd_face_node_offset, bm_log, f_adj);
1268 if (!nodes[ni].bm_unique_verts_.contains(v_new)) {
1269 nodes[ni].bm_other_verts_.add(v_new);
1288 const int cd_vert_node_offset,
1289 const int cd_face_node_offset,
1294 bool any_subdivided =
false;
1309#ifdef USE_EDGEQUEUE_TAG
1325 any_subdivided =
true;
1328 eq_ctx,
bm, nodes, node_changed, cd_vert_node_offset, cd_face_node_offset, bm_log,
e);
1331#ifdef USE_EDGEQUEUE_TAG_VERIFY
1332 pbvh_bmesh_edge_tag_verify(pbvh);
1338 return any_subdivided;
1404 CLOG_WARN(&
LOG,
"Unable to find edge shared between deleting and flap faces");
1419 const std::array<const BMEdge *, 4> source_edges{
1432 for (
const BMEdge *src_edge : source_edges) {
1434 CLOG_WARN(&
LOG,
"Unable to find source edge for flap attributes merge");
1449 BMVert *flap_vert =
nullptr;
1557 CLOG_WARN(&
LOG,
"Unable to find edge shared between old and new faces");
1564 if (dst_edge == edge_v1_v2) {
1580 CLOG_WARN(&
LOG,
"Unable to find edge to merge attributes from");
1588 const int cd_vert_node_offset,
1589 const int cd_face_node_offset,
1594 GHash *deleted_verts,
1602 if (v1_on_boundary || v2_on_boundary) {
1608 if (v1_on_boundary) {
1651 deleted_faces.
append(f_del);
1659 deleted_faces.
append(existing_face);
1666 while ((l_adj =
e->l)) {
1670 nodes, node_changed, cd_vert_node_offset, cd_face_node_offset, bm_log, f_adj);
1686 const std::array<BMVert *, 3> v_tri{v_conn,
l->
next->
v,
l->
prev->
v};
1690 int ni = n - nodes.data();
1693 bm, nodes, node_changed, cd_face_node_offset, bm_log, ni, v_tri, e_tri, f);
1706 for (
BMFace *f_del : deleted_faces) {
1710 const std::array<BMVert *, 3> v_tri{l_iter->
v, l_iter->
next->
v, l_iter->
next->
next->
v};
1711 const std::array<BMEdge *, 3> e_tri{l_iter->
e, l_iter->
next->
e, l_iter->
next->
next->
e};
1720 nodes, node_changed, cd_vert_node_offset, cd_face_node_offset, bm_log, f_del);
1734 if ((v_tri[j] != v_del) && (v_tri[j]->e ==
nullptr)) {
1736 nodes, node_changed, cd_vert_node_offset, cd_face_node_offset, v_tri[j]);
1740 if (v_tri[j] == v_conn) {
1761 if (v_conn !=
nullptr) {
1766 node_changed[f_node] =
true;
1780 const float min_edge_len,
1784 const int cd_vert_node_offset,
1785 const int cd_face_node_offset,
1790 const float min_len_squared = min_edge_len * min_edge_len;
1791 bool any_collapsed =
false;
1814#ifdef USE_EDGEQUEUE_TAG
1831 any_collapsed =
true;
1836 cd_vert_node_offset,
1837 cd_face_node_offset,
1850 return any_collapsed;
1857 const float3 &ray_normal,
1861 BMVert **r_active_vertex,
1865 float3 nearest_vertex_co(0.0f);
1867 use_original = use_original && !node.orig_tris_.is_empty();
1870 for (
const int tri_idx : node.orig_tris_.index_range()) {
1873 cos[0] = node.orig_positions_[node.orig_tris_[tri_idx][0]];
1874 cos[1] = node.orig_positions_[node.orig_tris_[tri_idx][1]];
1875 cos[2] = node.orig_positions_[node.orig_tris_[tri_idx][2]];
1882 if (r_active_vertex) {
1890 *r_active_vertex = node.orig_verts_[node.orig_tris_[tri_idx][i]];
1898 for (
BMFace *f : node.bm_faces_) {
1906 ray_start, isect_precalc, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co, depth))
1910 normal_tri_v3(r_face_normal, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co);
1912 if (r_active_vertex) {
1920 *r_active_vertex = v_tri[i];
1936 float *r_edge_length)
1945 for (
BMFace *f : node.bm_faces_) {
1952 ray_start, isect_precalc, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co, depth);
1977 const float3 &ray_normal,
1984 if (use_original && !node.orig_tris_.is_empty()) {
1985 for (
const int i : node.orig_tris_.index_range()) {
1986 const int *t = node.orig_tris_[i];
1989 node.orig_positions_[t[0]],
1990 node.orig_positions_[t[1]],
1991 node.orig_positions_[t[2]],
1997 for (
BMFace *f : node.bm_faces_) {
2004 ray_start, ray_normal, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co, r_depth, dist_sq);
2017 for (
BMFace *face : node.bm_faces_) {
2020 for (
BMVert *vert : node.bm_unique_verts_) {
2023 for (
BMVert *vert : node.bm_other_verts_) {
2054 for (
int i = 0; i < node->totface; i++) {
2055 BMFace *f = nodeinfo[i + node->start];
2067 int num_child1 = 0, num_child2 = 0;
2070 const int end = node->start + node->totface;
2071 for (
int i = node->start; i < end - num_child2; i++) {
2075 if (
math::midpoint(face_bounds[face_i].
min[axis], face_bounds[face_i].max[axis]) > mid) {
2076 int i_iter = end - num_child2 - 1;
2080 for (; i_iter > i; i_iter--) {
2081 BMFace *f_iter = nodeinfo[i_iter];
2084 face_bounds[face_iter_i].max[axis]) <= mid)
2093 if (candidate != -1) {
2094 BMFace *tmp = nodeinfo[i];
2095 nodeinfo[i] = nodeinfo[candidate];
2096 nodeinfo[candidate] = tmp;
2113 if (num_child2 == 0) {
2117 else if (num_child1 == 0) {
2124 BLI_assert((num_child1 + num_child2) == node->totface);
2132 child1->
start = node->start;
2134 child2->
start = node->start + num_child1;
2142 const int cd_vert_node_offset,
2143 const int cd_face_node_offset,
2152 int children_offset_ = nodes.size();
2155 nodes.resize(nodes.size() + 2);
2157 cd_vert_node_offset,
2158 cd_face_node_offset,
2164 cd_vert_node_offset,
2165 cd_face_node_offset,
2169 children_offset_ + 1);
2178 const int end = node->start + node->totface;
2180 for (
int i = node->start; i < end; i++) {
2189 BMLoop *l_iter = l_first;
2201 }
while ((l_iter = l_iter->
next) != l_first);
2232 BMLoop *l_iter = l_first;
2235 }
while ((l_iter = l_iter->
next) != l_first);
2265 nodes, cd_vert_node_offset, cd_face_node_offset, nodeinfo, face_bounds, &rootnode, 0);
2272 for (const int i : range) {
2273 const Set<BMFace *, 0> &faces = BKE_pbvh_bmesh_node_faces(&nodes[i]);
2274 if (std::all_of(faces.begin(), faces.end(), [&](const BMFace *face) {
2275 return BM_elem_flag_test(face, BM_ELEM_HIDDEN);
2278 nodes[i].flag_ |= PBVH_FullyHidden;
2293 const float min_edge_len,
2294 const float max_edge_len,
2295 const float center[3],
2296 const float view_normal[3],
2298 const bool use_frontface,
2299 const bool use_projected)
2308 bool modified =
false;
2324 cd_vert_mask_offset,
2325 cd_vert_node_offset,
2326 cd_face_node_offset,
2330 &eq_ctx, min_edge_len, nodes, center, view_normal, radius, use_frontface, use_projected);
2336 cd_vert_node_offset,
2337 cd_face_node_offset,
2350 cd_vert_mask_offset,
2351 cd_vert_node_offset,
2352 cd_face_node_offset,
2356 &eq_ctx, max_edge_len, nodes, center, view_normal, radius, use_frontface, use_projected);
2358 &eq_ctx,
bm, nodes, node_changed, cd_vert_node_offset, cd_face_node_offset, bm_log);
2369 for (
Node &node : nodes) {
2371 node.flag_ &= ~PBVH_UpdateTopology;
2378 node.flag_ &= ~PBVH_TopologyUpdated;
2380 if (!node.orig_tris_.is_empty()) {
2389 pbvh_bmesh_verify(pbvh);
2400 if (!use_original) {
2401 node->orig_positions_[i] =
v->
co;
2406 node->orig_positions_[i] = origco;
2409 node->orig_positions_[i] =
v->
co;
2413 node->orig_verts_[i] =
v;
2425 if (!node->orig_tris_.is_empty()) {
2429 const int totvert = node->bm_unique_verts_.size() + node->bm_other_verts_.size();
2431 node->orig_positions_.reinitialize(totvert);
2432 node->orig_verts_.reinitialize(totvert);
2439 for (
BMVert *
v : node->bm_unique_verts_) {
2444 for (
BMVert *
v : node->bm_other_verts_) {
2453 const int tris_num = std::count_if(
2454 node->bm_faces_.begin(), node->bm_faces_.end(), [&](
const BMFace *face) {
2455 return !BM_elem_flag_test_bool(face, BM_ELEM_HIDDEN);
2457 node->orig_tris_.reinitialize(tris_num);
2459 for (
BMFace *f : node->bm_faces_) {
2464 node->orig_tris_[i] =
int3(
2478 Vector<bke::pbvh::BMeshNode> &nodes = std::get<Vector<bke::pbvh::BMeshNode>>(pbvh.
nodes_);
2479 Vector<bool> node_changed(nodes.size(),
false);
2481 for (
const int i : orig_range) {
2485 pbvh_bmesh_node_drop_orig(n);
2488 pbvh_bmesh_node_limit_ensure(
2489 bm, nodes, node_changed, cd_vert_node_offset, cd_face_node_offset, i);
2493 IndexMaskMemory memory;
2497 update_mask_bmesh(
bm, node_mask, pbvh);
2508 return node->bm_unique_verts_;
2514 return node->bm_other_verts_;
2519 return node->bm_faces_;
2526static void pbvh_bmesh_print(Tree *pbvh)
2528 fprintf(stderr,
"\npbvh=%p\n", pbvh);
2529 fprintf(stderr,
"bm_face_to_node:\n");
2538 fprintf(stderr,
"bm_vert_to_node:\n");
2545 for (
int n = 0; n < pbvh->totnode; n++) {
2546 Node *node = &pbvh->nodes_[n];
2552 fprintf(stderr,
"node %d\n faces:\n", n);
2555 fprintf(stderr, " unique
verts:\n");
2556 GSET_ITER (gs_iter, node->bm_unique_verts_)
2558 fprintf(stderr, " other
verts:\n");
2559 GSET_ITER (gs_iter, node->bm_other_verts_)
2564static
void print_flag_factors(
int flag)
2567 for (
int i = 0; i < 32; i++) {
2568 if (
flag & (1 << i)) {
2569 printf(
" %d (1 << %d)\n", 1 << i, i);
2577static void pbvh_bmesh_verify(Tree *pbvh)
2603 int totface = 0, totvert = 0;
2604 for (
int i = 0; i < pbvh->totnode; i++) {
2605 Node *n = &pbvh->nodes_[i];
2606 totface += n->bm_faces_.is_empty() ? n->bm_faces_.size() : 0;
2607 totvert += n->bm_unique_verts_ ? n->bm_unique_verts_.size() : 0;
2619 Node *n = pbvh_bmesh_node_lookup(pbvh, f);
2636 nv = pbvh_bmesh_node_lookup(pbvh,
v);
2656 Node *n = pbvh_bmesh_node_lookup(pbvh,
v);
2672 if (pbvh_bmesh_node_lookup(pbvh, f) == n) {
2682 for (
int i = 0; i < pbvh->totnode; i++) {
2683 Node *n_other = &pbvh->nodes_[i];
2684 if ((n != n_other) && (n_other->bm_unique_verts_)) {
2696 bool has_unique =
false;
2697 for (
int i = 0; i < pbvh->totnode; i++) {
2698 Node *n = &pbvh->nodes_[i];
2699 if ((n->bm_unique_verts_ !=
nullptr) &&
BLI_gset_haskey(n->bm_unique_verts_, vi)) {
2708 BLI_assert(vert_count == pbvh->header.bm->totvert);
2712 for (
int i = 0; i < pbvh->totnode; i++) {
2713 Node *n = &pbvh->nodes_[i];
2717 for (
BMFace *f : n->bm_faces_) {
2718 Node *n_other = pbvh_bmesh_node_lookup(pbvh, f);
2723 GSET_ITER (gs_iter, n->bm_unique_verts_) {
2725 Node *n_other = pbvh_bmesh_node_lookup(pbvh,
v);
2731 GSET_ITER (gs_iter, n->bm_other_verts_) {
int CustomData_get_offset_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
void CustomData_bmesh_copy_block(CustomData &data, void *src_block, void **dst_block)
A BVH for high poly meshes.
void BKE_pbvh_node_mark_topology_update(blender::bke::pbvh::Node &node)
void BKE_pbvh_bmesh_after_stroke(BMesh &bm, blender::bke::pbvh::Tree &pbvh)
void BKE_pbvh_node_fully_hidden_set(blender::bke::pbvh::Node &node, int fully_hidden)
const blender::Set< BMFace *, 0 > & BKE_pbvh_bmesh_node_faces(blender::bke::pbvh::BMeshNode *node)
const blender::Set< BMVert *, 0 > & BKE_pbvh_bmesh_node_unique_verts(blender::bke::pbvh::BMeshNode *node)
void BKE_pbvh_bmesh_node_save_orig(BMesh *bm, BMLog *log, blender::bke::pbvh::BMeshNode *node, bool use_original)
const blender::Set< BMVert *, 0 > & BKE_pbvh_bmesh_node_other_verts(blender::bke::pbvh::BMeshNode *node)
bool BLI_gset_haskey(const GSet *gs, const void *key) ATTR_WARN_UNUSED_RESULT
GHash * BLI_ghash_ptr_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void ** BLI_ghash_lookup_p(GHash *gh, const void *key) 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)
#define GSET_ITER(gs_iter_, gset_)
void BLI_ghash_insert(GHash *gh, void *key, void *val)
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
GSet * BLI_gset_ptr_new_ex(const char *info, unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
A min-heap / priority queue ADT.
HeapSimple * BLI_heapsimple_new(void) ATTR_WARN_UNUSED_RESULT
void BLI_heapsimple_free(HeapSimple *heap, HeapSimpleFreeFP ptrfreefp) ATTR_NONNULL(1)
void * BLI_heapsimple_pop_min(HeapSimple *heap) ATTR_NONNULL(1)
bool BLI_heapsimple_is_empty(const HeapSimple *heap) ATTR_NONNULL(1)
void BLI_heapsimple_insert(HeapSimple *heap, float value, void *ptr) ATTR_NONNULL(1)
MINLINE float max_fff(float a, float b, float c)
MINLINE float max_ff(float a, float b)
MINLINE float square_f(float a)
void closest_on_tri_to_point_v3(float r[3], const float p[3], const float v1[3], const float v2[3], const float v3[3])
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
MINLINE float len_squared_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v3_v3(float r[3], const float a[3])
void project_plane_normalized_v3_v3v3(float out[3], const float p[3], const float v_plane[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float normalize_v3(float n[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 * BLI_mempool_alloc(BLI_mempool *pool) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(1)
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_destroy(BLI_mempool *pool) ATTR_NONNULL(1)
Platform independent time functions.
double BLI_time_now_seconds(void)
#define UNUSED_VARS_NDEBUG(...)
#define CLOG_WARN(clg_ref,...)
#define CLOG_INFO(clg_ref, level,...)
#define DYNTOPO_NODE_NONE
Read Guarded memory(de)allocation.
#define BM_ELEM_CD_GET_FLOAT(ele, offset)
#define BM_DISK_EDGE_NEXT(e, v)
#define BM_ELEM_CD_GET_INT(ele, offset)
#define BM_ELEM_CD_SET_INT(ele, offset, f)
#define BM_FACE_FIRST_LOOP(p)
void BM_vert_kill(BMesh *bm, BMVert *v)
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)
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.
#define BM_elem_index_get(ele)
#define BM_elem_index_set(ele, index)
#define BM_elem_flag_test(ele, hflag)
#define BM_elem_flag_test_bool(ele, hflag)
void BM_data_interp_from_edges(BMesh *bm, const BMEdge *e_src_1, const BMEdge *e_src_2, BMEdge *e_dst, const float fac)
Data, Interpolate From Edges.
void BM_data_interp_from_verts(BMesh *bm, const BMVert *v_src_1, const BMVert *v_src_2, BMVert *v_dst, const float fac)
Data, Interpolate From Verts.
int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len)
Iterator as Array.
#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
void BM_log_face_added(BMLog *log, BMFace *f)
void BM_log_face_removed(BMLog *log, BMFace *f)
const float * BM_log_find_original_vert_co(BMLog *log, BMVert *v)
void BM_log_vert_added(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
void BM_log_vert_removed(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
void BM_log_vert_before_modified(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
void BM_vert_normal_update(BMVert *v)
void BM_face_normal_update(BMFace *f)
void BM_face_as_array_vert_tri(BMFace *f, BMVert *r_verts[3])
bool BM_edge_in_face(const BMEdge *e, const BMFace *f)
bool BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb)
BMFace * BM_face_exists(BMVert *const *varr, int len)
float BM_edge_calc_length_squared(const BMEdge *e)
BMEdge * BM_edge_exists(BMVert *v_a, BMVert *v_b)
BMLoop * BM_vert_find_first_loop(BMVert *v)
int BM_edge_face_count(const BMEdge *e)
bool BM_vert_in_face(BMVert *v, BMFace *f)
bool BM_vert_face_check(const BMVert *v)
int BM_vert_face_count_at_most(const BMVert *v, int count_max)
BLI_INLINE bool BM_edge_is_manifold(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
BLI_INLINE BMVert * BM_edge_other_vert(BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
#define BM_vert_face_count_is_equal(v, n)
BLI_INLINE bool BM_edge_is_wire(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
#define BM_vert_edge_count_is_over(v, n)
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
IndexRange index_range() const
constexpr IndexRange index_range() const
void reserve(const int64_t n)
bool contains(const Key &key) const
void add_new(const Key &key)
bool remove(const Key &key)
constexpr const T * data() const
int64_t index_of(const Key &key) const
void reserve(const int64_t n)
void append(const T &value)
void resize(const int64_t new_size)
Bounds< float3 > bounds_orig_
void tag_positions_changed(const IndexMask &node_mask)
static Tree from_bmesh(BMesh &bm)
Span< NodeT > nodes() const
void tag_topology_changed(const IndexMask &node_mask)
std::variant< Vector< MeshNode >, Vector< GridsNode >, Vector< BMeshNode > > nodes_
static IndexMask from_bools(Span< bool > bools, IndexMaskMemory &memory)
void foreach_index(Fn &&fn) const
ccl_device_inline float3 cos(float3 v)
ccl_device_inline float3 log(float3 v)
static std::array< BMEdge *, 3 > bm_edges_from_tri(BMesh &bm, const Span< BMVert * > v_tri)
BLI_INLINE std::array< BMVert *, 3 > bm_face_as_array(BMFace *f)
static BMVert * bm_vert_hash_lookup_chain(GHash *deleted_verts, BMVert *v)
static void merge_flap_edge_data(BMesh &bm, BMFace *del_face, BMFace *flap_face, BMEdge *e, BMVert *v_del, BMLoop *l_del, BMVert *v_conn)
static void long_edge_queue_create(EdgeQueueContext *eq_ctx, const float max_edge_len, MutableSpan< BMeshNode > nodes, const float center[3], const float view_normal[3], float radius, const bool use_frontface, const bool use_projected)
static void pbvh_bmesh_vert_remove(MutableSpan< BMeshNode > nodes, MutableSpan< bool > node_changed, const int cd_vert_node_offset, const int cd_face_node_offset, BMVert *v)
bool raycast_node_detail_bmesh(BMeshNode &node, const float3 &ray_start, IsectRayPrecalc *isect_precalc, float *depth, float *r_edge_length)
static void pbvh_bmesh_collapse_edge(BMesh &bm, MutableSpan< BMeshNode > nodes, MutableSpan< bool > node_changed, const int cd_vert_node_offset, const int cd_face_node_offset, BMLog &bm_log, BMEdge *e, BMVert *v1, BMVert *v2, GHash *deleted_verts, EdgeQueueContext *eq_ctx)
static BMFace * pbvh_bmesh_face_create(BMesh &bm, MutableSpan< BMeshNode > nodes, MutableSpan< bool > node_changed, const int cd_face_node_offset, BMLog &bm_log, int node_index, const Span< BMVert * > v_tri, const Span< BMEdge * > e_tri, const BMFace *f_example)
void update_mask_bmesh(const BMesh &bm, const IndexMask &node_mask, Tree &pbvh)
static void short_edge_queue_face_add(EdgeQueueContext *eq_ctx, BMFace *f)
static void pbvh_bmesh_node_finalize(BMeshNode *n, const int node_index, const int cd_vert_node_offset, const int cd_face_node_offset)
static void edge_queue_insert(EdgeQueueContext *eq_ctx, BMEdge *e, float priority)
static void pbvh_bmesh_vert_ownership_transfer(MutableSpan< BMeshNode > nodes, MutableSpan< bool > node_changed, const int cd_vert_node_offset, const int new_owner_index, BMVert *v)
BLI_INLINE int pbvh_bmesh_node_index_from_face(const int cd_face_node_offset, const BMFace *key)
static bool pbvh_bmesh_subdivide_long_edges(EdgeQueueContext *eq_ctx, BMesh &bm, MutableSpan< BMeshNode > nodes, MutableSpan< bool > node_changed, const int cd_vert_node_offset, const int cd_face_node_offset, BMLog &bm_log)
static void merge_face_edge_data(BMesh &bm, BMFace *, BMFace *new_face, BMVert *v_del, BMLoop *l_del, BMVert *v_conn)
bool node_raycast_bmesh(BMeshNode &node, const float3 &ray_start, const float3 &ray_normal, IsectRayPrecalc *isect_precalc, float *depth, bool use_original, BMVert **r_active_vertex, float3 &r_face_normal)
static void short_edge_queue_edge_add(EdgeQueueContext *eq_ctx, BMEdge *e)
static void copy_original_vert(BMLog *log, BMeshNode *node, BMVert *v, int i, bool use_original)
static BMVert * find_outer_flap_vert(BMFace &face)
bool ray_face_nearest_tri(const float3 &ray_start, const float3 &ray_normal, const float3 &t0, const float3 &t1, const float3 &t2, float *r_depth, float *dist_sq)
static BMVert * pbvh_bmesh_vert_create(BMesh &bm, MutableSpan< BMeshNode > nodes, MutableSpan< bool > node_changed, BMLog &bm_log, const BMVert *v1, const BMVert *v2, const int node_index, const float co[3], const float no[3], const int cd_vert_node_offset, const int cd_vert_mask_offset)
void bmesh_normals_update(Tree &pbvh, const IndexMask &nodes_to_update)
static int pbvh_bmesh_node_vert_use_count_at_most(MutableSpan< BMeshNode > nodes, const int cd_face_node_offset, BMeshNode *node, BMVert *v, const int count_max)
static Bounds< float3 > negative_bounds()
static bool is_boundary_edge(const BMEdge &edge)
static void merge_edge_data(BMesh &bm, BMEdge &dst, const BMEdge &src)
bool bmesh_node_nearest_to_ray(BMeshNode &node, const float3 &ray_start, const float3 &ray_normal, float *r_depth, float *dist_sq, bool use_original)
static bool edge_queue_tri_in_sphere(const EdgeQueue *q, BMFace *f)
static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, BMesh &bm, MutableSpan< BMeshNode > nodes, MutableSpan< bool > node_changed, const int cd_vert_node_offset, const int cd_face_node_offset, BMLog &bm_log, BMEdge *e)
static BMFace * bm_face_exists_tri_from_loop_vert(BMLoop *l_radial_first, BMVert *v_opposite)
static void try_merge_flap_edge_data_before_dissolve(BMesh &bm, BMFace &face)
static std::optional< int > pbvh_bmesh_vert_other_node_find(const int cd_vert_node_offset, const int cd_face_node_offset, BMVert *v)
BLI_INLINE BMeshNode * pbvh_bmesh_node_from_vert(MutableSpan< BMeshNode > nodes, const int cd_vert_node_offset, const BMVert *key)
static bool pbvh_bmesh_node_limit_ensure(BMesh &bm, Vector< BMeshNode > &nodes, Vector< bool > &node_changed, const int cd_vert_node_offset, const int cd_face_node_offset, int node_index)
static void long_edge_queue_edge_add_recursive(EdgeQueueContext *eq_ctx, BMLoop *l_edge, BMLoop *l_end, const float len_sq, float limit_len)
static bool check_mask(EdgeQueueContext *eq_ctx, BMVert *v)
static void pbvh_bmesh_node_drop_orig(BMeshNode *node)
static void pbvh_bmesh_node_limit_ensure_fast(const MutableSpan< BMFace * > nodeinfo, const Span< Bounds< float3 > > face_bounds, FastNodeBuildInfo *node, MemArena *arena)
BLI_INLINE int pbvh_bmesh_node_index_from_vert(const int cd_vert_node_offset, const BMVert *key)
void update_bounds_bmesh(const BMesh &bm, Tree &pbvh)
bool bmesh_update_topology(BMesh &bm, Tree &pbvh, BMLog &bm_log, PBVHTopologyUpdateMode mode, float min_edge_len, float max_edge_len, const float center[3], const float view_normal[3], float radius, bool use_frontface, bool use_projected)
bool ray_face_intersection_tri(const float3 &ray_start, const IsectRayPrecalc *isect_precalc, const float3 &t0, const float3 &t1, const float3 &t2, float *depth)
BLI_INLINE BMeshNode * pbvh_bmesh_node_from_face(MutableSpan< BMeshNode > nodes, const int cd_face_node_offset, const BMFace *key)
static bool vert_in_face_adjacent_to_edge(BMVert &vert, BMEdge &edge)
static void short_edge_queue_create(EdgeQueueContext *eq_ctx, const float min_edge_len, MutableSpan< BMeshNode > nodes, const float center[3], const float view_normal[3], float radius, const bool use_frontface, const bool use_projected)
static float long_edge_queue_priority(const BMEdge &edge)
static void copy_edge_data(BMesh &bm, BMEdge &dst, BMEdge &src)
static void pbvh_bmesh_node_split(Vector< BMeshNode > &nodes, Vector< bool > &node_changed, const int cd_vert_node_offset, const int cd_face_node_offset, const Span< Bounds< float3 > > face_bounds, int node_index)
static bool is_boundary_vert(const BMVert &vertex)
static void long_edge_queue_face_add(EdgeQueueContext *eq_ctx, BMFace *f)
static float short_edge_queue_priority(const BMEdge &edge)
void store_bounds_orig(Tree &pbvh)
static void pbvh_bmesh_face_remove(MutableSpan< BMeshNode > nodes, MutableSpan< bool > node_changed, const int cd_vert_node_offset, const int cd_face_node_offset, BMLog &bm_log, BMFace *f)
static void long_edge_queue_edge_add(EdgeQueueContext *eq_ctx, BMEdge *e)
static Array< BMLoop * > pbvh_bmesh_edge_loops(BMEdge *e)
static void pbvh_bmesh_create_nodes_fast_recursive(Vector< BMeshNode > &nodes, const int cd_vert_node_offset, const int cd_face_node_offset, const Span< BMFace * > nodeinfo, const Span< Bounds< float3 > > face_bounds, FastNodeBuildInfo *node, int node_index)
static bool is_edge_adjacent_to_boundary(const BMEdge &edge)
static bool pbvh_bmesh_collapse_short_edges(EdgeQueueContext *eq_ctx, const float min_edge_len, BMesh &bm, MutableSpan< BMeshNode > nodes, MutableSpan< bool > node_changed, const int cd_vert_node_offset, const int cd_face_node_offset, BMLog &bm_log)
static bool edge_queue_tri_in_circle(const EdgeQueue *q, BMFace *f)
Bounds< T > merge(const Bounds< T > &a, const Bounds< T > &b)
T midpoint(const T &a, const T &b)
void min_max(const T &value, T &min, T &max)
int dominant_axis(const VecBase< T, 3 > &a)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
VecBase< int32_t, 3 > int3
VecBase< float, 3 > float3
#define BM_LOOPS_OF_VERT_ITER_END
#define BM_FACES_OF_VERT_ITER_BEGIN(f_iter_, v_)
#define pbvh_bmesh_node_vert_use_count_is_equal(nodes, cd_face_node_offset, node, v, n)
#define BM_LOOPS_OF_VERT_ITER_BEGIN(l_iter_radial_, v_)
#define EVEN_GENERATION_SCALE
#define EVEN_EDGELEN_THRESHOLD
#define BM_FACES_OF_VERT_ITER_END
#define EDGE_QUEUE_DISABLE(e)
#define EDGE_QUEUE_ENABLE(e)
#define EDGE_QUEUE_TEST(e)
struct BMLoop * radial_next
Set< BMFace *, 0 > bm_faces_
Set< BMVert *, 0 > bm_unique_verts_
Set< BMVert *, 0 > bm_other_verts_
const float * view_normal
bool(* edge_queue_tri_in_range)(const EdgeQueue *q, BMFace *f)
FastNodeBuildInfo * child1
FastNodeBuildInfo * child2