diff --git a/source/blender/blenkernel/BKE_bvhutils.hh b/source/blender/blenkernel/BKE_bvhutils.hh index 1c6c4757846..383b0e3e64c 100644 --- a/source/blender/blenkernel/BKE_bvhutils.hh +++ b/source/blender/blenkernel/BKE_bvhutils.hh @@ -23,11 +23,19 @@ struct MFace; struct Mesh; struct PointCloud; +class BVHTreeDeleter { + public: + void operator()(BVHTree *tree) + { + BLI_bvhtree_free(tree); + } +}; + /** * Struct that stores basic information about a #BVHTree built from a mesh. */ struct BVHTreeFromMesh { - BVHTree *tree = nullptr; + const BVHTree *tree = nullptr; /** Default callbacks to BVH nearest and ray-cast. */ BVHTree_NearestPointCallback nearest_callback; @@ -41,8 +49,7 @@ struct BVHTreeFromMesh { const MFace *face = nullptr; - /* Private data */ - bool cached = false; + std::unique_ptr owned_tree; }; enum BVHCacheType { @@ -110,17 +117,6 @@ BVHTree *bvhtree_from_mesh_corner_tris_ex(BVHTreeFromMesh *data, int tree_type, int axis); -/** - * Builds or queries a BVH-cache for the cache BVH-tree of the request type. - * - * \note This function only fills a cache, and therefore the mesh argument can - * be considered logically const. Concurrent access is protected by a mutex. - */ -BVHTree *BKE_bvhtree_from_mesh_get(BVHTreeFromMesh *data, - const Mesh *mesh, - BVHCacheType bvh_cache_type, - int tree_type); - /** * Build a bvh tree from the triangles in the mesh that correspond to the faces in the given mask. */ @@ -142,11 +138,6 @@ void BKE_bvhtree_from_mesh_verts_init(const Mesh &mesh, const blender::IndexMask &verts_mask, BVHTreeFromMesh &r_data); -/** - * Frees data allocated by a call to `bvhtree_from_mesh_*`. - */ -void free_bvhtree_from_mesh(BVHTreeFromMesh *data); - /** * Math functions used by callbacks */ @@ -172,16 +163,3 @@ void BKE_bvhtree_from_pointcloud_get(const PointCloud &pointcloud, BVHTreeFromPointCloud &r_data); void free_bvhtree_from_pointcloud(BVHTreeFromPointCloud *data); - -/** - * BVHCache - */ - -/* Using local coordinates */ - -bool bvhcache_has_tree(const BVHCache *bvh_cache, const BVHTree *tree); -BVHCache *bvhcache_init(); -/** - * Frees a BVH-cache. - */ -void bvhcache_free(BVHCache *bvh_cache); diff --git a/source/blender/blenkernel/BKE_mesh_types.hh b/source/blender/blenkernel/BKE_mesh_types.hh index 705b005186d..79c152d943c 100644 --- a/source/blender/blenkernel/BKE_mesh_types.hh +++ b/source/blender/blenkernel/BKE_mesh_types.hh @@ -22,14 +22,14 @@ #include "DNA_customdata_types.h" struct BMEditMesh; -struct BVHCache; +struct BVHTree; struct Mesh; class ShrinkwrapBoundaryData; struct SubdivCCG; struct SubsurfRuntimeData; namespace blender::bke { struct EditMeshData; -} +} // namespace blender::bke namespace blender::bke::bake { struct BakeMaterialsList; } @@ -107,6 +107,12 @@ struct TrianglesCache { void tag_dirty(); }; +struct BVHCacheItem { + BVHTree *tree = nullptr; + BVHCacheItem(); + ~BVHCacheItem(); +}; + struct MeshRuntime { /** * "Evaluated" mesh owned by this mesh. Used for objects which don't have effective modifiers, so @@ -158,8 +164,15 @@ struct MeshRuntime { /** Cache for triangle to original face index map, accessed with #Mesh::corner_tri_faces(). */ SharedCache> corner_tri_faces_cache; - /** Cache for BVH trees generated for the mesh. Defined in 'BKE_bvhutil.c' */ - BVHCache *bvh_cache = nullptr; + SharedCache bvh_cache_verts; + SharedCache bvh_cache_edges; + SharedCache bvh_cache_faces; + SharedCache bvh_cache_corner_tris; + SharedCache bvh_cache_corner_tris_no_hidden; + SharedCache bvh_cache_loose_verts; + SharedCache bvh_cache_loose_verts_no_hidden; + SharedCache bvh_cache_loose_edges; + SharedCache bvh_cache_loose_edges_no_hidden; /** Needed in case we need to lazily initialize the mesh. */ CustomData_MeshMasks cd_mask_extra = {}; diff --git a/source/blender/blenkernel/BKE_shrinkwrap.hh b/source/blender/blenkernel/BKE_shrinkwrap.hh index 1a0a12c8bd3..670d2970a94 100644 --- a/source/blender/blenkernel/BKE_shrinkwrap.hh +++ b/source/blender/blenkernel/BKE_shrinkwrap.hh @@ -79,10 +79,11 @@ const ShrinkwrapBoundaryData &boundary_cache_ensure(const Mesh &mesh); struct ShrinkwrapTreeData { Mesh *mesh; - BVHTree *bvh; + const BVHTree *bvh; BVHTreeFromMesh treeData; blender::OffsetIndices faces; + blender::Span edges; blender::Span corner_edges; blender::Span face_normals; diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc index f6304e60eeb..399c246e5d4 100644 --- a/source/blender/blenkernel/intern/attribute_access.cc +++ b/source/blender/blenkernel/intern/attribute_access.cc @@ -481,8 +481,12 @@ GAttributeWriter CustomDataAttributeProvider::try_get_for_write(void *owner, if (type == nullptr) { continue; } + std::function tag_modified_fn; + if (custom_data_access_.get_tag_modified_function != nullptr) { + tag_modified_fn = custom_data_access_.get_tag_modified_function(owner, attribute_id); + } GMutableSpan data{*type, layer.data, element_num}; - return {GVMutableArray::ForSpan(data), domain_}; + return {GVMutableArray::ForSpan(data), domain_, tag_modified_fn}; } return {}; } @@ -498,6 +502,13 @@ bool CustomDataAttributeProvider::try_delete(void *owner, const StringRef attrib const CustomDataLayer &layer = custom_data->layers[i]; if (this->type_is_supported(eCustomDataType(layer.type)) && layer.name == attribute_id) { CustomData_free_layer(custom_data, eCustomDataType(layer.type), element_num, i); + if (custom_data_access_.get_tag_modified_function != nullptr) { + if (const std::function fn = custom_data_access_.get_tag_modified_function( + owner, attribute_id)) + { + fn(); + } + } return true; } } @@ -528,6 +539,18 @@ bool CustomDataAttributeProvider::try_create(void *owner, const int element_num = custom_data_access_.get_element_num(owner); add_custom_data_layer_from_attribute_init( attribute_id, *custom_data, data_type, element_num, initializer, {}); + if (initializer.type != AttributeInit::Type::Construct) { + /* Avoid calling update function when values are not default-initialized. Without default + * initialization or otherwise meaningful initial values, they should be set elsewhere + * anyway, which will cause a separate update tag. */ + if (custom_data_access_.get_tag_modified_function != nullptr) { + if (const std::function fn = custom_data_access_.get_tag_modified_function( + owner, attribute_id)) + { + fn(); + } + } + } return true; } diff --git a/source/blender/blenkernel/intern/attribute_access_intern.hh b/source/blender/blenkernel/intern/attribute_access_intern.hh index fc7953cf418..3591fc1d793 100644 --- a/source/blender/blenkernel/intern/attribute_access_intern.hh +++ b/source/blender/blenkernel/intern/attribute_access_intern.hh @@ -2,6 +2,8 @@ * * SPDX-License-Identifier: GPL-2.0-or-later */ +#include + #include "BLI_generic_pointer.hh" #include "BLI_map.hh" #include "BLI_span.hh" @@ -21,10 +23,12 @@ struct CustomDataAccessInfo { using CustomDataGetter = CustomData *(*)(void *owner); using ConstCustomDataGetter = const CustomData *(*)(const void *owner); using GetElementNum = int (*)(const void *owner); + using GetTagModifiedFunction = std::function (*)(void *owner, StringRef name); CustomDataGetter get_custom_data; ConstCustomDataGetter get_const_custom_data; GetElementNum get_element_num; + GetTagModifiedFunction get_tag_modified_function; }; /** diff --git a/source/blender/blenkernel/intern/bvhutils.cc b/source/blender/blenkernel/intern/bvhutils.cc index 08af4a4509d..862a5c6a437 100644 --- a/source/blender/blenkernel/intern/bvhutils.cc +++ b/source/blender/blenkernel/intern/bvhutils.cc @@ -21,6 +21,7 @@ using blender::BitSpan; using blender::BitVector; using blender::float3; using blender::IndexRange; +using blender::int2; using blender::int3; using blender::Span; using blender::VArray; @@ -29,136 +30,22 @@ using blender::VArray; /** \name BVHCache * \{ */ -struct BVHCacheItem { - bool is_filled; - BVHTree *tree; -}; +namespace blender::bke { -struct BVHCache { - BVHCacheItem items[BVHTREE_MAX_ITEM]; - ThreadMutex mutex; -}; - -/** - * Queries a bvhcache for the cache bvhtree of the request type - * - * When the `r_locked` is filled and the tree could not be found the caches mutex will be - * locked. This mutex can be unlocked by calling `bvhcache_unlock`. - * - * When `r_locked` is used the `mesh_eval_mutex` must contain the `MeshRuntime.eval_mutex`. - */ -static bool bvhcache_find(BVHCache **bvh_cache_p, - BVHCacheType type, - BVHTree **r_tree, - bool *r_locked, - std::mutex *mesh_eval_mutex) +BVHCacheItem::BVHCacheItem() = default; +BVHCacheItem::~BVHCacheItem() { - bool do_lock = r_locked; - if (r_locked) { - *r_locked = false; - } - if (*bvh_cache_p == nullptr) { - if (!do_lock) { - /* Cache does not exist and no lock is requested. */ - return false; - } - /* Lazy initialization of the bvh_cache using the `mesh_eval_mutex`. */ - std::lock_guard lock{*mesh_eval_mutex}; - if (*bvh_cache_p == nullptr) { - *bvh_cache_p = bvhcache_init(); - } - } - BVHCache *bvh_cache = *bvh_cache_p; - - if (bvh_cache->items[type].is_filled) { - *r_tree = bvh_cache->items[type].tree; - return true; - } - if (do_lock) { - BLI_mutex_lock(&bvh_cache->mutex); - bool in_cache = bvhcache_find(bvh_cache_p, type, r_tree, nullptr, nullptr); - if (in_cache) { - BLI_mutex_unlock(&bvh_cache->mutex); - return in_cache; - } - *r_locked = true; - } - return false; + BLI_bvhtree_free(this->tree); } -static void bvhcache_unlock(BVHCache *bvh_cache, bool lock_started) -{ - if (lock_started) { - BLI_mutex_unlock(&bvh_cache->mutex); - } -} +} // namespace blender::bke -bool bvhcache_has_tree(const BVHCache *bvh_cache, const BVHTree *tree) -{ - if (bvh_cache == nullptr) { - return false; - } +using blender::bke::BVHCacheItem; - for (int i = 0; i < BVHTREE_MAX_ITEM; i++) { - if (bvh_cache->items[i].tree == tree) { - return true; - } - } - return false; -} - -BVHCache *bvhcache_init() -{ - BVHCache *cache = MEM_cnew(__func__); - BLI_mutex_init(&cache->mutex); - return cache; -} -/** - * Inserts a BVHTree of the given type under the cache - * After that the caller no longer needs to worry when to free the BVHTree - * as that will be done when the cache is freed. - * - * A call to this assumes that there was no previous cached tree of the given type - * \warning The #BVHTree can be nullptr. - */ -static void bvhcache_insert(BVHCache *bvh_cache, BVHTree *tree, BVHCacheType type) -{ - BVHCacheItem *item = &bvh_cache->items[type]; - BLI_assert(!item->is_filled); - item->tree = tree; - item->is_filled = true; -} - -void bvhcache_free(BVHCache *bvh_cache) -{ - for (int index = 0; index < BVHTREE_MAX_ITEM; index++) { - BVHCacheItem *item = &bvh_cache->items[index]; - BLI_bvhtree_free(item->tree); - item->tree = nullptr; - } - BLI_mutex_end(&bvh_cache->mutex); - MEM_freeN(bvh_cache); -} - -/** - * BVH-tree balancing inside a mutex lock must be run in isolation. Balancing - * is multithreaded, and we do not want the current thread to start another task - * that may involve acquiring the same mutex lock that it is waiting for. - */ -static void bvhtree_balance_isolated(void *userdata) -{ - BLI_bvhtree_balance((BVHTree *)userdata); -} - -static void bvhtree_balance(BVHTree *tree, const bool isolate) +static void bvhtree_balance(BVHTree *tree) { if (tree) { - if (isolate) { - BLI_task_isolate(bvhtree_balance_isolated, tree); - } - else { - BLI_bvhtree_balance(tree); - } + BLI_bvhtree_balance(tree); } } @@ -487,24 +374,23 @@ static void mesh_edges_spherecast(void *userdata, /** \name Common Utils * \{ */ -static void bvhtree_from_mesh_setup_data(BVHTree *tree, - const BVHCacheType bvh_cache_type, - const Span positions, - const Span edges, - const Span corner_verts, - const Span corner_tris, - const MFace *face, - BVHTreeFromMesh *r_data) +static BVHTreeFromMesh bvhtree_from_mesh_setup_data(BVHTree *tree, + const BVHCacheType bvh_cache_type, + const Span positions, + const Span edges, + const Span corner_verts, + const Span corner_tris, + const MFace *face) { - *r_data = {}; + BVHTreeFromMesh data{}; - r_data->tree = tree; + data.tree = tree; - r_data->vert_positions = positions; - r_data->edges = edges; - r_data->face = face; - r_data->corner_verts = corner_verts; - r_data->corner_tris = corner_tris; + data.vert_positions = positions; + data.edges = edges; + data.face = face; + data.corner_verts = corner_verts; + data.corner_tris = corner_tris; switch (bvh_cache_type) { case BVHTREE_FROM_VERTS: @@ -512,28 +398,29 @@ static void bvhtree_from_mesh_setup_data(BVHTree *tree, case BVHTREE_FROM_LOOSEVERTS_NO_HIDDEN: /* a nullptr nearest callback works fine * remember the min distance to point is the same as the min distance to BV of point */ - r_data->nearest_callback = nullptr; - r_data->raycast_callback = mesh_verts_spherecast; + data.nearest_callback = nullptr; + data.raycast_callback = mesh_verts_spherecast; break; case BVHTREE_FROM_EDGES: case BVHTREE_FROM_LOOSEEDGES: case BVHTREE_FROM_LOOSEEDGES_NO_HIDDEN: - r_data->nearest_callback = mesh_edges_nearest_point; - r_data->raycast_callback = mesh_edges_spherecast; + data.nearest_callback = mesh_edges_nearest_point; + data.raycast_callback = mesh_edges_spherecast; break; case BVHTREE_FROM_FACES: - r_data->nearest_callback = mesh_faces_nearest_point; - r_data->raycast_callback = mesh_faces_spherecast; + data.nearest_callback = mesh_faces_nearest_point; + data.raycast_callback = mesh_faces_spherecast; break; case BVHTREE_FROM_CORNER_TRIS: case BVHTREE_FROM_CORNER_TRIS_NO_HIDDEN: - r_data->nearest_callback = mesh_corner_tris_nearest_point; - r_data->raycast_callback = mesh_corner_tris_spherecast; + data.nearest_callback = mesh_corner_tris_nearest_point; + data.raycast_callback = mesh_corner_tris_spherecast; break; case BVHTREE_MAX_ITEM: BLI_assert(false); break; } + return data; } static BVHTree *bvhtree_new_common( @@ -593,11 +480,11 @@ BVHTree *bvhtree_from_mesh_verts_ex(BVHTreeFromMesh *data, BVHTree *tree = bvhtree_from_mesh_verts_create_tree( epsilon, tree_type, axis, vert_positions, verts_mask, verts_num_active); - bvhtree_balance(tree, false); + bvhtree_balance(tree); if (data) { /* Setup BVHTreeFromMesh */ - bvhtree_from_mesh_setup_data(tree, BVHTREE_FROM_VERTS, vert_positions, {}, {}, {}, {}, data); + *data = bvhtree_from_mesh_setup_data(tree, BVHTREE_FROM_VERTS, vert_positions, {}, {}, {}, {}); } return tree; @@ -648,12 +535,12 @@ BVHTree *bvhtree_from_mesh_edges_ex(BVHTreeFromMesh *data, BVHTree *tree = bvhtree_from_mesh_edges_create_tree( vert_positions, edges, edges_mask, edges_num_active, epsilon, tree_type, axis); - bvhtree_balance(tree, false); + bvhtree_balance(tree); if (data) { /* Setup BVHTreeFromMesh */ - bvhtree_from_mesh_setup_data( - tree, BVHTREE_FROM_EDGES, vert_positions, edges, {}, {}, {}, data); + *data = bvhtree_from_mesh_setup_data( + tree, BVHTREE_FROM_EDGES, vert_positions, edges, {}, {}, {}); } return tree; @@ -764,18 +651,12 @@ BVHTree *bvhtree_from_mesh_corner_tris_ex(BVHTreeFromMesh *data, corner_tris_mask, corner_tris_num_active); - bvhtree_balance(tree, false); + bvhtree_balance(tree); if (data) { /* Setup BVHTreeFromMesh */ - bvhtree_from_mesh_setup_data(tree, - BVHTREE_FROM_CORNER_TRIS, - vert_positions, - {}, - corner_verts, - corner_tris, - nullptr, - data); + *data = bvhtree_from_mesh_setup_data( + tree, BVHTREE_FROM_CORNER_TRIS, vert_positions, {}, corner_verts, corner_tris, nullptr); } return tree; @@ -896,138 +777,173 @@ static BitVector<> corner_tris_no_hidden_map_get(const blender::OffsetIndicesruntime->bvh_cache; - - Span corner_tris; - if (ELEM(bvh_cache_type, BVHTREE_FROM_CORNER_TRIS, BVHTREE_FROM_CORNER_TRIS_NO_HIDDEN)) { - corner_tris = mesh->corner_tris(); - } - - const Span positions = mesh->vert_positions(); - const Span edges = mesh->edges(); - const Span corner_verts = mesh->corner_verts(); - - /* Setup BVHTreeFromMesh */ - bvhtree_from_mesh_setup_data(nullptr, - bvh_cache_type, - positions, - edges, - corner_verts, - corner_tris, - (const MFace *)CustomData_get_layer(&mesh->fdata_legacy, CD_MFACE), - data); - - bool lock_started = false; - data->cached = bvhcache_find( - bvh_cache_p, bvh_cache_type, &data->tree, &lock_started, &mesh->runtime->eval_mutex); - - if (data->cached) { - BLI_assert(lock_started == false); - - /* NOTE: #data->tree can be nullptr. */ - return data->tree; - } - - /* Create BVHTree. */ - - switch (bvh_cache_type) { - case BVHTREE_FROM_LOOSEVERTS: { - const LooseVertCache &loose_verts = mesh->loose_verts(); - data->tree = bvhtree_from_mesh_verts_create_tree( - 0.0f, tree_type, 6, positions, loose_verts.is_loose_bits, loose_verts.count); - break; + const Span positions = this->vert_positions(); + this->runtime->bvh_cache_loose_verts.ensure([&](BVHCacheItem &data) { + const LooseVertCache &loose_verts = this->loose_verts(); + data.tree = bvhtree_from_mesh_verts_create_tree( + 0.0f, 2, 6, positions, loose_verts.is_loose_bits, loose_verts.count); + if (data.tree) { + BLI_bvhtree_balance(data.tree); } - case BVHTREE_FROM_LOOSEVERTS_NO_HIDDEN: { - int mask_bits_act_len = -1; - const BitVector<> mask = loose_verts_no_hidden_mask_get(*mesh, &mask_bits_act_len); - data->tree = bvhtree_from_mesh_verts_create_tree( - 0.0f, tree_type, 6, positions, mask, mask_bits_act_len); - break; - } - case BVHTREE_FROM_VERTS: { - data->tree = bvhtree_from_mesh_verts_create_tree(0.0f, tree_type, 6, positions, {}, -1); - break; - } - case BVHTREE_FROM_LOOSEEDGES: { - const LooseEdgeCache &loose_edges = mesh->loose_edges(); - data->tree = bvhtree_from_mesh_edges_create_tree( - positions, edges, loose_edges.is_loose_bits, loose_edges.count, 0.0f, tree_type, 6); - break; - } - case BVHTREE_FROM_LOOSEEDGES_NO_HIDDEN: { - int mask_bits_act_len = -1; - const BitVector<> mask = loose_edges_no_hidden_mask_get(*mesh, &mask_bits_act_len); - data->tree = bvhtree_from_mesh_edges_create_tree( - positions, edges, mask, mask_bits_act_len, 0.0f, tree_type, 6); - break; - } - case BVHTREE_FROM_EDGES: { - data->tree = bvhtree_from_mesh_edges_create_tree( - positions, edges, {}, -1, 0.0f, tree_type, 6); - break; - } - case BVHTREE_FROM_FACES: { - BLI_assert(!(mesh->totface_legacy == 0 && mesh->faces_num != 0)); - data->tree = bvhtree_from_mesh_faces_create_tree( - 0.0f, - tree_type, - 6, - positions, - (const MFace *)CustomData_get_layer(&mesh->fdata_legacy, CD_MFACE), - mesh->totface_legacy, - {}, - -1); - break; - } - case BVHTREE_FROM_CORNER_TRIS_NO_HIDDEN: { - AttributeAccessor attributes = mesh->attributes(); - int mask_bits_act_len = -1; - const BitVector<> mask = corner_tris_no_hidden_map_get( - mesh->faces(), - *attributes.lookup_or_default(".hide_poly", AttrDomain::Face, false), - corner_tris.size(), - &mask_bits_act_len); - data->tree = bvhtree_from_mesh_corner_tris_create_tree( - 0.0f, tree_type, 6, positions, corner_verts, corner_tris, mask, mask_bits_act_len); - break; - } - case BVHTREE_FROM_CORNER_TRIS: { - data->tree = bvhtree_from_mesh_corner_tris_create_tree( - 0.0f, tree_type, 6, positions, corner_verts, corner_tris, {}, -1); - break; - } - case BVHTREE_MAX_ITEM: - BLI_assert_unreachable(); - break; - } + }); + const BVHCacheItem &tree = this->runtime->bvh_cache_loose_verts.data(); + return bvhtree_from_mesh_setup_data( + tree.tree, BVHTREE_FROM_LOOSEVERTS, positions, {}, {}, {}, nullptr); +} - bvhtree_balance(data->tree, lock_started); - - /* Save on cache for later use */ - // printf("BVHTree built and saved on cache\n"); - BLI_assert(data->cached == false); - data->cached = true; - bvhcache_insert(*bvh_cache_p, data->tree, bvh_cache_type); - bvhcache_unlock(*bvh_cache_p, lock_started); - -#ifndef NDEBUG - if (data->tree != nullptr) { - if (BLI_bvhtree_get_tree_type(data->tree) != tree_type) { - printf("tree_type %d obtained instead of %d\n", - BLI_bvhtree_get_tree_type(data->tree), - tree_type); +BVHTreeFromMesh Mesh::bvh_loose_no_hidden_verts() const +{ + const Span positions = this->vert_positions(); + this->runtime->bvh_cache_loose_verts_no_hidden.ensure([&](BVHCacheItem &data) { + int mask_bits_act_len = -1; + const BitVector<> mask = loose_verts_no_hidden_mask_get(*this, &mask_bits_act_len); + data.tree = bvhtree_from_mesh_verts_create_tree(0.0f, 2, 6, positions, {}, -1); + if (data.tree) { + BLI_bvhtree_balance(data.tree); } - } -#endif + }); + const BVHCacheItem &tree = this->runtime->bvh_cache_loose_verts_no_hidden.data(); + return bvhtree_from_mesh_setup_data( + tree.tree, BVHTREE_FROM_LOOSEVERTS_NO_HIDDEN, positions, {}, {}, {}, nullptr); +} - return data->tree; +BVHTreeFromMesh Mesh::bvh_verts() const +{ + const Span positions = this->vert_positions(); + this->runtime->bvh_cache_verts.ensure([&](BVHCacheItem &data) { + data.tree = bvhtree_from_mesh_verts_create_tree(0.0f, 2, 6, positions, {}, -1); + if (data.tree) { + BLI_bvhtree_balance(data.tree); + } + }); + const BVHCacheItem &tree = this->runtime->bvh_cache_verts.data(); + return bvhtree_from_mesh_setup_data( + tree.tree, BVHTREE_FROM_VERTS, positions, {}, {}, {}, nullptr); +} + +BVHTreeFromMesh Mesh::bvh_loose_edges() const +{ + using namespace blender::bke; + const Span positions = this->vert_positions(); + const Span edges = this->edges(); + this->runtime->bvh_cache_loose_edges.ensure([&](BVHCacheItem &data) { + const LooseEdgeCache &loose_edges = this->loose_edges(); + data.tree = bvhtree_from_mesh_edges_create_tree( + positions, edges, loose_edges.is_loose_bits, loose_edges.count, 0.0f, 2, 6); + if (data.tree) { + BLI_bvhtree_balance(data.tree); + } + }); + const BVHCacheItem &tree = this->runtime->bvh_cache_loose_edges.data(); + BVHTreeFromMesh data; + return bvhtree_from_mesh_setup_data( + tree.tree, BVHTREE_FROM_LOOSEEDGES, positions, edges, {}, {}, nullptr); +} + +BVHTreeFromMesh Mesh::bvh_loose_no_hidden_edges() const +{ + const Span positions = this->vert_positions(); + const Span edges = this->edges(); + this->runtime->bvh_cache_loose_edges_no_hidden.ensure([&](BVHCacheItem &data) { + int mask_bits_act_len = -1; + const BitVector<> mask = loose_edges_no_hidden_mask_get(*this, &mask_bits_act_len); + data.tree = bvhtree_from_mesh_edges_create_tree( + positions, edges, mask, mask_bits_act_len, 0.0f, 2, 6); + if (data.tree) { + BLI_bvhtree_balance(data.tree); + } + }); + const BVHCacheItem &tree = this->runtime->bvh_cache_loose_edges_no_hidden.data(); + return bvhtree_from_mesh_setup_data( + tree.tree, BVHTREE_FROM_LOOSEEDGES_NO_HIDDEN, positions, {}, {}, {}, nullptr); +} + +BVHTreeFromMesh Mesh::bvh_edges() const +{ + const Span positions = this->vert_positions(); + const Span edges = this->edges(); + this->runtime->bvh_cache_edges.ensure([&](BVHCacheItem &data) { + data.tree = bvhtree_from_mesh_edges_create_tree(positions, edges, {}, -1, 0.0f, 2, 6); + if (data.tree) { + BLI_bvhtree_balance(data.tree); + } + }); + const BVHCacheItem &tree = this->runtime->bvh_cache_edges.data(); + return bvhtree_from_mesh_setup_data( + tree.tree, BVHTREE_FROM_EDGES, positions, edges, {}, {}, nullptr); +} + +BVHTreeFromMesh Mesh::bvh_legacy_faces() const +{ + BLI_assert(!(this->totface_legacy == 0 && this->faces_num != 0)); + const Span positions = this->vert_positions(); + this->runtime->bvh_cache_faces.ensure([&](BVHCacheItem &data) { + data.tree = bvhtree_from_mesh_faces_create_tree( + 0.0f, + 2, + 6, + positions, + (const MFace *)CustomData_get_layer(&this->fdata_legacy, CD_MFACE), + this->totface_legacy, + {}, + -1); + if (data.tree) { + BLI_bvhtree_balance(data.tree); + } + }); + const BVHCacheItem &tree = this->runtime->bvh_cache_faces.data(); + return bvhtree_from_mesh_setup_data( + tree.tree, BVHTREE_FROM_FACES, positions, {}, {}, {}, nullptr); +} + +BVHTreeFromMesh Mesh::bvh_corner_tris_no_hidden() const +{ + using namespace blender::bke; + const Span positions = this->vert_positions(); + const Span corner_verts = this->corner_verts(); + const Span corner_tris = this->corner_tris(); + this->runtime->bvh_cache_verts.ensure([&](BVHCacheItem &data) { + AttributeAccessor attributes = this->attributes(); + int mask_bits_act_len = -1; + const BitVector<> mask = corner_tris_no_hidden_map_get( + this->faces(), + *attributes.lookup_or_default(".hide_poly", AttrDomain::Face, false), + corner_tris.size(), + &mask_bits_act_len); + data.tree = bvhtree_from_mesh_corner_tris_create_tree( + 0.0f, 2, 6, positions, corner_verts, corner_tris, mask, mask_bits_act_len); + if (data.tree) { + BLI_bvhtree_balance(data.tree); + } + }); + const BVHCacheItem &tree = this->runtime->bvh_cache_verts.data(); + return bvhtree_from_mesh_setup_data(tree.tree, + BVHTREE_FROM_CORNER_TRIS_NO_HIDDEN, + positions, + {}, + corner_verts, + corner_tris, + nullptr); +} + +BVHTreeFromMesh Mesh::bvh_corner_tris() const +{ + const Span positions = this->vert_positions(); + const Span corner_verts = this->corner_verts(); + const Span corner_tris = this->corner_tris(); + this->runtime->bvh_cache_corner_tris.ensure([&](BVHCacheItem &data) { + data.tree = bvhtree_from_mesh_corner_tris_create_tree( + 0.0f, 2, 6, positions, corner_verts, corner_tris, {}, -1); + if (data.tree) { + BLI_bvhtree_balance(data.tree); + } + }); + const BVHCacheItem &tree = this->runtime->bvh_cache_corner_tris.data(); + return bvhtree_from_mesh_setup_data( + tree.tree, BVHTREE_FROM_CORNER_TRIS, positions, {}, corner_verts, corner_tris, nullptr); } void BKE_bvhtree_from_mesh_tris_init(const Mesh &mesh, @@ -1039,7 +955,7 @@ void BKE_bvhtree_from_mesh_tris_init(const Mesh &mesh, if (faces_mask.size() == mesh.faces_num) { /* Can use cache if all faces are in the bvh tree. */ - BKE_bvhtree_from_mesh_get(&r_data, &mesh, BVHTREE_FROM_CORNER_TRIS, 2); + r_data = mesh.bvh_corner_tris(); return; } @@ -1048,14 +964,8 @@ void BKE_bvhtree_from_mesh_tris_init(const Mesh &mesh, const Span corner_verts = mesh.corner_verts(); const OffsetIndices faces = mesh.faces(); const Span corner_tris = mesh.corner_tris(); - bvhtree_from_mesh_setup_data(nullptr, - BVHTREE_FROM_CORNER_TRIS, - positions, - edges, - corner_verts, - corner_tris, - nullptr, - &r_data); + r_data = bvhtree_from_mesh_setup_data( + nullptr, BVHTREE_FROM_CORNER_TRIS, positions, edges, corner_verts, corner_tris, nullptr); int tris_num = 0; faces_mask.foreach_index( @@ -1063,6 +973,7 @@ void BKE_bvhtree_from_mesh_tris_init(const Mesh &mesh, int active_num = -1; BVHTree *tree = bvhtree_new_common(0.0f, 2, 6, tris_num, active_num); + r_data.owned_tree = std::unique_ptr(tree); r_data.tree = tree; if (tree == nullptr) { return; @@ -1092,17 +1003,18 @@ void BKE_bvhtree_from_mesh_edges_init(const Mesh &mesh, if (edges_mask.size() == mesh.edges_num) { /* Can use cache if all edges are in the bvh tree. */ - BKE_bvhtree_from_mesh_get(&r_data, &mesh, BVHTREE_FROM_EDGES, 2); + r_data = mesh.bvh_edges(); return; } const Span positions = mesh.vert_positions(); const Span edges = mesh.edges(); - bvhtree_from_mesh_setup_data( - nullptr, BVHTREE_FROM_EDGES, positions, edges, {}, {}, nullptr, &r_data); + r_data = bvhtree_from_mesh_setup_data( + nullptr, BVHTREE_FROM_EDGES, positions, edges, {}, {}, nullptr); int active_num = -1; BVHTree *tree = bvhtree_new_common(0.0f, 2, 6, edges_mask.size(), active_num); + r_data.owned_tree = std::unique_ptr(tree); r_data.tree = tree; if (tree == nullptr) { return; @@ -1128,16 +1040,17 @@ void BKE_bvhtree_from_mesh_verts_init(const Mesh &mesh, if (verts_mask.size() == mesh.verts_num) { /* Can use cache if all vertices are in the bvh tree. */ - BKE_bvhtree_from_mesh_get(&r_data, &mesh, BVHTREE_FROM_VERTS, 2); + r_data = mesh.bvh_verts(); return; } const Span positions = mesh.vert_positions(); - bvhtree_from_mesh_setup_data( - nullptr, BVHTREE_FROM_VERTS, positions, {}, {}, {}, nullptr, &r_data); + r_data = bvhtree_from_mesh_setup_data( + nullptr, BVHTREE_FROM_VERTS, positions, {}, {}, {}, nullptr); int active_num = -1; BVHTree *tree = bvhtree_new_common(0.0f, 2, 6, verts_mask.size(), active_num); + r_data.owned_tree = std::unique_ptr(tree); r_data.tree = tree; if (tree == nullptr) { return; @@ -1153,21 +1066,6 @@ void BKE_bvhtree_from_mesh_verts_init(const Mesh &mesh, /** \} */ -/* -------------------------------------------------------------------- */ -/** \name Free Functions - * \{ */ - -void free_bvhtree_from_mesh(BVHTreeFromMesh *data) -{ - if (data->tree && !data->cached) { - BLI_bvhtree_free(data->tree); - } - - *data = {}; -} - -/** \} */ - /* -------------------------------------------------------------------- */ /** \name Point Cloud BVH Building * \{ */ diff --git a/source/blender/blenkernel/intern/cloth.cc b/source/blender/blenkernel/intern/cloth.cc index e52e90cfc7f..8f88a15bdf7 100644 --- a/source/blender/blenkernel/intern/cloth.cc +++ b/source/blender/blenkernel/intern/cloth.cc @@ -1500,7 +1500,6 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) bool use_internal_springs = (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_INTERNAL_SPRINGS); if (use_internal_springs && numface > 0) { - BVHTreeFromMesh treedata = {nullptr}; int tar_v_idx; Mesh *tmp_mesh = nullptr; RNG *rng; @@ -1513,7 +1512,7 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) } Set existing_vert_pairs; - BKE_bvhtree_from_mesh_get(&treedata, tmp_mesh ? tmp_mesh : mesh, BVHTREE_FROM_CORNER_TRIS, 2); + BVHTreeFromMesh treedata = tmp_mesh ? tmp_mesh->bvh_corner_tris() : mesh->bvh_corner_tris(); rng = BLI_rng_new_srandom(0); const blender::Span vert_normals = tmp_mesh ? tmp_mesh->vert_normals() : @@ -1561,7 +1560,6 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) } else { cloth_free_errorsprings(cloth, edgelist, spring_ref); - free_bvhtree_from_mesh(&treedata); if (tmp_mesh) { BKE_id_free(nullptr, &tmp_mesh->id); } @@ -1571,7 +1569,6 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh) } } existing_vert_pairs.clear_and_shrink(); - free_bvhtree_from_mesh(&treedata); if (tmp_mesh) { BKE_id_free(nullptr, &tmp_mesh->id); } diff --git a/source/blender/blenkernel/intern/constraint.cc b/source/blender/blenkernel/intern/constraint.cc index 9d9cf25664a..5cd9436295e 100644 --- a/source/blender/blenkernel/intern/constraint.cc +++ b/source/blender/blenkernel/intern/constraint.cc @@ -5195,8 +5195,7 @@ static void followtrack_project_to_depth_object_if_needed(FollowTrackContext *co sub_v3_v3v3(ray_direction, ray_end, ray_start); normalize_v3(ray_direction); - BVHTreeFromMesh tree_data = NULL_BVHTreeFromMesh; - BKE_bvhtree_from_mesh_get(&tree_data, depth_mesh, BVHTREE_FROM_CORNER_TRIS, 4); + BVHTreeFromMesh tree_data = depth_mesh->bvh_corner_tris(); BVHTreeRayHit hit; hit.dist = BVH_RAYCAST_DIST_MAX; @@ -5213,8 +5212,6 @@ static void followtrack_project_to_depth_object_if_needed(FollowTrackContext *co if (result != -1) { mul_v3_m4v3(cob->matrix[3], depth_object->object_to_world().ptr(), hit.co); } - - free_bvhtree_from_mesh(&tree_data); } static void followtrack_evaluate_using_2d_position(FollowTrackContext *context, bConstraintOb *cob) diff --git a/source/blender/blenkernel/intern/dynamicpaint.cc b/source/blender/blenkernel/intern/dynamicpaint.cc index 222ba1cc84c..92a504085db 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.cc +++ b/source/blender/blenkernel/intern/dynamicpaint.cc @@ -4311,7 +4311,6 @@ static bool dynamicPaint_paintMesh(Depsgraph *depsgraph, } { - BVHTreeFromMesh treeData = {nullptr}; float avg_brushNor[3] = {0.0f}; const float brush_radius = brush->paint_distance * surface->radius_scale; int numOfVerts; @@ -4355,7 +4354,8 @@ static bool dynamicPaint_paintMesh(Depsgraph *depsgraph, /* check bounding box collision */ if (grid && meshBrush_boundsIntersect(&grid->grid_bounds, &mesh_bb, brush, brush_radius)) { /* Build a bvh tree from transformed vertices */ - if (BKE_bvhtree_from_mesh_get(&treeData, mesh, BVHTREE_FROM_CORNER_TRIS, 4)) { + BVHTreeFromMesh treeData = mesh->bvh_corner_tris(); + if (treeData.tree != nullptr) { int c_index; int total_cells = grid->dim[0] * grid->dim[1] * grid->dim[2]; @@ -4396,8 +4396,6 @@ static bool dynamicPaint_paintMesh(Depsgraph *depsgraph, } } } - /* free bvh tree */ - free_bvhtree_from_mesh(&treeData); BKE_id_free(nullptr, mesh); } diff --git a/source/blender/blenkernel/intern/fluid.cc b/source/blender/blenkernel/intern/fluid.cc index 333e8621628..462d95f1e22 100644 --- a/source/blender/blenkernel/intern/fluid.cc +++ b/source/blender/blenkernel/intern/fluid.cc @@ -1009,7 +1009,6 @@ static void obstacles_from_mesh(Object *coll_ob, float dt) { if (fes->mesh) { - BVHTreeFromMesh tree_data = {nullptr}; int numverts, i; float *vert_vel = nullptr; @@ -1079,8 +1078,8 @@ static void obstacles_from_mesh(Object *coll_ob, /* Skip effector sampling loop if object has disabled effector. */ bool use_effector = fes->flags & FLUID_EFFECTOR_USE_EFFEC; - if (use_effector && BKE_bvhtree_from_mesh_get(&tree_data, mesh, BVHTREE_FROM_CORNER_TRIS, 4)) { - + BVHTreeFromMesh tree_data = mesh->bvh_corner_tris(); + if (use_effector && tree_data.tree != nullptr) { ObstaclesFromDMData data{}; data.fes = fes; data.vert_positions = positions; @@ -1099,8 +1098,6 @@ static void obstacles_from_mesh(Object *coll_ob, settings.min_iter_per_thread = 2; BLI_task_parallel_range(min[2], max[2], &data, obstacles_from_mesh_task_cb, &settings); } - /* Free bvh tree. */ - free_bvhtree_from_mesh(&tree_data); if (vert_vel) { MEM_freeN(vert_vel); @@ -2068,7 +2065,6 @@ static void emit_from_mesh( Object *flow_ob, FluidDomainSettings *fds, FluidFlowSettings *ffs, FluidObjectBB *bb, float dt) { if (ffs->mesh) { - BVHTreeFromMesh tree_data = {nullptr}; int i; float *vert_vel = nullptr; @@ -2147,7 +2143,8 @@ static void emit_from_mesh( /* Skip flow sampling loop if object has disabled flow. */ bool use_flow = ffs->flags & FLUID_FLOW_USE_INFLOW; - if (use_flow && BKE_bvhtree_from_mesh_get(&tree_data, mesh, BVHTREE_FROM_CORNER_TRIS, 4)) { + BVHTreeFromMesh tree_data = mesh->bvh_corner_tris(); + if (use_flow && tree_data.tree != nullptr) { EmitFromDMData data{}; data.fds = fds; @@ -2173,8 +2170,6 @@ static void emit_from_mesh( settings.min_iter_per_thread = 2; BLI_task_parallel_range(min[2], max[2], &data, emit_from_mesh_task_cb, &settings); } - /* Free bvh tree. */ - free_bvhtree_from_mesh(&tree_data); if (vert_vel) { MEM_freeN(vert_vel); diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index c2adfaa11dd..59de24e1e42 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -153,6 +153,18 @@ static void mesh_copy_data(Main *bmain, mesh_dst->runtime->vert_to_face_map_cache = mesh_src->runtime->vert_to_face_map_cache; mesh_dst->runtime->vert_to_corner_map_cache = mesh_src->runtime->vert_to_corner_map_cache; mesh_dst->runtime->corner_to_face_map_cache = mesh_src->runtime->corner_to_face_map_cache; + mesh_dst->runtime->bvh_cache_verts = mesh_src->runtime->bvh_cache_verts; + mesh_dst->runtime->bvh_cache_edges = mesh_src->runtime->bvh_cache_edges; + mesh_dst->runtime->bvh_cache_faces = mesh_src->runtime->bvh_cache_faces; + mesh_dst->runtime->bvh_cache_corner_tris = mesh_src->runtime->bvh_cache_corner_tris; + mesh_dst->runtime->bvh_cache_corner_tris_no_hidden = + mesh_src->runtime->bvh_cache_corner_tris_no_hidden; + mesh_dst->runtime->bvh_cache_loose_verts = mesh_src->runtime->bvh_cache_loose_verts; + mesh_dst->runtime->bvh_cache_loose_verts_no_hidden = + mesh_src->runtime->bvh_cache_loose_verts_no_hidden; + mesh_dst->runtime->bvh_cache_loose_edges = mesh_src->runtime->bvh_cache_loose_edges; + mesh_dst->runtime->bvh_cache_loose_edges_no_hidden = + mesh_src->runtime->bvh_cache_loose_edges_no_hidden; if (mesh_src->runtime->bake_materials) { mesh_dst->runtime->bake_materials = std::make_unique( *mesh_src->runtime->bake_materials); diff --git a/source/blender/blenkernel/intern/mesh_attributes.cc b/source/blender/blenkernel/intern/mesh_attributes.cc index b9e3d42ba51..b0ceeaa4cc6 100644 --- a/source/blender/blenkernel/intern/mesh_attributes.cc +++ b/source/blender/blenkernel/intern/mesh_attributes.cc @@ -832,6 +832,14 @@ class MeshVertexGroupsAttributeProvider final : public DynamicAttributesProvider } }; +static std::function get_tag_modified_function(void *owner, const StringRef name) +{ + if (name.startswith(".hide")) { + return [owner]() { (static_cast(owner))->tag_visibility_changed(); }; + } + return {}; +} + /** * In this function all the attribute providers for a mesh component are created. Most data in this * function is statically allocated, because it does not change over time. @@ -856,16 +864,20 @@ static GeometryAttributeProviders create_attribute_providers_for_mesh() static CustomDataAccessInfo corner_access = {MAKE_MUTABLE_CUSTOM_DATA_GETTER(corner_data), MAKE_CONST_CUSTOM_DATA_GETTER(corner_data), - MAKE_GET_ELEMENT_NUM_GETTER(corners_num)}; + MAKE_GET_ELEMENT_NUM_GETTER(corners_num), + get_tag_modified_function}; static CustomDataAccessInfo point_access = {MAKE_MUTABLE_CUSTOM_DATA_GETTER(vert_data), MAKE_CONST_CUSTOM_DATA_GETTER(vert_data), - MAKE_GET_ELEMENT_NUM_GETTER(verts_num)}; + MAKE_GET_ELEMENT_NUM_GETTER(verts_num), + get_tag_modified_function}; static CustomDataAccessInfo edge_access = {MAKE_MUTABLE_CUSTOM_DATA_GETTER(edge_data), MAKE_CONST_CUSTOM_DATA_GETTER(edge_data), - MAKE_GET_ELEMENT_NUM_GETTER(edges_num)}; + MAKE_GET_ELEMENT_NUM_GETTER(edges_num), + get_tag_modified_function}; static CustomDataAccessInfo face_access = {MAKE_MUTABLE_CUSTOM_DATA_GETTER(face_data), MAKE_CONST_CUSTOM_DATA_GETTER(face_data), - MAKE_GET_ELEMENT_NUM_GETTER(faces_num)}; + MAKE_GET_ELEMENT_NUM_GETTER(faces_num), + get_tag_modified_function}; #undef MAKE_CONST_CUSTOM_DATA_GETTER #undef MAKE_MUTABLE_CUSTOM_DATA_GETTER diff --git a/source/blender/blenkernel/intern/mesh_remap.cc b/source/blender/blenkernel/intern/mesh_remap.cc index 57df2545736..2b1b4bd293c 100644 --- a/source/blender/blenkernel/intern/mesh_remap.cc +++ b/source/blender/blenkernel/intern/mesh_remap.cc @@ -117,14 +117,13 @@ float BKE_mesh_remap_calc_difference_from_mesh(const SpaceTransform *space_trans const int numverts_dst, const Mesh *me_src) { - BVHTreeFromMesh treedata = {nullptr}; BVHTreeNearest nearest = {0}; float hit_dist; float result = 0.0f; int i; - BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_VERTS, 2); + BVHTreeFromMesh treedata = me_src->bvh_verts(); nearest.index = -1; for (i = 0; i < numverts_dst; i++) { @@ -471,14 +470,14 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode, } } else { - BVHTreeFromMesh treedata = {nullptr}; + BVHTreeFromMesh treedata{}; BVHTreeNearest nearest = {0}; BVHTreeRayHit rayhit = {0}; float hit_dist; float tmp_co[3], tmp_no[3]; if (mode == MREMAP_MODE_VERT_NEAREST) { - BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_VERTS, 2); + treedata = me_src->bvh_verts(); nearest.index = -1; for (i = 0; i < numverts_dst; i++) { @@ -503,7 +502,7 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode, const blender::Span edges_src = me_src->edges(); const blender::Span positions_src = me_src->vert_positions(); - BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_EDGES, 2); + treedata = me_src->bvh_edges(); nearest.index = -1; for (i = 0; i < numverts_dst; i++) { @@ -565,7 +564,7 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode, float *weights = static_cast( MEM_mallocN(sizeof(*weights) * tmp_buff_size, __func__)); - BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_CORNER_TRIS, 2); + treedata = me_src->bvh_corner_tris(); if (mode == MREMAP_MODE_VERT_POLYINTERP_VNORPROJ) { for (i = 0; i < numverts_dst; i++) { @@ -665,8 +664,6 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode, CLOG_WARN(&LOG, "Unsupported mesh-to-mesh vertex mapping mode (%d)!", mode); memset(r_map->items, 0, sizeof(*r_map->items) * size_t(numverts_dst)); } - - free_bvhtree_from_mesh(&treedata); } } @@ -698,7 +695,7 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode, } } else { - BVHTreeFromMesh treedata = {nullptr}; + BVHTreeFromMesh treedata{}; BVHTreeNearest nearest = {0}; BVHTreeRayHit rayhit = {0}; float hit_dist; @@ -725,7 +722,7 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode, const GroupedSpan vert_to_edge_src_map = bke::mesh::build_vert_to_edge_map( edges_src, num_verts_src, vert_to_edge_src_offsets, vert_to_edge_src_indices); - BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_VERTS, 2); + treedata = me_src->bvh_verts(); nearest.index = -1; for (i = 0; i < numedges_dst; i++) { @@ -828,7 +825,7 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode, MEM_freeN(v_dst_to_src_map); } else if (mode == MREMAP_MODE_EDGE_NEAREST) { - BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_EDGES, 2); + treedata = me_src->bvh_edges(); nearest.index = -1; for (i = 0; i < numedges_dst; i++) { @@ -859,7 +856,7 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode, const blender::Span positions_src = me_src->vert_positions(); const blender::Span tri_faces = me_src->corner_tri_faces(); - BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_CORNER_TRIS, 2); + treedata = me_src->bvh_corner_tris(); for (i = 0; i < numedges_dst; i++) { interp_v3_v3v3(tmp_co, @@ -916,7 +913,7 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode, float *weights = static_cast( MEM_mallocN(sizeof(*weights) * size_t(numedges_src), __func__)); - BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_EDGES, 2); + treedata = me_src->bvh_edges(); const blender::Span vert_normals_dst = me_dst->vert_normals(); @@ -1013,8 +1010,6 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode, CLOG_WARN(&LOG, "Unsupported mesh-to-mesh edge mapping mode (%d)!", mode); memset(r_map->items, 0, sizeof(*r_map->items) * size_t(numedges_dst)); } - - free_bvhtree_from_mesh(&treedata); } } @@ -1239,7 +1234,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, } } else { - BVHTreeFromMesh *treedata = nullptr; + Array treedata; BVHTreeNearest nearest = {0}; BVHTreeRayHit rayhit = {0}; int num_trees = 0; @@ -1374,8 +1369,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, &island_store); num_trees = use_islands ? island_store.islands_num : 1; - treedata = static_cast( - MEM_callocN(sizeof(*treedata) * size_t(num_trees), __func__)); + treedata.reinitialize(num_trees); if (isld_steps_src) { as_graphdata = static_cast( MEM_callocN(sizeof(*as_graphdata) * size_t(num_trees), __func__)); @@ -1392,7 +1386,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, } else { num_trees = 1; - treedata = static_cast(MEM_callocN(sizeof(*treedata), __func__)); + treedata.reinitialize(1); if (isld_steps_src) { as_graphdata = static_cast(MEM_callocN(sizeof(*as_graphdata), __func__)); } @@ -1436,7 +1430,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, } else { BLI_assert(num_trees == 1); - BKE_bvhtree_from_mesh_get(&treedata[0], me_src, BVHTREE_FROM_VERTS, 2); + treedata[0] = me_src->bvh_verts(); } } else { /* We use faces. */ @@ -1468,7 +1462,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, } else { BLI_assert(num_trees == 1); - BKE_bvhtree_from_mesh_get(&treedata[0], me_src, BVHTREE_FROM_CORNER_TRIS, 2); + treedata[0] = me_src->bvh_corner_tris(); } } @@ -1999,14 +1993,12 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, for (tindex = 0; tindex < num_trees; tindex++) { MEM_freeN(islands_res[tindex]); - free_bvhtree_from_mesh(&treedata[tindex]); if (isld_steps_src) { BLI_astar_graph_free(&as_graphdata[tindex]); } } MEM_freeN(islands_res); BKE_mesh_loop_islands_free(&island_store); - MEM_freeN(treedata); if (isld_steps_src) { MEM_freeN(as_graphdata); BLI_astar_solution_free(&as_solution); @@ -2063,13 +2055,12 @@ void BKE_mesh_remap_calc_faces_from_mesh(const int mode, } } else { - BVHTreeFromMesh treedata = {nullptr}; BVHTreeNearest nearest = {0}; BVHTreeRayHit rayhit = {0}; float hit_dist; const blender::Span tri_faces = me_src->corner_tri_faces(); - BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_CORNER_TRIS, 2); + BVHTreeFromMesh treedata = me_src->bvh_corner_tris(); if (mode == MREMAP_MODE_POLY_NEAREST) { nearest.index = -1; @@ -2308,8 +2299,6 @@ void BKE_mesh_remap_calc_faces_from_mesh(const int mode, CLOG_WARN(&LOG, "Unsupported mesh-to-mesh face mapping mode (%d)!", mode); memset(r_map->items, 0, sizeof(*r_map->items) * size_t(faces_dst.size())); } - - free_bvhtree_from_mesh(&treedata); } } diff --git a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc index 862f168ba8c..731c17d0761 100644 --- a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc +++ b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc @@ -520,8 +520,7 @@ void mesh_remesh_reproject_attributes(const Mesh &src, Mesh &dst) * the decisions made here, which mainly results in easier refactoring, more generic code, and * possibly improved performance from lower cache usage in the "complex" sampling part of the * algorithm and the copying itself. */ - BVHTreeFromMesh bvhtree{}; - BKE_bvhtree_from_mesh_get(&bvhtree, &src, BVHTREE_FROM_CORNER_TRIS, 2); + BVHTreeFromMesh bvhtree = src.bvh_corner_tris(); const Span dst_positions = dst.vert_positions(); const OffsetIndices dst_faces = dst.faces(); @@ -586,8 +585,6 @@ void mesh_remesh_reproject_attributes(const Mesh &src, Mesh &dst) if (src.default_color_attribute) { BKE_id_attributes_default_color_set(&dst.id, src.default_color_attribute); } - - free_bvhtree_from_mesh(&bvhtree); } } // namespace blender::bke diff --git a/source/blender/blenkernel/intern/mesh_runtime.cc b/source/blender/blenkernel/intern/mesh_runtime.cc index 2b8b01551d7..465e64db9b6 100644 --- a/source/blender/blenkernel/intern/mesh_runtime.cc +++ b/source/blender/blenkernel/intern/mesh_runtime.cc @@ -41,14 +41,6 @@ static void free_mesh_eval(MeshRuntime &mesh_runtime) } } -static void free_bvh_cache(MeshRuntime &mesh_runtime) -{ - if (mesh_runtime.bvh_cache) { - bvhcache_free(mesh_runtime.bvh_cache); - mesh_runtime.bvh_cache = nullptr; - } -} - static void free_batch_cache(MeshRuntime &mesh_runtime) { if (mesh_runtime.batch_cache) { @@ -57,12 +49,24 @@ static void free_batch_cache(MeshRuntime &mesh_runtime) } } +static void free_bvh_caches(MeshRuntime &mesh_runtime) +{ + mesh_runtime.bvh_cache_verts.tag_dirty(); + mesh_runtime.bvh_cache_edges.tag_dirty(); + mesh_runtime.bvh_cache_faces.tag_dirty(); + mesh_runtime.bvh_cache_corner_tris.tag_dirty(); + mesh_runtime.bvh_cache_corner_tris_no_hidden.tag_dirty(); + mesh_runtime.bvh_cache_loose_verts.tag_dirty(); + mesh_runtime.bvh_cache_loose_verts_no_hidden.tag_dirty(); + mesh_runtime.bvh_cache_loose_edges.tag_dirty(); + mesh_runtime.bvh_cache_loose_edges_no_hidden.tag_dirty(); +} + MeshRuntime::MeshRuntime() = default; MeshRuntime::~MeshRuntime() { free_mesh_eval(*this); - free_bvh_cache(*this); free_batch_cache(*this); } @@ -312,7 +316,7 @@ void BKE_mesh_runtime_clear_cache(Mesh *mesh) void BKE_mesh_runtime_clear_geometry(Mesh *mesh) { /* Tagging shared caches dirty will free the allocated data if there is only one user. */ - free_bvh_cache(*mesh->runtime); + free_bvh_caches(*mesh->runtime); mesh->runtime->subdiv_ccg.reset(); mesh->runtime->bounds_cache.tag_dirty(); mesh->runtime->vert_to_face_offset_cache.tag_dirty(); @@ -336,7 +340,7 @@ void BKE_mesh_runtime_clear_geometry(Mesh *mesh) void Mesh::tag_edges_split() { /* Triangulation didn't change because vertex positions and loop vertex indices didn't change. */ - free_bvh_cache(*this->runtime); + free_bvh_caches(*this->runtime); this->runtime->vert_normals_cache.tag_dirty(); this->runtime->subdiv_ccg.reset(); this->runtime->vert_to_face_offset_cache.tag_dirty(); @@ -392,7 +396,7 @@ void Mesh::tag_positions_changed() void Mesh::tag_positions_changed_no_normals() { - free_bvh_cache(*this->runtime); + free_bvh_caches(*this->runtime); this->runtime->corner_tris_cache.tag_dirty(); this->runtime->bounds_cache.tag_dirty(); this->runtime->shrinkwrap_boundary_cache.tag_dirty(); @@ -401,7 +405,7 @@ void Mesh::tag_positions_changed_no_normals() void Mesh::tag_positions_changed_uniformly() { /* The normals and triangulation didn't change, since all verts moved by the same amount. */ - free_bvh_cache(*this->runtime); + free_bvh_caches(*this->runtime); this->runtime->bounds_cache.tag_dirty(); } @@ -410,6 +414,13 @@ void Mesh::tag_topology_changed() BKE_mesh_runtime_clear_geometry(this); } +void Mesh::tag_visibility_changed() +{ + this->runtime->bvh_cache_corner_tris_no_hidden.tag_dirty(); + this->runtime->bvh_cache_loose_verts_no_hidden.tag_dirty(); + this->runtime->bvh_cache_loose_edges_no_hidden.tag_dirty(); +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/blenkernel/intern/shrinkwrap.cc b/source/blender/blenkernel/intern/shrinkwrap.cc index 6326fe9b237..f1f9f37f463 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.cc +++ b/source/blender/blenkernel/intern/shrinkwrap.cc @@ -113,6 +113,7 @@ bool BKE_shrinkwrap_init_tree( } data->mesh = mesh; + data->edges = mesh->edges(); data->faces = mesh->faces(); data->corner_edges = mesh->corner_edges(); data->vert_normals = mesh->vert_normals(); @@ -120,8 +121,8 @@ bool BKE_shrinkwrap_init_tree( data->sharp_faces = *attributes.lookup("sharp_face", AttrDomain::Face); if (shrinkType == MOD_SHRINKWRAP_NEAREST_VERTEX) { - data->bvh = BKE_bvhtree_from_mesh_get(&data->treeData, mesh, BVHTREE_FROM_VERTS, 2); - + data->treeData = mesh->bvh_verts(); + data->bvh = data->treeData.tree; return data->bvh != nullptr; } @@ -129,7 +130,8 @@ bool BKE_shrinkwrap_init_tree( return false; } - data->bvh = BKE_bvhtree_from_mesh_get(&data->treeData, mesh, BVHTREE_FROM_CORNER_TRIS, 4); + data->treeData = mesh->bvh_corner_tris(); + data->bvh = data->treeData.tree; if (data->bvh == nullptr) { return false; @@ -149,10 +151,7 @@ bool BKE_shrinkwrap_init_tree( return true; } -void BKE_shrinkwrap_free_tree(ShrinkwrapTreeData *data) -{ - free_bvhtree_from_mesh(&data->treeData); -} +void BKE_shrinkwrap_free_tree(ShrinkwrapTreeData * /*data*/) {} namespace blender::bke::shrinkwrap { @@ -913,7 +912,7 @@ static void target_project_edge(const ShrinkwrapTreeData *tree, int eidx) { const BVHTreeFromMesh *data = &tree->treeData; - const blender::int2 &edge = data->edges[eidx]; + const blender::int2 &edge = tree->edges[eidx]; const float *vedge_co[2] = {data->vert_positions[edge[0]], data->vert_positions[edge[1]]}; #ifdef TRACE_TARGET_PROJECT @@ -1036,7 +1035,7 @@ static void mesh_corner_tris_target_project(void *userdata, { const BitSpan is_boundary = tree->boundary->edge_is_boundary; const int3 edges = bke::mesh::corner_tri_get_real_edges( - data->edges, data->corner_verts, tree->corner_edges, tri); + tree->edges, data->corner_verts, tree->corner_edges, tri); for (int i = 0; i < 3; i++) { if (edges[i] >= 0 && is_boundary[edges[i]]) { diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc index 3f1b2bf2f68..ee6ea3412a4 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc @@ -195,9 +195,8 @@ static void statvis_calc_thickness(const MeshRenderData &mr, MutableSpan } } else { - BVHTreeFromMesh treeData = {nullptr}; - - BVHTree *tree = BKE_bvhtree_from_mesh_get(&treeData, mr.mesh, BVHTREE_FROM_CORNER_TRIS, 4); + BVHTreeFromMesh treeData = mr.mesh->bvh_corner_tris(); + const BVHTree *tree = treeData.tree; if (tree == nullptr) { return; } @@ -327,9 +326,8 @@ static void statvis_calc_intersect(const MeshRenderData &mr, MutableSpan } else { uint overlap_len; - BVHTreeFromMesh treeData = {nullptr}; - - BVHTree *tree = BKE_bvhtree_from_mesh_get(&treeData, mr.mesh, BVHTREE_FROM_CORNER_TRIS, 4); + BVHTreeFromMesh treeData = mr.mesh->bvh_corner_tris(); + const BVHTree *tree = treeData.tree; if (tree == nullptr) { return; } diff --git a/source/blender/editors/armature/meshlaplacian.cc b/source/blender/editors/armature/meshlaplacian.cc index 93d0e8b353d..5ea3bb12a59 100644 --- a/source/blender/editors/armature/meshlaplacian.cc +++ b/source/blender/editors/armature/meshlaplacian.cc @@ -915,7 +915,7 @@ struct MeshDeformBind { /* direct solver */ int *varidx; - BVHTree *bvhtree; + const BVHTree *bvhtree; BVHTreeFromMesh bvhdata; /* avoid DM function calls during intersections */ @@ -1604,8 +1604,8 @@ static void harmonic_coordinates_bind(MeshDeformModifierData *mmd, MeshDeformBin mdb->boundisect = static_cast( MEM_callocN(sizeof(*mdb->boundisect) * mdb->size3, "MDefBoundIsect")); mdb->semibound = static_cast(MEM_callocN(sizeof(int) * mdb->size3, "MDefSemiBound")); - mdb->bvhtree = BKE_bvhtree_from_mesh_get( - &mdb->bvhdata, mdb->cagemesh, BVHTREE_FROM_CORNER_TRIS, 4); + mdb->bvhdata = mdb->cagemesh->bvh_corner_tris(); + mdb->bvhtree = mdb->bvhdata.tree; mdb->inside = static_cast(MEM_callocN(sizeof(int) * mdb->verts_num, "MDefInside")); if (mmd->flag & MOD_MDEF_DYNAMIC_BIND) { @@ -1751,7 +1751,6 @@ static void harmonic_coordinates_bind(MeshDeformModifierData *mmd, MeshDeformBin MEM_freeN(mdb->boundisect); MEM_freeN(mdb->semibound); BLI_memarena_free(mdb->memarena); - free_bvhtree_from_mesh(&mdb->bvhdata); } void ED_mesh_deform_bind_callback(Object *object, diff --git a/source/blender/editors/curves/intern/curves_ops.cc b/source/blender/editors/curves/intern/curves_ops.cc index 70eb12cb36a..c2970828132 100644 --- a/source/blender/editors/curves/intern/curves_ops.cc +++ b/source/blender/editors/curves/intern/curves_ops.cc @@ -273,9 +273,7 @@ static void try_convert_single_object(Object &curves_ob, } Mesh &surface_me = *static_cast(surface_ob.data); - BVHTreeFromMesh surface_bvh; - BKE_bvhtree_from_mesh_get(&surface_bvh, &surface_me, BVHTREE_FROM_CORNER_TRIS, 2); - BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&surface_bvh); }); + BVHTreeFromMesh surface_bvh = surface_me.bvh_corner_tris(); const Span positions_cu = curves.positions(); const Span tri_faces = surface_me.corner_tri_faces(); @@ -615,9 +613,7 @@ static void snap_curves_to_surface_exec_object(Object &curves_ob, switch (attach_mode) { case AttachMode::Nearest: { - BVHTreeFromMesh surface_bvh; - BKE_bvhtree_from_mesh_get(&surface_bvh, &surface_mesh, BVHTREE_FROM_CORNER_TRIS, 2); - BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&surface_bvh); }); + BVHTreeFromMesh surface_bvh = surface_mesh.bvh_corner_tris(); threading::parallel_for(curves.curves_range(), 256, [&](const IndexRange curves_range) { for (const int curve_i : curves_range) { diff --git a/source/blender/editors/physics/particle_edit.cc b/source/blender/editors/physics/particle_edit.cc index 5c13e2493c3..559e34619f5 100644 --- a/source/blender/editors/physics/particle_edit.cc +++ b/source/blender/editors/physics/particle_edit.cc @@ -467,7 +467,7 @@ struct PEData { Object *ob; Mesh *mesh; PTCacheEdit *edit; - BVHTreeFromMesh shape_bvh; + BVHTreeFromMesh *shape_bvh; Depsgraph *depsgraph; RNG *rng; @@ -534,19 +534,17 @@ static bool PE_create_shape_tree(PEData *data, Object *shapeob) Object *shapeob_eval = DEG_get_evaluated_object(data->depsgraph, shapeob); const Mesh *mesh = BKE_object_get_evaluated_mesh(shapeob_eval); - data->shape_bvh = {}; - if (!mesh) { return false; } - return (BKE_bvhtree_from_mesh_get(&data->shape_bvh, mesh, BVHTREE_FROM_CORNER_TRIS, 4) != - nullptr); + data->shape_bvh = MEM_new(__func__, mesh->bvh_corner_tris()); + return data->shape_bvh->tree != nullptr; } static void PE_free_shape_tree(PEData *data) { - free_bvhtree_from_mesh(&data->shape_bvh); + MEM_delete(data->shape_bvh); } static void PE_create_random_generator(PEData *data) @@ -5114,7 +5112,7 @@ static bool shape_cut_poll(bContext *C) } struct PointInsideBVH { - BVHTreeFromMesh bvhdata; + BVHTreeFromMesh *bvhdata; int num_hits; }; @@ -5125,7 +5123,7 @@ static void point_inside_bvh_cb(void *userdata, { PointInsideBVH *data = static_cast(userdata); - data->bvhdata.raycast_callback(&data->bvhdata, index, ray, hit); + data->bvhdata->raycast_callback(&data->bvhdata, index, ray, hit); if (hit->index != -1) { ++data->num_hits; @@ -5135,7 +5133,7 @@ static void point_inside_bvh_cb(void *userdata, /* true if the point is inside the shape mesh */ static bool shape_cut_test_point(PEData *data, ParticleEditSettings *pset, ParticleCacheKey *key) { - BVHTreeFromMesh *shape_bvh = &data->shape_bvh; + BVHTreeFromMesh *shape_bvh = data->shape_bvh; const float dir[3] = {1.0f, 0.0f, 0.0f}; PointInsideBVH userdata; @@ -5193,12 +5191,12 @@ static void shape_cut(PEData *data, int pa_index) memset(&hit, 0, sizeof(hit)); hit.index = -1; hit.dist = len_shape; - BLI_bvhtree_ray_cast(data->shape_bvh.tree, + BLI_bvhtree_ray_cast(data->shape_bvh->tree, co_curr_shape, dir_shape, 0.0f, &hit, - data->shape_bvh.raycast_callback, + data->shape_bvh->raycast_callback, &data->shape_bvh); if (hit.index >= 0) { if (hit.dist < len_shape) { diff --git a/source/blender/editors/physics/particle_object.cc b/source/blender/editors/physics/particle_object.cc index 9945b5b2b6b..b98668c68ba 100644 --- a/source/blender/editors/physics/particle_object.cc +++ b/source/blender/editors/physics/particle_object.cc @@ -757,12 +757,12 @@ static bool remap_hair_emitter(Depsgraph *depsgraph, if (mesh->totface_legacy != 0) { mface = static_cast(CustomData_get_layer(&mesh->fdata_legacy, CD_MFACE)); - BKE_bvhtree_from_mesh_get(&bvhtree, mesh, BVHTREE_FROM_FACES, 2); + bvhtree = mesh->bvh_legacy_faces(); } else if (mesh->edges_num != 0) { edges = static_cast( CustomData_get_layer_named(&mesh->edge_data, CD_PROP_INT32_2D, ".edge_verts")); - BKE_bvhtree_from_mesh_get(&bvhtree, mesh, BVHTREE_FROM_EDGES, 2); + bvhtree = mesh->bvh_edges(); } else { BKE_id_free(nullptr, mesh); @@ -897,7 +897,6 @@ static bool remap_hair_emitter(Depsgraph *depsgraph, } } - free_bvhtree_from_mesh(&bvhtree); BKE_id_free(nullptr, mesh); psys_free_path_cache(target_psys, target_edit); diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_add.cc b/source/blender/editors/sculpt_paint/curves_sculpt_add.cc index 6b231fcb33e..6386328326a 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_add.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_add.cc @@ -142,8 +142,7 @@ struct AddOperationExecutor { surface_positions_eval_ = surface_eval_->vert_positions(); surface_corner_verts_eval_ = surface_eval_->corner_verts(); surface_corner_tris_eval_ = surface_eval_->corner_tris(); - BKE_bvhtree_from_mesh_get(&surface_bvh_eval_, surface_eval_, BVHTREE_FROM_CORNER_TRIS, 2); - BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&surface_bvh_eval_); }); + surface_bvh_eval_ = surface_eval_->bvh_corner_tris(); curves_sculpt_ = ctx_.scene->toolsettings->curves_sculpt; brush_ = BKE_paint_brush_for_read(&curves_sculpt_->paint); diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc b/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc index 4479f1dc5a8..323b4f59f09 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc @@ -8,6 +8,8 @@ #include "BLI_math_geom.h" +#include "DNA_mesh_types.h" + #include "BKE_attribute_math.hh" #include "BKE_bvhutils.hh" #include "BKE_context.hh" @@ -190,9 +192,7 @@ std::optional sample_curves_3d_brush(const Depsgraph &depsgraph, const float4x4 world_to_surface_mat = math::invert(surface_to_world_mat); Mesh *surface_eval = BKE_object_get_evaluated_mesh(surface_object_eval); - BVHTreeFromMesh surface_bvh; - BKE_bvhtree_from_mesh_get(&surface_bvh, surface_eval, BVHTREE_FROM_CORNER_TRIS, 2); - BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&surface_bvh); }); + BVHTreeFromMesh surface_bvh = surface_eval->bvh_corner_tris(); const float3 center_ray_start_su = math::transform_point(world_to_surface_mat, center_ray_start_wo); diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_density.cc b/source/blender/editors/sculpt_paint/curves_sculpt_density.cc index 1b958fa3b89..42e8ac27382 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_density.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_density.cc @@ -130,8 +130,7 @@ struct DensityAddOperationExecutor { return; } - BKE_bvhtree_from_mesh_get(&surface_bvh_eval_, surface_eval_, BVHTREE_FROM_CORNER_TRIS, 2); - BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&surface_bvh_eval_); }); + surface_bvh_eval_ = surface_eval_->bvh_corner_tris(); surface_corner_tris_eval_ = surface_eval_->corner_tris(); /* Find UV map. */ VArraySpan surface_uv_map; @@ -550,8 +549,7 @@ struct DensitySubtractOperationExecutor { } surface_eval_ = BKE_object_get_evaluated_mesh(surface_ob_eval_); - BKE_bvhtree_from_mesh_get(&surface_bvh_eval_, surface_eval_, BVHTREE_FROM_CORNER_TRIS, 2); - BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&surface_bvh_eval_); }); + surface_bvh_eval_ = surface_eval_->bvh_corner_tris(); curves_sculpt_ = ctx_.scene->toolsettings->curves_sculpt; brush_ = BKE_paint_brush_for_read(&curves_sculpt_->paint); @@ -832,9 +830,7 @@ static bool use_add_density_mode(const BrushStrokeMode brush_mode, } const CurvesSurfaceTransforms transforms(curves_ob_orig, curves_id_orig.surface); - BVHTreeFromMesh surface_bvh_eval; - BKE_bvhtree_from_mesh_get(&surface_bvh_eval, surface_mesh_eval, BVHTREE_FROM_CORNER_TRIS, 2); - BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&surface_bvh_eval); }); + BVHTreeFromMesh surface_bvh_eval = surface_mesh_eval->bvh_corner_tris(); const float2 brush_pos_re = stroke_start.mouse_position; /* Reduce radius so that only an inner circle is used to determine the existing density. */ diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc index 6f57b0eef90..a868cc504d4 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc @@ -36,6 +36,7 @@ #include "DNA_brush_types.h" #include "DNA_curves_types.h" +#include "DNA_mesh_types.h" #include "DNA_screen_types.h" #include "RNA_access.hh" @@ -1025,9 +1026,7 @@ static int min_distance_edit_invoke(bContext *C, wmOperator *op, const wmEvent * return OPERATOR_CANCELLED; } - BVHTreeFromMesh surface_bvh_eval; - BKE_bvhtree_from_mesh_get(&surface_bvh_eval, surface_me_eval, BVHTREE_FROM_CORNER_TRIS, 2); - BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&surface_bvh_eval); }); + BVHTreeFromMesh surface_bvh_eval = surface_me_eval->bvh_corner_tris(); const int2 mouse_pos_int_re{event->mval}; const float2 mouse_pos_re{mouse_pos_int_re}; diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc b/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc index 1e95a983b2f..cfc4e8cc286 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc @@ -118,8 +118,7 @@ struct PuffOperationExecutor { surface_corner_verts_ = surface_->corner_verts(); surface_corner_tris_ = surface_->corner_tris(); corner_normals_su_ = surface_->corner_normals(); - BKE_bvhtree_from_mesh_get(&surface_bvh_, surface_, BVHTREE_FROM_CORNER_TRIS, 2); - BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&surface_bvh_); }); + surface_bvh_ = surface_->bvh_corner_tris(); if (stroke_extension.is_first) { if (falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE) { diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_slide.cc b/source/blender/editors/sculpt_paint/curves_sculpt_slide.cc index 64814141e91..74a39fcab83 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_slide.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_slide.cc @@ -197,8 +197,7 @@ struct SlideOperationExecutor { report_missing_uv_map_on_evaluated_surface(stroke_extension.reports); return; } - BKE_bvhtree_from_mesh_get(&surface_bvh_eval_, surface_eval_, BVHTREE_FROM_CORNER_TRIS, 2); - BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&surface_bvh_eval_); }); + surface_bvh_eval_ = surface_eval_->bvh_corner_tris(); if (stroke_extension.is_first) { self_->initial_brush_pos_re_ = brush_pos_re_; diff --git a/source/blender/editors/sculpt_paint/paint_utils.cc b/source/blender/editors/sculpt_paint/paint_utils.cc index 7bdecdb5982..ff9ea5232d8 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.cc +++ b/source/blender/editors/sculpt_paint/paint_utils.cc @@ -283,9 +283,7 @@ static int imapaint_pick_face(ViewContext *vc, const float3 start_object = math::transform_point(world_to_object, start_world); const float3 end_object = math::transform_point(world_to_object, end_world); - BVHTreeFromMesh mesh_bvh; - BKE_bvhtree_from_mesh_get(&mesh_bvh, &mesh, BVHTREE_FROM_CORNER_TRIS, 2); - BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&mesh_bvh); }); + BVHTreeFromMesh mesh_bvh = mesh.bvh_corner_tris(); BVHTreeRayHit ray_hit; ray_hit.dist = FLT_MAX; diff --git a/source/blender/editors/transform/transform_snap_object.cc b/source/blender/editors/transform/transform_snap_object.cc index dfa83588348..a83232e2fa5 100644 --- a/source/blender/editors/transform/transform_snap_object.cc +++ b/source/blender/editors/transform/transform_snap_object.cc @@ -651,7 +651,7 @@ static bool raycastObjects(SnapObjectContext *sctx) /** \name Surface Snap Functions * \{ */ -static void nearest_world_tree_co(BVHTree *tree, +static void nearest_world_tree_co(const BVHTree *tree, BVHTree_NearestPointCallback nearest_cb, void *treedata, const float3 &co, @@ -665,7 +665,7 @@ static void nearest_world_tree_co(BVHTree *tree, } bool nearest_world_tree(SnapObjectContext *sctx, - BVHTree *tree, + const BVHTree *tree, BVHTree_NearestPointCallback nearest_cb, const blender::float4x4 &obmat, void *treedata, diff --git a/source/blender/editors/transform/transform_snap_object.hh b/source/blender/editors/transform/transform_snap_object.hh index a64aa0b0613..2f7771f40f6 100644 --- a/source/blender/editors/transform/transform_snap_object.hh +++ b/source/blender/editors/transform/transform_snap_object.hh @@ -181,7 +181,7 @@ void cb_snap_edge(void *userdata, BVHTreeNearest *nearest); bool nearest_world_tree(SnapObjectContext *sctx, - BVHTree *tree, + const BVHTree *tree, BVHTree_NearestPointCallback nearest_cb, const blender::float4x4 &obmat, void *treedata, diff --git a/source/blender/editors/transform/transform_snap_object_mesh.cc b/source/blender/editors/transform/transform_snap_object_mesh.cc index 284a1cc6647..07cd6655a04 100644 --- a/source/blender/editors/transform/transform_snap_object_mesh.cc +++ b/source/blender/editors/transform/transform_snap_object_mesh.cc @@ -34,11 +34,12 @@ static void snap_object_data_mesh_get(const Mesh *mesh_eval, BVHTreeFromMesh *r_treedata) { /* The BVHTree from corner_tris is always required. */ - BKE_bvhtree_from_mesh_get(r_treedata, - mesh_eval, - skip_hidden ? BVHTREE_FROM_CORNER_TRIS_NO_HIDDEN : - BVHTREE_FROM_CORNER_TRIS, - 4); + if (skip_hidden) { + *r_treedata = mesh_eval->bvh_corner_tris_no_hidden(); + } + else { + *r_treedata = mesh_eval->bvh_corner_tris(); + } } /** \} */ @@ -476,20 +477,12 @@ static eSnapMode snapMesh(SnapObjectContext *sctx, BVHTreeFromMesh treedata, treedata_dummy; snap_object_data_mesh_get(mesh_eval, skip_hidden, &treedata); - BVHTree *bvhtree[2] = {nullptr}; - bvhtree[0] = BKE_bvhtree_from_mesh_get(&treedata_dummy, - mesh_eval, - skip_hidden ? BVHTREE_FROM_LOOSEEDGES_NO_HIDDEN : - BVHTREE_FROM_LOOSEEDGES, - 2); - BLI_assert(treedata_dummy.cached); + const BVHTree *bvhtree[2] = {nullptr}; + bvhtree[0] = skip_hidden ? mesh_eval->bvh_loose_no_hidden_edges().tree : + mesh_eval->bvh_loose_edges().tree; if (snap_to & SCE_SNAP_TO_POINT) { - bvhtree[1] = BKE_bvhtree_from_mesh_get(&treedata_dummy, - mesh_eval, - skip_hidden ? BVHTREE_FROM_LOOSEVERTS_NO_HIDDEN : - BVHTREE_FROM_LOOSEVERTS, - 2); - BLI_assert(treedata_dummy.cached); + bvhtree[1] = skip_hidden ? mesh_eval->bvh_loose_no_hidden_verts().tree : + mesh_eval->bvh_loose_verts().tree; } /* #XRAY_ENABLED can return false even with the XRAY flag enabled, this happens because the diff --git a/source/blender/geometry/intern/curve_constraints.cc b/source/blender/geometry/intern/curve_constraints.cc index 0020c466a44..1a0df4d0d87 100644 --- a/source/blender/geometry/intern/curve_constraints.cc +++ b/source/blender/geometry/intern/curve_constraints.cc @@ -5,6 +5,8 @@ #include "BLI_math_matrix.hh" #include "BLI_task.hh" +#include "DNA_mesh_types.h" + #include "GEO_curve_constraints.hh" #include "BKE_bvhutils.hh" @@ -69,9 +71,7 @@ void solve_length_and_collision_constraints(const OffsetIndices points_by_c { solve_length_constraints(points_by_curve, curve_selection, segment_lengths_cu, positions_cu); - BVHTreeFromMesh surface_bvh; - BKE_bvhtree_from_mesh_get(&surface_bvh, &surface, BVHTREE_FROM_CORNER_TRIS, 2); - BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&surface_bvh); }); + BVHTreeFromMesh surface_bvh = surface.bvh_corner_tris(); const float radius = 0.005f; const int max_collisions = 5; diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index d5499473453..ada4d4f6018 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -46,6 +46,7 @@ typedef struct MeshRuntimeHandle MeshRuntimeHandle; #endif struct AnimData; +struct BVHTreeFromMesh; struct Ipo; struct Key; struct MCol; @@ -398,6 +399,16 @@ typedef struct Mesh { */ blender::Span corner_normals() const; + BVHTreeFromMesh bvh_verts() const; + BVHTreeFromMesh bvh_edges() const; + BVHTreeFromMesh bvh_legacy_faces() const; + BVHTreeFromMesh bvh_corner_tris() const; + BVHTreeFromMesh bvh_corner_tris_no_hidden() const; + BVHTreeFromMesh bvh_loose_verts() const; + BVHTreeFromMesh bvh_loose_edges() const; + BVHTreeFromMesh bvh_loose_no_hidden_verts() const; + BVHTreeFromMesh bvh_loose_no_hidden_edges() const; + void count_memory(blender::MemoryCounter &memory) const; /** Call after changing vertex positions to tag lazily calculated caches for recomputation. */ @@ -416,6 +427,8 @@ typedef struct Mesh { void tag_edges_split(); /** Call for topology updates not described by other update tags. */ void tag_topology_changed(); + /** Call when changing the ".hide_vert", ".hide_edge", or ".hide_poly" attributes. */ + void tag_visibility_changed(); #endif } Mesh; diff --git a/source/blender/makesrna/intern/rna_object_api.cc b/source/blender/makesrna/intern/rna_object_api.cc index 692810d51a2..15c96812157 100644 --- a/source/blender/makesrna/intern/rna_object_api.cc +++ b/source/blender/makesrna/intern/rna_object_api.cc @@ -624,11 +624,10 @@ static void rna_Object_ray_cast(Object *ob, origin, direction_unit, bounds->min, bounds->max, &distmin, nullptr) && distmin <= distance)) { - BVHTreeFromMesh treeData = {nullptr}; /* No need to managing allocation or freeing of the BVH data. * This is generated and freed as needed. */ - BKE_bvhtree_from_mesh_get(&treeData, mesh_eval, BVHTREE_FROM_CORNER_TRIS, 4); + BVHTreeFromMesh treeData = mesh_eval->bvh_corner_tris(); /* may fail if the mesh has no faces, in that case the ray-cast misses */ if (treeData.tree != nullptr) { @@ -653,8 +652,6 @@ static void rna_Object_ray_cast(Object *ob, *r_index = mesh_corner_tri_to_face_index(mesh_eval, hit.index); } } - - free_bvhtree_from_mesh(&treeData); } } if (success == false) { @@ -677,7 +674,6 @@ static void rna_Object_closest_point_on_mesh(Object *ob, float r_normal[3], int *r_index) { - BVHTreeFromMesh treeData = {nullptr}; if ((ob = eval_object_ensure(ob, C, reports, rnaptr_depsgraph)) == nullptr) { return; @@ -686,7 +682,7 @@ static void rna_Object_closest_point_on_mesh(Object *ob, /* No need to managing allocation or freeing of the BVH data. * this is generated and freed as needed. */ Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); - BKE_bvhtree_from_mesh_get(&treeData, mesh_eval, BVHTREE_FROM_CORNER_TRIS, 4); + BVHTreeFromMesh treeData = mesh_eval->bvh_corner_tris(); if (treeData.tree == nullptr) { BKE_reportf(reports, @@ -709,8 +705,6 @@ static void rna_Object_closest_point_on_mesh(Object *ob, copy_v3_v3(r_location, nearest.co); copy_v3_v3(r_normal, nearest.no); *r_index = mesh_corner_tri_to_face_index(mesh_eval, nearest.index); - - goto finally; } } @@ -719,9 +713,6 @@ static void rna_Object_closest_point_on_mesh(Object *ob, zero_v3(r_location); zero_v3(r_normal); *r_index = -1; - -finally: - free_bvhtree_from_mesh(&treeData); } static bool rna_Object_is_modified(Object *ob, Scene *scene, int settings) diff --git a/source/blender/modifiers/intern/MOD_surface.cc b/source/blender/modifiers/intern/MOD_surface.cc index 52e8bb02cdc..3ce9641577e 100644 --- a/source/blender/modifiers/intern/MOD_surface.cc +++ b/source/blender/modifiers/intern/MOD_surface.cc @@ -58,8 +58,8 @@ static void free_data(ModifierData *md) if (surmd) { if (surmd->runtime.bvhtree) { - free_bvhtree_from_mesh(surmd->runtime.bvhtree); - MEM_SAFE_FREE(surmd->runtime.bvhtree); + MEM_delete(surmd->runtime.bvhtree); + surmd->runtime.bvhtree = nullptr; } if (surmd->runtime.mesh) { @@ -87,10 +87,8 @@ static void deform_verts(ModifierData *md, const int cfra = int(DEG_get_ctime(ctx->depsgraph)); /* Free mesh and BVH cache. */ - if (surmd->runtime.bvhtree) { - free_bvhtree_from_mesh(surmd->runtime.bvhtree); - MEM_SAFE_FREE(surmd->runtime.bvhtree); - } + MEM_delete(surmd->runtime.bvhtree); + surmd->runtime.bvhtree = nullptr; if (surmd->runtime.mesh) { BKE_id_free(nullptr, surmd->runtime.mesh); @@ -159,12 +157,10 @@ static void deform_verts(ModifierData *md, MEM_callocN(sizeof(BVHTreeFromMesh), __func__)); if (has_face) { - BKE_bvhtree_from_mesh_get( - surmd->runtime.bvhtree, surmd->runtime.mesh, BVHTREE_FROM_CORNER_TRIS, 2); + *surmd->runtime.bvhtree = surmd->runtime.mesh->bvh_corner_tris(); } else if (has_edge) { - BKE_bvhtree_from_mesh_get( - surmd->runtime.bvhtree, surmd->runtime.mesh, BVHTREE_FROM_EDGES, 2); + *surmd->runtime.bvhtree = surmd->runtime.mesh->bvh_edges(); } } } diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.cc b/source/blender/modifiers/intern/MOD_surfacedeform.cc index 100cfc55342..40045f732ce 100644 --- a/source/blender/modifiers/intern/MOD_surfacedeform.cc +++ b/source/blender/modifiers/intern/MOD_surfacedeform.cc @@ -1172,7 +1172,6 @@ static bool surfacedeformBind(Object *ob, Mesh *target, Mesh *mesh) { - BVHTreeFromMesh treeData = {nullptr}; const blender::Span positions = target->vert_positions(); const blender::Span edges = target->edges(); const blender::OffsetIndices polys = target->faces(); @@ -1213,7 +1212,7 @@ static bool surfacedeformBind(Object *ob, return false; } - BKE_bvhtree_from_mesh_get(&treeData, target, BVHTREE_FROM_CORNER_TRIS, 2); + BVHTreeFromMesh treeData = target->bvh_corner_tris(); if (treeData.tree == nullptr) { BKE_modifier_set_error(ob, (ModifierData *)smd_eval, "Out of memory"); freeAdjacencyMap(vert_edges, adj_array, edge_polys); @@ -1228,7 +1227,6 @@ static bool surfacedeformBind(Object *ob, BKE_modifier_set_error( ob, (ModifierData *)smd_eval, "Target has edges with more than two polygons"); freeAdjacencyMap(vert_edges, adj_array, edge_polys); - free_bvhtree_from_mesh(&treeData); MEM_freeN(smd_orig->verts); smd_orig->verts = nullptr; return false; @@ -1323,7 +1321,6 @@ static bool surfacedeformBind(Object *ob, } freeAdjacencyMap(vert_edges, adj_array, edge_polys); - free_bvhtree_from_mesh(&treeData); return data.success == 1; } diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.cc b/source/blender/modifiers/intern/MOD_weightvgproximity.cc index e6612b0c92e..4e408278c3b 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.cc +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.cc @@ -154,13 +154,13 @@ static void get_vert2geom_distance(int verts_num, Vert2GeomData data{}; Vert2GeomDataChunk data_chunk = {{{0}}}; - BVHTreeFromMesh treeData_v = {nullptr}; - BVHTreeFromMesh treeData_e = {nullptr}; - BVHTreeFromMesh treeData_f = {nullptr}; + BVHTreeFromMesh treeData_v{}; + BVHTreeFromMesh treeData_e{}; + BVHTreeFromMesh treeData_f{}; if (dist_v) { /* Create a BVH-tree of the given target's verts. */ - BKE_bvhtree_from_mesh_get(&treeData_v, target, BVHTREE_FROM_VERTS, 2); + treeData_v = target->bvh_verts(); if (treeData_v.tree == nullptr) { OUT_OF_MEMORY(); return; @@ -168,7 +168,7 @@ static void get_vert2geom_distance(int verts_num, } if (dist_e) { /* Create a BVH-tree of the given target's edges. */ - BKE_bvhtree_from_mesh_get(&treeData_e, target, BVHTREE_FROM_EDGES, 2); + treeData_e = target->bvh_edges(); if (treeData_e.tree == nullptr) { OUT_OF_MEMORY(); return; @@ -176,7 +176,7 @@ static void get_vert2geom_distance(int verts_num, } if (dist_f) { /* Create a BVH-tree of the given target's faces. */ - BKE_bvhtree_from_mesh_get(&treeData_f, target, BVHTREE_FROM_CORNER_TRIS, 2); + treeData_f = target->bvh_corner_tris(); if (treeData_f.tree == nullptr) { OUT_OF_MEMORY(); return; @@ -199,16 +199,6 @@ static void get_vert2geom_distance(int verts_num, settings.userdata_chunk = &data_chunk; settings.userdata_chunk_size = sizeof(data_chunk); BLI_task_parallel_range(0, verts_num, &data, vert2geom_task_cb_ex, &settings); - - if (dist_v) { - free_bvhtree_from_mesh(&treeData_v); - } - if (dist_e) { - free_bvhtree_from_mesh(&treeData_e); - } - if (dist_f) { - free_bvhtree_from_mesh(&treeData_f); - } } /** diff --git a/source/blender/nodes/geometry/nodes/node_geo_proximity.cc b/source/blender/nodes/geometry/nodes/node_geo_proximity.cc index d91cdd2412d..4a7a8d234e3 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_proximity.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_proximity.cc @@ -99,9 +99,6 @@ class ProximityFunction : public mf::MultiFunction { ~ProximityFunction() { for (BVHTrees &trees : bvh_trees_) { - if (trees.mesh_bvh.tree) { - free_bvhtree_from_mesh(&trees.mesh_bvh); - } if (trees.pointcloud_bvh.tree) { free_bvhtree_from_pointcloud(&trees.pointcloud_bvh); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_raycast.cc b/source/blender/nodes/geometry/nodes/node_geo_raycast.cc index a395f4b7a02..e03e856e979 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_raycast.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_raycast.cc @@ -99,15 +99,10 @@ static void raycast_to_mesh(const IndexMask &mask, const MutableSpan r_hit_normals, const MutableSpan r_hit_distances) { - BVHTreeFromMesh tree_data; - BKE_bvhtree_from_mesh_get(&tree_data, &mesh, BVHTREE_FROM_CORNER_TRIS, 4); - BLI_SCOPED_DEFER([&]() { free_bvhtree_from_mesh(&tree_data); }); - + BVHTreeFromMesh tree_data = mesh.bvh_corner_tris(); if (tree_data.tree == nullptr) { return; } - /* We shouldn't be rebuilding the BVH tree when calling this function in parallel. */ - BLI_assert(tree_data.cached); mask.foreach_index([&](const int i) { const float ray_length = ray_lengths[i]; diff --git a/source/blender/nodes/geometry/nodes/node_geo_sample_nearest.cc b/source/blender/nodes/geometry/nodes/node_geo_sample_nearest.cc index 96551bdfc69..ea9ce5cdad4 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_sample_nearest.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_sample_nearest.cc @@ -112,10 +112,8 @@ static void get_closest_mesh_points(const Mesh &mesh, const MutableSpan r_positions) { BLI_assert(mesh.verts_num > 0); - BVHTreeFromMesh tree_data; - BKE_bvhtree_from_mesh_get(&tree_data, &mesh, BVHTREE_FROM_VERTS, 2); + BVHTreeFromMesh tree_data = mesh.bvh_verts(); get_closest_in_bvhtree(tree_data, positions, mask, r_point_indices, r_distances_sq, r_positions); - free_bvhtree_from_mesh(&tree_data); } static void get_closest_mesh_edges(const Mesh &mesh, @@ -126,10 +124,8 @@ static void get_closest_mesh_edges(const Mesh &mesh, const MutableSpan r_positions) { BLI_assert(mesh.edges_num > 0); - BVHTreeFromMesh tree_data; - BKE_bvhtree_from_mesh_get(&tree_data, &mesh, BVHTREE_FROM_EDGES, 2); + BVHTreeFromMesh tree_data = mesh.bvh_edges(); get_closest_in_bvhtree(tree_data, positions, mask, r_edge_indices, r_distances_sq, r_positions); - free_bvhtree_from_mesh(&tree_data); } static void get_closest_mesh_tris(const Mesh &mesh, @@ -140,10 +136,8 @@ static void get_closest_mesh_tris(const Mesh &mesh, const MutableSpan r_positions) { BLI_assert(mesh.faces_num > 0); - BVHTreeFromMesh tree_data; - BKE_bvhtree_from_mesh_get(&tree_data, &mesh, BVHTREE_FROM_CORNER_TRIS, 2); + BVHTreeFromMesh tree_data = mesh.bvh_corner_tris(); get_closest_in_bvhtree(tree_data, positions, mask, r_tri_indices, r_distances_sq, r_positions); - free_bvhtree_from_mesh(&tree_data); } static void get_closest_mesh_faces(const Mesh &mesh, diff --git a/source/blender/nodes/geometry/nodes/node_geo_sample_nearest_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_sample_nearest_surface.cc index 8e3d9f4e474..e604eb52598 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_sample_nearest_surface.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_sample_nearest_surface.cc @@ -130,12 +130,7 @@ class SampleNearestSurfaceFunction : public mf::MultiFunction { [&](const int group_i) { return group_masks[group_i].size(); }, mesh.faces_num)); } - ~SampleNearestSurfaceFunction() - { - for (BVHTreeFromMesh &tree : bvh_trees_) { - free_bvhtree_from_mesh(&tree); - } - } + ~SampleNearestSurfaceFunction() = default; void call(const IndexMask &mask, mf::Params params, mf::Context /*context*/) const override { diff --git a/source/blender/render/intern/bake.cc b/source/blender/render/intern/bake.cc index cd1649169d6..a6530adf099 100644 --- a/source/blender/render/intern/bake.cc +++ b/source/blender/render/intern/bake.cc @@ -594,9 +594,7 @@ bool RE_bake_pixels_populate_from_objects(Mesh *me_low, me_highpoly[i] = highpoly[i].mesh; if (BKE_mesh_runtime_corner_tris_len(me_highpoly[i]) != 0) { - /* Create a BVH-tree for each `highpoly` object. */ - BKE_bvhtree_from_mesh_get(&treeData[i], me_highpoly[i], BVHTREE_FROM_CORNER_TRIS, 2); - + treeData[i] = me_highpoly[i]->bvh_corner_tris(); if (treeData[i].tree == nullptr) { printf("Baking: out of memory while creating BHVTree for object \"%s\"\n", highpoly[i].ob->id.name + 2); @@ -663,8 +661,6 @@ bool RE_bake_pixels_populate_from_objects(Mesh *me_low, /* garbage collection */ cleanup: for (int i = 0; i < tot_highpoly; i++) { - free_bvhtree_from_mesh(&treeData[i]); - if (tris_high[i]) { MEM_freeN(tris_high[i]); }