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
This commit is contained in:
@@ -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<BVHTree, BVHTreeDeleter> 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);
|
||||
|
||||
@@ -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<Array<int>> corner_tri_faces_cache;
|
||||
|
||||
/** Cache for BVH trees generated for the mesh. Defined in 'BKE_bvhutil.c' */
|
||||
BVHCache *bvh_cache = nullptr;
|
||||
SharedCache<BVHCacheItem> bvh_cache_verts;
|
||||
SharedCache<BVHCacheItem> bvh_cache_edges;
|
||||
SharedCache<BVHCacheItem> bvh_cache_faces;
|
||||
SharedCache<BVHCacheItem> bvh_cache_corner_tris;
|
||||
SharedCache<BVHCacheItem> bvh_cache_corner_tris_no_hidden;
|
||||
SharedCache<BVHCacheItem> bvh_cache_loose_verts;
|
||||
SharedCache<BVHCacheItem> bvh_cache_loose_verts_no_hidden;
|
||||
SharedCache<BVHCacheItem> bvh_cache_loose_edges;
|
||||
SharedCache<BVHCacheItem> bvh_cache_loose_edges_no_hidden;
|
||||
|
||||
/** Needed in case we need to lazily initialize the mesh. */
|
||||
CustomData_MeshMasks cd_mask_extra = {};
|
||||
|
||||
@@ -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<int> faces;
|
||||
blender::Span<blender::int2> edges;
|
||||
blender::Span<int> corner_edges;
|
||||
|
||||
blender::Span<blender::float3> face_normals;
|
||||
|
||||
@@ -481,8 +481,12 @@ GAttributeWriter CustomDataAttributeProvider::try_get_for_write(void *owner,
|
||||
if (type == nullptr) {
|
||||
continue;
|
||||
}
|
||||
std::function<void()> 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<void()> 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<void()> fn = custom_data_access_.get_tag_modified_function(
|
||||
owner, attribute_id))
|
||||
{
|
||||
fn();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include <functional>
|
||||
|
||||
#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()> (*)(void *owner, StringRef name);
|
||||
|
||||
CustomDataGetter get_custom_data;
|
||||
ConstCustomDataGetter get_const_custom_data;
|
||||
GetElementNum get_element_num;
|
||||
GetTagModifiedFunction get_tag_modified_function;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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<BVHCache>(__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<float3> positions,
|
||||
const Span<blender::int2> edges,
|
||||
const Span<int> corner_verts,
|
||||
const Span<int3> corner_tris,
|
||||
const MFace *face,
|
||||
BVHTreeFromMesh *r_data)
|
||||
static BVHTreeFromMesh bvhtree_from_mesh_setup_data(BVHTree *tree,
|
||||
const BVHCacheType bvh_cache_type,
|
||||
const Span<float3> positions,
|
||||
const Span<blender::int2> edges,
|
||||
const Span<int> corner_verts,
|
||||
const Span<int3> 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::OffsetIndices<in
|
||||
return corner_tris_mask;
|
||||
}
|
||||
|
||||
BVHTree *BKE_bvhtree_from_mesh_get(BVHTreeFromMesh *data,
|
||||
const Mesh *mesh,
|
||||
const BVHCacheType bvh_cache_type,
|
||||
const int tree_type)
|
||||
BVHTreeFromMesh Mesh::bvh_loose_verts() const
|
||||
{
|
||||
using namespace blender;
|
||||
using namespace blender::bke;
|
||||
BVHCache **bvh_cache_p = (BVHCache **)&mesh->runtime->bvh_cache;
|
||||
|
||||
Span<int3> corner_tris;
|
||||
if (ELEM(bvh_cache_type, BVHTREE_FROM_CORNER_TRIS, BVHTREE_FROM_CORNER_TRIS_NO_HIDDEN)) {
|
||||
corner_tris = mesh->corner_tris();
|
||||
}
|
||||
|
||||
const Span<float3> positions = mesh->vert_positions();
|
||||
const Span<int2> edges = mesh->edges();
|
||||
const Span<int> 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<float3> 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<float3> 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<float3> 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<float3> positions = this->vert_positions();
|
||||
const Span<int2> 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<float3> positions = this->vert_positions();
|
||||
const Span<int2> 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<float3> positions = this->vert_positions();
|
||||
const Span<int2> 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<float3> 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<float3> positions = this->vert_positions();
|
||||
const Span<int> corner_verts = this->corner_verts();
|
||||
const Span<int3> 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<float3> positions = this->vert_positions();
|
||||
const Span<int> corner_verts = this->corner_verts();
|
||||
const Span<int3> 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<int> corner_verts = mesh.corner_verts();
|
||||
const OffsetIndices faces = mesh.faces();
|
||||
const Span<int3> 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<BVHTree, BVHTreeDeleter>(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<float3> positions = mesh.vert_positions();
|
||||
const Span<int2> 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<BVHTree, BVHTreeDeleter>(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<float3> 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<BVHTree, BVHTreeDeleter>(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
|
||||
* \{ */
|
||||
|
||||
@@ -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<OrderedEdge> 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<blender::float3> 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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<blender::bke::bake::BakeMaterialsList>(
|
||||
*mesh_src->runtime->bake_materials);
|
||||
|
||||
@@ -832,6 +832,14 @@ class MeshVertexGroupsAttributeProvider final : public DynamicAttributesProvider
|
||||
}
|
||||
};
|
||||
|
||||
static std::function<void()> get_tag_modified_function(void *owner, const StringRef name)
|
||||
{
|
||||
if (name.startswith(".hide")) {
|
||||
return [owner]() { (static_cast<Mesh *>(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
|
||||
|
||||
@@ -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<blender::int2> edges_src = me_src->edges();
|
||||
const blender::Span<blender::float3> 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<float *>(
|
||||
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<int> 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<blender::float3> positions_src = me_src->vert_positions();
|
||||
const blender::Span<int> 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<float *>(
|
||||
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<blender::float3> 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<BVHTreeFromMesh> 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<BVHTreeFromMesh *>(
|
||||
MEM_callocN(sizeof(*treedata) * size_t(num_trees), __func__));
|
||||
treedata.reinitialize(num_trees);
|
||||
if (isld_steps_src) {
|
||||
as_graphdata = static_cast<BLI_AStarGraph *>(
|
||||
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<BVHTreeFromMesh *>(MEM_callocN(sizeof(*treedata), __func__));
|
||||
treedata.reinitialize(1);
|
||||
if (isld_steps_src) {
|
||||
as_graphdata = static_cast<BLI_AStarGraph *>(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<int> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<float3> 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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
@@ -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<bool>("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]]) {
|
||||
|
||||
@@ -195,9 +195,8 @@ static void statvis_calc_thickness(const MeshRenderData &mr, MutableSpan<float>
|
||||
}
|
||||
}
|
||||
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<float>
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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<MDefBoundIsect *(*)[6]>(
|
||||
MEM_callocN(sizeof(*mdb->boundisect) * mdb->size3, "MDefBoundIsect"));
|
||||
mdb->semibound = static_cast<int *>(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<int *>(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,
|
||||
|
||||
@@ -273,9 +273,7 @@ static void try_convert_single_object(Object &curves_ob,
|
||||
}
|
||||
Mesh &surface_me = *static_cast<Mesh *>(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<float3> positions_cu = curves.positions();
|
||||
const Span<int> 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) {
|
||||
|
||||
@@ -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<BVHTreeFromMesh>(__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<PointInsideBVH *>(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) {
|
||||
|
||||
@@ -757,12 +757,12 @@ static bool remap_hair_emitter(Depsgraph *depsgraph,
|
||||
|
||||
if (mesh->totface_legacy != 0) {
|
||||
mface = static_cast<const MFace *>(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<const blender::int2 *>(
|
||||
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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<CurvesBrush3D> 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);
|
||||
|
||||
@@ -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<float2> 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. */
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<int> 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;
|
||||
|
||||
@@ -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<blender::float3> 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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1172,7 +1172,6 @@ static bool surfacedeformBind(Object *ob,
|
||||
Mesh *target,
|
||||
Mesh *mesh)
|
||||
{
|
||||
BVHTreeFromMesh treeData = {nullptr};
|
||||
const blender::Span<blender::float3> positions = target->vert_positions();
|
||||
const blender::Span<blender::int2> 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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -99,15 +99,10 @@ static void raycast_to_mesh(const IndexMask &mask,
|
||||
const MutableSpan<float3> r_hit_normals,
|
||||
const MutableSpan<float> 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];
|
||||
|
||||
@@ -112,10 +112,8 @@ static void get_closest_mesh_points(const Mesh &mesh,
|
||||
const MutableSpan<float3> 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<float3> 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<float3> 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,
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user