38# define USE_EDGEQUEUE_TAG_VERIFY
45static void pbvh_bmesh_verify(
Tree *pbvh);
66#define BM_LOOPS_OF_VERT_ITER_BEGIN(l_iter_radial_, v_) \
70 BMEdge *e_iter, *e_first; \
71 BMLoop *l_iter_radial; \
75 _iter.e_iter = _iter.e_first = _iter.v->e; \
77 if (_iter.e_iter->l) { \
78 _iter.l_iter_radial = _iter.e_iter->l; \
80 if (_iter.l_iter_radial->v == _iter.v) { \
81 l_iter_radial_ = _iter.l_iter_radial;
83#define BM_LOOPS_OF_VERT_ITER_END \
86 while ((_iter.l_iter_radial = _iter.l_iter_radial->radial_next) != _iter.e_iter->l) \
90 while ((_iter.e_iter = BM_DISK_EDGE_NEXT(_iter.e_iter, _iter.v)) != _iter.e_first) \
96#define BM_FACES_OF_VERT_ITER_BEGIN(f_iter_, v_) \
98 BMLoop *l_iter_radial_; \
99 BM_LOOPS_OF_VERT_ITER_BEGIN (l_iter_radial_, v_) { \
100 f_iter_ = l_iter_radial_->f;
102#define BM_FACES_OF_VERT_ITER_END \
104 BM_LOOPS_OF_VERT_ITER_END; \
110 return {
float3(std::numeric_limits<float>::max()),
float3(std::numeric_limits<float>::lowest())};
128 std::array<BMVert *, 3>
result;
158 !
ELEM(v_opposite, l_radial_first->
v, l_radial_first->
next->
v, l_radial_first->
prev->
v));
159 if (l_radial_first->
radial_next != l_radial_first) {
163 if (l_radial_iter->
prev->
v == v_opposite) {
164 return l_radial_iter->
f;
166 }
while ((l_radial_iter = l_radial_iter->
radial_next) != l_radial_first);
179 if (v_next_p ==
nullptr) {
183 if (*v_next_p ==
nullptr) {
199 const int node_index,
200 const int cd_vert_node_offset,
201 const int cd_face_node_offset)
203 bool has_visible =
false;
213 const BMLoop *l_iter = l_first;
228 }
while ((l_iter = l_iter->
next) != l_first);
246 const int cd_vert_node_offset,
247 const int cd_face_node_offset,
249 const int node_index)
254 nodes[node_index], node_index, cd_vert_node_offset, cd_face_node_offset);
260 for (
const BMFace *f :
nodes[node_index].bm_faces_) {
271 const int children =
nodes.size();
272 nodes[node_index].children_offset_ = children;
274 node_changed.
resize(node_changed.
size() + 2,
true);
281 c2->parent_ = node_index;
283 c2->bm_faces_.reserve(
nodes[node_index].bm_faces_.size() / 2);
292 c2->bm_faces_.add(f);
301 other = &c2->bm_faces_;
303 else if (c2->bm_faces_.is_empty()) {
304 empty = &c2->bm_faces_;
308 for (
BMFace *f : *other) {
326 nodes[node_index].bm_faces_.clear();
329 node_changed[node_index] =
true;
333 nodes, node_changed, cd_vert_node_offset, cd_face_node_offset, face_bounds, children);
335 nodes, node_changed, cd_vert_node_offset, cd_face_node_offset, face_bounds, children + 1);
339 nodes[
nodes[node_index].children_offset_ + 1].bounds_);
340 nodes[node_index].bounds_orig_ =
nodes[node_index].bounds_;
347 const int cd_vert_node_offset,
348 const int cd_face_node_offset,
349 const int node_index)
351 const int faces_num =
nodes[node_index].bm_faces_.size();
368 }
while ((l_iter = l_iter->
next) != l_first);
379 nodes, node_changed, cd_vert_node_offset, cd_face_node_offset, face_bounds, node_index);
389 cd_vert_node_offset);
397 cd_face_node_offset);
403 const int cd_vert_node_offset,
410 const int cd_face_node_offset,
422 const int node_index,
425 const int cd_vert_node_offset,
426 const int cd_vert_mask_offset)
444 node_changed[node_index] =
true;
458 const int cd_face_node_offset,
460 const int node_index,
477 node_changed[node_index] =
true;
486#define pbvh_bmesh_node_vert_use_count_is_equal(nodes, cd_face_node_offset, node, v, n) \
487 (pbvh_bmesh_node_vert_use_count_at_most(nodes, cd_face_node_offset, node, v, (n) + 1) == n)
490 const int cd_face_node_offset,
500 if (f_node == node) {
502 if (
count == count_max) {
514 const int cd_face_node_offset,
523 if (f_node != current_node) {
534 const int cd_vert_node_offset,
535 const int new_owner_index,
541 node_changed[new_owner_index] =
true;
557 node_changed[new_owner_index] =
true;
562 const int cd_vert_node_offset,
563 const int cd_face_node_offset,
579 if (f_node_index_prev != f_node_index) {
580 f_node_index_prev = f_node_index;
584 node_changed[f_node_index] =
true;
598 const int cd_vert_node_offset,
599 const int cd_face_node_offset,
608 const BMLoop *l_iter = l_first;
616 cd_vert_node_offset, cd_face_node_offset,
v);
621 nodes, node_changed, cd_vert_node_offset, *new_node,
v);
629 }
while ((l_iter = l_iter->
next) != l_first);
640 node_changed[node_index] =
true;
646 std::array<BMLoop *, 2> manifold_loops;
690#define EDGE_QUEUE_TEST(e) BM_elem_flag_test((CHECK_TYPE_INLINE(e, BMEdge *), e), BM_ELEM_TAG)
691#define EDGE_QUEUE_ENABLE(e) BM_elem_flag_enable((CHECK_TYPE_INLINE(e, BMEdge *), e), BM_ELEM_TAG)
692#define EDGE_QUEUE_DISABLE(e) \
693 BM_elem_flag_disable((CHECK_TYPE_INLINE(e, BMEdge *), e), BM_ELEM_TAG)
695#ifdef USE_EDGEQUEUE_TAG_VERIFY
698static void pbvh_bmesh_edge_tag_verify(Tree *pbvh)
700 for (
int n = 0; n < pbvh->totnode; n++) {
701 Node *node = &pbvh->nodes_[n];
702 if (node->bm_faces_) {
711 e_tri[0] = l_iter->
e;
712 l_iter = l_iter->
next;
713 e_tri[1] = l_iter->
e;
714 l_iter = l_iter->
next;
715 e_tri[2] = l_iter->
e;
727 std::array<BMVert *, 3> v_tri;
743 std::array<BMVert *, 3> v_tri;
748 std::array<float3, 3> tri_proj;
810 const BMEdge *first_edge = edge;
811 if (first_edge ==
nullptr) {
881 const float limit_len)
903 static constexpr float even_edgelen_threshold = 1.2f;
906 static constexpr float even_generation_scale = 1.6f;
908 const float len_sq_cmp = len_sq * even_edgelen_threshold;
910 const float new_limit_len = limit_len * even_generation_scale;
911 const float new_limit_len_sq =
square_f(new_limit_len);
913 const BMLoop *l_iter = l_edge;
915 std::array<BMLoop *, 2> l_adjacent = {l_iter->
next, l_iter->
prev};
916 for (
int i = 0;
i < l_adjacent.size();
i++) {
918 if (len_sq_other >
max_ff(len_sq_cmp, new_limit_len_sq)) {
921 eq_ctx, l_adjacent[
i]->radial_next, l_adjacent[
i], len_sq_other, new_limit_len);
948 const BMLoop *l_iter = l_first;
955 }
while ((l_iter = l_iter->
next) != l_first);
970 const BMLoop *l_iter = l_first;
973 }
while ((l_iter = l_iter->
next) != l_first);
988 const float max_edge_len,
991 const std::optional<float3> view_normal,
993 const bool use_frontface,
994 const bool use_projected)
997 view_normal || (!use_frontface && !use_projected),
998 "If either use_frontface or use_projected is specified, view_normal must be non-empty");
1010 if (use_projected && view_normal) {
1018#ifdef USE_EDGEQUEUE_TAG_VERIFY
1019 pbvh_bmesh_edge_tag_verify(
pbvh);
1027 for (
BMFace *f : node.bm_faces_) {
1045 const float min_edge_len,
1048 const std::optional<float3> view_normal,
1050 const bool use_frontface,
1051 const bool use_projected)
1054 view_normal || (!use_frontface && !use_projected),
1055 "If either use_frontface or use_projected is specified, view_normal must be non-empty");
1067 if (use_projected && view_normal) {
1080 for (
BMFace *f : node.bm_faces_) {
1118 const int cd_vert_node_offset,
1119 const int cd_face_node_offset,
1140 cd_vert_node_offset,
1145 const BMLoop *l_adj = edge_loops[
i];
1159 if (ni != node_index &&
i == 0) {
1189 const std::array<BMVert *, 3> first_tri({v1, v_new, v_opp});
1194 bm,
nodes, node_changed, cd_face_node_offset, bm_log, ni, first_tri, first_edges, f_adj);
1198 const std::array<BMVert *, 3> second_tri({v_new,
v2, v_opp});
1199 const std::array<BMEdge *, 3> second_edges{
1207 bm,
nodes, node_changed, cd_face_node_offset, bm_log, ni, second_tri, second_edges, f_adj);
1212 nodes, node_changed, cd_vert_node_offset, cd_face_node_offset, bm_log, f_adj);
1216 if (!
nodes[ni].bm_unique_verts_.contains(v_new)) {
1217 nodes[ni].bm_other_verts_.add(v_new);
1236 const int cd_vert_node_offset,
1237 const int cd_face_node_offset,
1242 bool any_subdivided =
false;
1271 any_subdivided =
true;
1274 eq_ctx,
bm,
nodes, node_changed, cd_vert_node_offset, cd_face_node_offset, bm_log,
e);
1277#ifdef USE_EDGEQUEUE_TAG_VERIFY
1278 pbvh_bmesh_edge_tag_verify(
pbvh);
1283 return any_subdivided;
1349 CLOG_WARN(&
LOG,
"Unable to find edge shared between deleting and flap faces");
1364 const std::array<const BMEdge *, 4> source_edges{
1377 for (
const BMEdge *src_edge : source_edges) {
1379 CLOG_WARN(&
LOG,
"Unable to find source edge for flap attributes merge");
1394 BMVert *flap_vert =
nullptr;
1441 const BMEdge *edge_2 = l_flap->
e;
1502 CLOG_WARN(&
LOG,
"Unable to find edge shared between old and new faces");
1509 if (dst_edge == edge_v1_v2) {
1525 CLOG_WARN(&
LOG,
"Unable to find edge to merge attributes from");
1533 const int cd_vert_node_offset,
1534 const int cd_face_node_offset,
1547 if (v1_on_boundary || v2_on_boundary) {
1553 if (v1_on_boundary) {
1596 deleted_faces.
append(f_del);
1604 deleted_faces.
append(existing_face);
1611 while ((l_adj =
e->l)) {
1615 nodes, node_changed, cd_vert_node_offset, cd_face_node_offset, bm_log, f_adj);
1631 const std::array<BMVert *, 3> v_tri{v_conn,
l->next->v,
l->prev->v};
1635 const int ni = n -
nodes.data();
1638 bm,
nodes, node_changed, cd_face_node_offset, bm_log, ni, v_tri, e_tri, f);
1651 for (
BMFace *f_del : deleted_faces) {
1655 const std::array<BMVert *, 3> v_tri{l_iter->
v, l_iter->
next->
v, l_iter->
next->
next->
v};
1656 const std::array<BMEdge *, 3> e_tri{l_iter->
e, l_iter->
next->
e, l_iter->
next->
next->
e};
1665 nodes, node_changed, cd_vert_node_offset, cd_face_node_offset, bm_log, f_del);
1679 if ((v_tri[j] != v_del) && (v_tri[j]->
e ==
nullptr)) {
1681 nodes, node_changed, cd_vert_node_offset, cd_face_node_offset, v_tri[j]);
1685 if (v_tri[j] == v_conn) {
1688 deleted_verts.
add_new(v_tri[j],
nullptr);
1706 if (v_conn !=
nullptr) {
1711 node_changed[f_node] =
true;
1720 deleted_verts.
add_new(v_del, v_conn);
1725 const float min_edge_len,
1729 const int cd_vert_node_offset,
1730 const int cd_face_node_offset,
1735 const float min_len_squared = min_edge_len * min_edge_len;
1736 bool any_collapsed =
false;
1750 if (!v1 || !
v2 || (v1 ==
v2)) {
1774 any_collapsed =
true;
1779 cd_vert_node_offset,
1780 cd_face_node_offset,
1791 return any_collapsed;
1798 const float3 &ray_normal,
1802 BMVert **r_active_vertex,
1806 float3 nearest_vertex_co(0.0f);
1808 use_original = use_original && !node.
orig_tris_.is_empty();
1811 for (
const int tri_idx : node.
orig_tris_.index_range()) {
1817 ray_start, isect_precalc, positions[0], positions[1], positions[2], depth))
1821 r_face_normal =
math::normal_tri(positions[0], positions[1], positions[2]);
1823 if (r_active_vertex) {
1824 const float3 location = ray_start + ray_normal * *depth;
1825 for (
int i = 0;
i < positions.size();
i++) {
1829 nearest_vertex_co = positions[
i];
1842 std::array<BMVert *, 3> v_tri;
1845 std::array<float3, 3> positions = {v_tri[0]->co, v_tri[1]->co, v_tri[2]->co};
1848 ray_start, isect_precalc, positions[0], positions[1], positions[2], depth))
1852 r_face_normal =
math::normal_tri(positions[0], positions[1], positions[2]);
1854 if (r_active_vertex) {
1855 const float3 location = ray_start + ray_normal * *depth;
1856 for (
int i = 0;
i < positions.size();
i++) {
1860 nearest_vertex_co = positions[
i];
1861 *r_active_vertex = v_tri[
i];
1877 float *r_edge_length)
1889 std::array<BMVert *, 3> v_tri;
1892 ray_start, isect_precalc, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co, depth))
1901 std::array<BMVert *, 3> v_tri;
1917 const float3 &ray_normal,
1920 const bool use_original)
1924 if (use_original && !node.
orig_tris_.is_empty()) {
1925 for (
const int i : node.
orig_tris_.index_range()) {
1940 std::array<BMVert *, 3> v_tri;
1944 ray_start, ray_normal, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co, r_depth, dist_sq);
2008 for (
int i = node->
start;
i < end - num_child2;
i++) {
2009 const BMFace *f = nodeinfo[
i];
2013 int i_iter = end - num_child2 - 1;
2017 for (; i_iter >
i; i_iter--) {
2018 const BMFace *f_iter = nodeinfo[i_iter];
2021 face_bounds[face_iter_i].
max[axis]) <= mid)
2030 if (candidate != -1) {
2032 nodeinfo[
i] = nodeinfo[candidate];
2033 nodeinfo[candidate] = tmp;
2050 if (num_child2 == 0) {
2054 else if (num_child1 == 0) {
2074 child1->
child1 =
nullptr;
2075 child1->
child2 =
nullptr;
2079 child2->
child1 =
nullptr;
2080 child2->
child2 =
nullptr;
2087 const int cd_vert_node_offset,
2088 const int cd_face_node_offset,
2092 const int node_index,
2093 const int parent_index)
2096 nodes[node_index].parent_ = parent_index;
2100 int children_offset_ =
nodes.size();
2102 nodes[node_index].children_offset_ = children_offset_;
2105 cd_vert_node_offset,
2106 cd_face_node_offset,
2113 cd_vert_node_offset,
2114 cd_face_node_offset,
2118 children_offset_ + 1,
2130 for (
int i = node->
start;
i < end;
i++) {
2134 nodes[node_index].bm_faces_.add_new(f);
2139 const BMLoop *l_iter = l_first;
2142 if (!
nodes[node_index].bm_unique_verts_.contains(
v)) {
2144 nodes[node_index].bm_other_verts_.add(
v);
2147 nodes[node_index].bm_unique_verts_.add(
v);
2151 }
while ((l_iter = l_iter->
next) != l_first);
2161 if (
bm.totface == 0) {
2182 const BMLoop *l_iter = l_first;
2185 }
while ((l_iter = l_iter->
next) != l_first);
2215 nodes, cd_vert_node_offset, cd_face_node_offset, nodeinfo, face_bounds, &rootnode, 0, -1);
2217 pbvh.tag_positions_changed(
nodes.index_range());
2218 pbvh.update_bounds_bmesh(
bm);
2222 for (const int i : range) {
2223 const Set<BMFace *, 0> &faces = BKE_pbvh_bmesh_node_faces(&nodes[i]);
2224 if (std::all_of(faces.begin(), faces.end(), [&](const BMFace *face) {
2225 return BM_elem_flag_test(face, BM_ELEM_HIDDEN);
2228 nodes[i].flag_ |= Node::FullyHidden;
2243 const float min_edge_len,
2244 const float max_edge_len,
2246 const std::optional<float3> &view_normal,
2248 const bool use_frontface,
2249 const bool use_projected)
2258 bool modified =
false;
2261 "View normal must be non-zero length if provided");
2273 cd_vert_mask_offset,
2274 cd_vert_node_offset,
2275 cd_face_node_offset,
2279 &eq_ctx, min_edge_len,
nodes, center, view_normal, radius, use_frontface, use_projected);
2285 cd_vert_node_offset,
2286 cd_face_node_offset,
2299 cd_vert_mask_offset,
2300 cd_vert_node_offset,
2301 cd_face_node_offset,
2305 &eq_ctx, max_edge_len,
nodes, center, view_normal, radius, use_frontface, use_projected);
2307 &eq_ctx,
bm,
nodes, node_changed, cd_vert_node_offset, cd_face_node_offset, bm_log);
2314 pbvh.tag_positions_changed(node_mask);
2315 pbvh.tag_topology_changed(node_mask);
2320 node.flag_ &=
~Node::UpdateTopology;
2327 node.flag_ &=
~Node::TopologyUpdated;
2329 if (!node.orig_tris_.is_empty()) {
2338 pbvh_bmesh_verify(
pbvh);
2349 if (!use_original) {
2402 const int tris_num = std::count_if(
2404 return !BM_elem_flag_test_bool(face, BM_ELEM_HIDDEN);
2430 for (
const int i : orig_range) {
2434 pbvh_bmesh_node_drop_orig(n);
2437 pbvh_bmesh_node_limit_ensure(
2438 bm,
nodes, node_changed, cd_vert_node_offset, cd_face_node_offset,
i);
2446 update_mask_bmesh(
bm, node_mask, pbvh);
2475static void pbvh_bmesh_print(Tree *
pbvh)
2477 fprintf(stderr,
"\npbvh=%p\n",
pbvh);
2478 fprintf(stderr,
"bm_face_to_node:\n");
2487 fprintf(stderr,
"bm_vert_to_node:\n");
2494 for (
int n = 0; n <
pbvh->totnode; n++) {
2495 Node *node = &
pbvh->nodes_[n];
2496 if (!(node->flag & Node::Leaf)) {
2501 fprintf(stderr,
"node %d\n faces:\n", n);
2504 fprintf(stderr,
" unique verts:\n");
2505 GSET_ITER (gs_iter, node->bm_unique_verts_)
2507 fprintf(stderr,
" other verts:\n");
2508 GSET_ITER (gs_iter, node->bm_other_verts_)
2513static
void print_flag_factors(
int flag)
2516 for (
int i = 0;
i < 32;
i++) {
2517 if (
flag & (1 <<
i)) {
2518 printf(
" %d (1 << %d)\n", 1 <<
i,
i);
2526static void pbvh_bmesh_verify(Tree *
pbvh)
2552 int totface = 0, totvert = 0;
2553 for (
int i = 0;
i <
pbvh->totnode;
i++) {
2554 Node *n = &
pbvh->nodes_[
i];
2555 totface += n->bm_faces_.is_empty() ? n->bm_faces_.size() : 0;
2556 totvert += n->bm_unique_verts_ ? n->bm_unique_verts_.size() : 0;
2568 Node *n = pbvh_bmesh_node_lookup(
pbvh, f);
2585 nv = pbvh_bmesh_node_lookup(
pbvh,
v);
2605 Node *n = pbvh_bmesh_node_lookup(
pbvh,
v);
2619 BMFace *f =
nullptr;
2621 if (pbvh_bmesh_node_lookup(
pbvh, f) == n) {
2631 for (
int i = 0;
i <
pbvh->totnode;
i++) {
2632 Node *n_other = &
pbvh->nodes_[
i];
2633 if ((n != n_other) && (n_other->bm_unique_verts_)) {
2645 bool has_unique =
false;
2646 for (
int i = 0;
i <
pbvh->totnode;
i++) {
2647 Node *n = &
pbvh->nodes_[
i];
2648 if ((n->bm_unique_verts_ !=
nullptr) &&
BLI_gset_haskey(n->bm_unique_verts_, vi)) {
2661 for (
int i = 0;
i <
pbvh->totnode;
i++) {
2662 Node *n = &
pbvh->nodes_[
i];
2663 if (n->flag & Node::Leaf) {
2666 for (BMFace *f : n->bm_faces_) {
2667 Node *n_other = pbvh_bmesh_node_lookup(
pbvh, f);
2672 GSET_ITER (gs_iter, n->bm_unique_verts_) {
2674 Node *n_other = pbvh_bmesh_node_lookup(
pbvh,
v);
2680 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)
#define BLI_assert_msg(a, msg)
bool BLI_gset_haskey(const GSet *gs, const void *key) ATTR_WARN_UNUSED_RESULT
struct GSetIterator GSetIterator
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_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])
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 add_v3_v3(float r[3], const float a[3])
MINLINE float normalize_v3(float n[3])
#define BLI_MEMARENA_STD_BUFSIZE
MemArena * BLI_memarena_new(size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(2) ATTR_MALLOC
void BLI_memarena_free(MemArena *ma) ATTR_NONNULL(1)
void * BLI_memarena_alloc(MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
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_DEBUG(clg_ref,...)
#define CLOG_WARN(clg_ref,...)
#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)
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
void reinitialize(const int64_t new_size)
void reserve(const int64_t n)
bool contains(const Key &key) const
bool remove(const Key &key)
void reserve(const int64_t n)
int64_t index_of(const Key &key) const
IndexRange index_range() const
static IndexMask from_bools(Span< bool > bools, IndexMaskMemory &memory)
const Value * lookup_ptr(const Key &key) const
void add_new(const Key &key, const Value &value)
constexpr const T * data() const
void append(const T &value)
void resize(const int64_t new_size)
Bounds< float3 > bounds_orig_
Tree(const Tree &other)=delete
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_
void foreach_index(Fn &&fn) const
static void edge_queue_insert(const EdgeQueueContext *eq_ctx, BMEdge *e, const float priority)
static BMFace * pbvh_bmesh_face_create(BMesh &bm, MutableSpan< BMeshNode > nodes, MutableSpan< bool > node_changed, const int cd_face_node_offset, BMLog &bm_log, const int node_index, const Span< BMVert * > v_tri, const Span< BMEdge * > e_tri, const BMFace *f_example)
static void long_edge_queue_edge_add_recursive(const EdgeQueueContext *eq_ctx, const BMLoop *l_edge, const BMLoop *l_end, const float len_sq, const float limit_len)
static std::array< BMEdge *, 3 > bm_edges_from_tri(BMesh &bm, const Span< BMVert * > v_tri)
static void long_edge_queue_face_add(const EdgeQueueContext *eq_ctx, BMFace *f)
static bool check_mask(const EdgeQueueContext *eq_ctx, const BMVert *v)
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 bmesh_node_nearest_to_ray(BMeshNode &node, const float3 &ray_start, const float3 &ray_normal, float *r_depth, float *dist_sq, const bool use_original)
static void long_edge_queue_create(const EdgeQueueContext *eq_ctx, const float max_edge_len, MutableSpan< BMeshNode > nodes, const float3 ¢er, const std::optional< float3 > view_normal, const float radius, const bool use_frontface, const bool use_projected)
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, const int node_index)
void update_mask_bmesh(const BMesh &bm, const IndexMask &node_mask, Tree &pbvh)
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)
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, Map< BMVert *, BMVert * > &deleted_verts, const EdgeQueueContext *eq_ctx)
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 float3 &co, const float3 &no, const int cd_vert_node_offset, const int cd_vert_mask_offset)
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, const FastNodeBuildInfo *node, const int node_index, const int parent_index)
BLI_INLINE int pbvh_bmesh_node_index_from_face(const int cd_face_node_offset, const BMFace *key)
static BMVert * bm_vert_hash_lookup_chain(Map< BMVert *, BMVert * > &deleted_verts, BMVert *v)
static void copy_original_vert(BMLog *log, BMeshNode *node, BMVert *v, int i, bool use_original)
BLI_INLINE std::array< BMVert *, 3 > bm_face_as_array(const BMFace &f)
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 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, const int node_index)
void bmesh_normals_update(Tree &pbvh, const IndexMask &nodes_to_update)
static void short_edge_queue_create(const EdgeQueueContext *eq_ctx, const float min_edge_len, MutableSpan< BMeshNode > nodes, const float3 ¢er, const std::optional< float3 > view_normal, const float radius, const bool use_frontface, const bool use_projected)
static bool pbvh_bmesh_subdivide_long_edges(const 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)
bool node_raycast_bmesh(BMeshNode &node, const float3 &ray_start, const float3 &ray_normal, const IsectRayPrecalc *isect_precalc, float *depth, bool use_original, BMVert **r_active_vertex, float3 &r_face_normal)
static bool pbvh_bmesh_collapse_short_edges(const 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 Bounds< float3 > negative_bounds()
static bool is_boundary_edge(const BMEdge &edge)
static void pbvh_bmesh_split_edge(const 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(const BMLoop *l_radial_first, const BMVert *v_opposite)
static bool edge_queue_tri_in_sphere(const EdgeQueue *queue, BMFace *f)
static void merge_edge_data(BMesh &bm, BMEdge &dst, const BMEdge &src)
static constexpr int dyntopo_node_none
static void short_edge_queue_edge_add(const EdgeQueueContext *eq_ctx, BMEdge *e)
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)
bool bmesh_update_topology(BMesh &bm, Tree &pbvh, BMLog &bm_log, PBVHTopologyUpdateMode mode, float min_edge_len, float max_edge_len, const float3 ¢er, const std::optional< float3 > &view_normal, float radius, bool use_frontface, bool use_projected)
static void merge_flap_edge_data(BMesh &bm, const BMFace *del_face, const BMFace *flap_face, BMEdge *e, BMVert *v_del, const BMLoop *l_del, BMVert *v_conn)
bool raycast_node_detail_bmesh(const BMeshNode &node, const float3 &ray_start, const IsectRayPrecalc *isect_precalc, float *depth, float *r_edge_length)
static void merge_face_edge_data(BMesh &bm, BMFace *, BMFace *new_face, BMVert *v_del, const BMLoop *l_del, const BMVert *v_conn)
static void pbvh_bmesh_node_drop_orig(BMeshNode *node)
static void copy_edge_data(BMesh &bm, BMEdge &dst, const BMEdge &src)
static void pbvh_bmesh_node_limit_ensure_fast(const MutableSpan< BMFace * > nodeinfo, const Span< Bounds< float3 > > face_bounds, FastNodeBuildInfo *node, MemArena *arena)
static void pbvh_bmesh_node_finalize(BMeshNode &n, const int node_index, const int cd_vert_node_offset, const int cd_face_node_offset)
BLI_INLINE int pbvh_bmesh_node_index_from_vert(const int cd_vert_node_offset, const BMVert *key)
bool ray_face_intersection_tri(const float3 &ray_start, const IsectRayPrecalc *isect_precalc, const float3 &t0, const float3 &t1, const float3 &t2, float *depth)
static void short_edge_queue_face_add(const EdgeQueueContext *eq_ctx, BMFace *f)
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 float long_edge_queue_priority(const BMEdge &edge)
static bool is_boundary_vert(const BMVert &vertex)
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 Array< BMLoop * > pbvh_bmesh_edge_loops(BMEdge *e)
static bool is_edge_adjacent_to_boundary(const BMEdge &edge)
static void long_edge_queue_edge_add(const EdgeQueueContext *eq_ctx, BMEdge *e)
static int pbvh_bmesh_node_vert_use_count_at_most(MutableSpan< BMeshNode > nodes, const int cd_face_node_offset, const BMeshNode *node, BMVert *v, const int count_max)
static bool edge_queue_tri_in_circle(const EdgeQueue *queue, BMFace *f)
Bounds< T > merge(const Bounds< T > &a, const Bounds< T > &b)
T length_squared(const VecBase< T, Size > &a)
VecBase< T, 3 > normal_tri(const VecBase< T, 3 > &v1, const VecBase< T, 3 > &v2, const VecBase< T, 3 > &v3)
T midpoint(const T &a, const T &b)
void min_max(const T &value, T &min, T &max)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
T distance_squared(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
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 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
Array< int3, 0 > orig_tris_
Set< BMFace *, 0 > bm_faces_
Array< BMVert *, 0 > orig_verts_
Array< float3, 0 > orig_positions_
Set< BMVert *, 0 > bm_unique_verts_
Set< BMVert *, 0 > bm_other_verts_
std::optional< float3 > view_normal
bool(* edge_queue_tri_in_range)(const EdgeQueue *q, BMFace *f)
FastNodeBuildInfo * child1
FastNodeBuildInfo * child2