From 024d7d12e24a5468d3e9878adf29b0b0443b5dc8 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 4 Dec 2024 00:17:17 +0100 Subject: [PATCH] Mesh: Move BVH storage to shared cache system Avoid rebuilding BVH trees when meshes are copied. Similar to the other uses of the shared cache system, this can arbitrarily improve performance when meshes are copied but not deformed and BVH building is the main bottleneck. In a simple test file I got a 6x speedup. The amount of code is also reduced and the system is much simpler overall-- built out of common threading patterns like `SharedCache` with its double-checked lock. RAII is used in a few places to simplify memory management too. The downside is storing more `SharedCache` items in the mesh runtime struct. That has a slight cost when copying a small mesh many times, but we have ideas to improve that in the future anyway (#104327). Pull Request: https://projects.blender.org/blender/blender/pulls/130865 --- source/blender/blenkernel/BKE_bvhutils.hh | 42 +- source/blender/blenkernel/BKE_mesh_types.hh | 21 +- source/blender/blenkernel/BKE_shrinkwrap.hh | 3 +- .../blenkernel/intern/attribute_access.cc | 25 +- .../intern/attribute_access_intern.hh | 4 + source/blender/blenkernel/intern/bvhutils.cc | 528 +++++++----------- source/blender/blenkernel/intern/cloth.cc | 5 +- .../blender/blenkernel/intern/constraint.cc | 5 +- .../blender/blenkernel/intern/dynamicpaint.cc | 6 +- source/blender/blenkernel/intern/fluid.cc | 13 +- source/blender/blenkernel/intern/mesh.cc | 12 + .../blenkernel/intern/mesh_attributes.cc | 20 +- .../blender/blenkernel/intern/mesh_remap.cc | 43 +- .../blenkernel/intern/mesh_remesh_voxel.cc | 5 +- .../blender/blenkernel/intern/mesh_runtime.cc | 37 +- .../blender/blenkernel/intern/shrinkwrap.cc | 17 +- .../extract_mesh_vbo_mesh_analysis.cc | 10 +- .../blender/editors/armature/meshlaplacian.cc | 7 +- .../editors/curves/intern/curves_ops.cc | 8 +- .../blender/editors/physics/particle_edit.cc | 20 +- .../editors/physics/particle_object.cc | 5 +- .../editors/sculpt_paint/curves_sculpt_add.cc | 3 +- .../sculpt_paint/curves_sculpt_brush.cc | 6 +- .../sculpt_paint/curves_sculpt_density.cc | 10 +- .../editors/sculpt_paint/curves_sculpt_ops.cc | 5 +- .../sculpt_paint/curves_sculpt_puff.cc | 3 +- .../sculpt_paint/curves_sculpt_slide.cc | 3 +- .../editors/sculpt_paint/paint_utils.cc | 4 +- .../transform/transform_snap_object.cc | 4 +- .../transform/transform_snap_object.hh | 2 +- .../transform/transform_snap_object_mesh.cc | 29 +- .../geometry/intern/curve_constraints.cc | 6 +- source/blender/makesdna/DNA_mesh_types.h | 13 + .../blender/makesrna/intern/rna_object_api.cc | 13 +- .../blender/modifiers/intern/MOD_surface.cc | 16 +- .../modifiers/intern/MOD_surfacedeform.cc | 5 +- .../modifiers/intern/MOD_weightvgproximity.cc | 22 +- .../geometry/nodes/node_geo_proximity.cc | 3 - .../nodes/geometry/nodes/node_geo_raycast.cc | 7 +- .../geometry/nodes/node_geo_sample_nearest.cc | 12 +- .../nodes/node_geo_sample_nearest_surface.cc | 7 +- source/blender/render/intern/bake.cc | 6 +- 42 files changed, 438 insertions(+), 577 deletions(-) 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]); }