Sculpt: Reuse existing mesh triangles cache in sculpt mode #123638
@ -94,6 +94,19 @@ struct LooseEdgeCache : public LooseGeomCache {};
|
||||
*/
|
||||
struct LooseVertCache : public LooseGeomCache {};
|
||||
|
||||
struct TrianglesCache {
|
||||
SharedCache<Array<int3>> data;
|
||||
bool frozen = false;
|
||||
bool dirty_while_frozen = false;
|
||||
|
||||
/** Delay applying dirty tags from #tag_dirty() until #unfreeze is called. */
|
||||
void freeze();
|
||||
/** Apply dirty tags from after #freeze, and make future dirty tags apply immediately. */
|
||||
void unfreeze();
|
||||
/** Call instead of `data.tag_dirty()`. */
|
||||
void tag_dirty();
|
||||
};
|
||||
|
||||
struct MeshRuntime {
|
||||
/**
|
||||
* "Evaluated" mesh owned by this mesh. Used for objects which don't have effective modifiers, so
|
||||
@ -141,7 +154,7 @@ struct MeshRuntime {
|
||||
void *batch_cache = nullptr;
|
||||
|
||||
/** Cache for derived triangulation of the mesh, accessed with #Mesh::corner_tris(). */
|
||||
SharedCache<Array<int3>> corner_tris_cache;
|
||||
TrianglesCache corner_tris_cache;
|
||||
/** Cache for triangle to original face index map, accessed with #Mesh::corner_tri_faces(). */
|
||||
SharedCache<Array<int>> corner_tri_faces_cache;
|
||||
|
||||
|
@ -226,9 +226,38 @@ void Mesh::tag_overlapping_none()
|
||||
this->flag |= ME_NO_OVERLAPPING_TOPOLOGY;
|
||||
}
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
void TrianglesCache::freeze()
|
||||
{
|
||||
this->frozen = true;
|
||||
this->dirty_while_frozen = false;
|
||||
}
|
||||
|
||||
void TrianglesCache::unfreeze()
|
||||
{
|
||||
this->frozen = false;
|
||||
if (this->dirty_while_frozen) {
|
||||
this->data.tag_dirty();
|
||||
}
|
||||
this->dirty_while_frozen = false;
|
||||
}
|
||||
|
||||
void TrianglesCache::tag_dirty()
|
||||
{
|
||||
if (this->frozen) {
|
||||
this->dirty_while_frozen = true;
|
||||
}
|
||||
else {
|
||||
this->data.tag_dirty();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::bke
|
||||
|
||||
blender::Span<blender::int3> Mesh::corner_tris() const
|
||||
{
|
||||
this->runtime->corner_tris_cache.ensure([&](blender::Array<blender::int3> &r_data) {
|
||||
this->runtime->corner_tris_cache.data.ensure([&](blender::Array<blender::int3> &r_data) {
|
||||
const Span<float3> positions = this->vert_positions();
|
||||
const blender::OffsetIndices faces = this->faces();
|
||||
const Span<int> corner_verts = this->corner_verts();
|
||||
@ -244,7 +273,7 @@ blender::Span<blender::int3> Mesh::corner_tris() const
|
||||
}
|
||||
});
|
||||
|
||||
return this->runtime->corner_tris_cache.data();
|
||||
return this->runtime->corner_tris_cache.data.data();
|
||||
}
|
||||
|
||||
blender::Span<int> Mesh::corner_tri_faces() const
|
||||
@ -296,7 +325,7 @@ void BKE_mesh_runtime_clear_geometry(Mesh *mesh)
|
||||
mesh->runtime->loose_edges_cache.tag_dirty();
|
||||
mesh->runtime->loose_verts_cache.tag_dirty();
|
||||
mesh->runtime->verts_no_face_cache.tag_dirty();
|
||||
mesh->runtime->corner_tris_cache.tag_dirty();
|
||||
mesh->runtime->corner_tris_cache.data.tag_dirty();
|
||||
mesh->runtime->corner_tri_faces_cache.tag_dirty();
|
||||
mesh->runtime->shrinkwrap_boundary_cache.tag_dirty();
|
||||
mesh->runtime->subsurf_face_dot_tags.clear_and_shrink();
|
||||
|
@ -654,14 +654,10 @@ std::unique_ptr<PBVH> build_mesh(Mesh *mesh)
|
||||
pbvh->header.type = PBVH_FACES;
|
||||
|
||||
const int totvert = mesh->verts_num;
|
||||
const int corner_tris_num = poly_to_tri_count(mesh->faces_num, mesh->corners_num);
|
||||
MutableSpan<float3> vert_positions = mesh->vert_positions_for_write();
|
||||
const OffsetIndices<int> faces = mesh->faces();
|
||||
const Span<int> corner_verts = mesh->corner_verts();
|
||||
HooglyBoogly marked this conversation as resolved
Outdated
|
||||
|
||||
pbvh->corner_tris.reinitialize(corner_tris_num);
|
||||
mesh::corner_tris_calc(vert_positions, faces, corner_verts, pbvh->corner_tris);
|
||||
const Span<int3> corner_tris = pbvh->corner_tris;
|
||||
const Span<int3> corner_tris = mesh->corner_tris();
|
||||
pbvh->corner_tris = corner_tris;
|
||||
|
||||
pbvh->mesh = mesh;
|
||||
|
||||
@ -681,7 +677,7 @@ std::unique_ptr<PBVH> build_mesh(Mesh *mesh)
|
||||
#endif
|
||||
|
||||
/* For each face, store the AABB and the AABB centroid */
|
||||
Array<Bounds<float3>> prim_bounds(corner_tris_num);
|
||||
Array<Bounds<float3>> prim_bounds(corner_tris.size());
|
||||
const Bounds<float3> cb = threading::parallel_reduce(
|
||||
corner_tris.index_range(),
|
||||
1024,
|
||||
@ -701,7 +697,7 @@ std::unique_ptr<PBVH> build_mesh(Mesh *mesh)
|
||||
},
|
||||
[](const Bounds<float3> &a, const Bounds<float3> &b) { return bounds::merge(a, b); });
|
||||
|
||||
if (corner_tris_num) {
|
||||
if (!corner_tris.is_empty()) {
|
||||
const AttributeAccessor attributes = mesh->attributes();
|
||||
const VArraySpan hide_poly = *attributes.lookup<bool>(".hide_poly", AttrDomain::Face);
|
||||
const VArraySpan material_index = *attributes.lookup<int>("material_index", AttrDomain::Face);
|
||||
@ -716,7 +712,7 @@ std::unique_ptr<PBVH> build_mesh(Mesh *mesh)
|
||||
vert_bitmap,
|
||||
&cb,
|
||||
prim_bounds,
|
||||
corner_tris_num);
|
||||
corner_tris.size());
|
||||
|
||||
#ifdef TEST_PBVH_FACE_SPLIT
|
||||
test_face_boundaries(pbvh, tri_faces);
|
||||
|
@ -154,8 +154,7 @@ struct PBVH {
|
||||
/** Only valid for polygon meshes. */
|
||||
blender::OffsetIndices<int> faces;
|
||||
blender::Span<int> corner_verts;
|
||||
/* Owned by the #PBVH, because after deformations they have to be recomputed. */
|
||||
blender::Array<blender::int3> corner_tris;
|
||||
blender::Span<blender::int3> corner_tris;
|
||||
|
||||
/* Grid Data */
|
||||
CCGKey gridkey;
|
||||
|
@ -355,6 +355,10 @@ void ED_object_sculptmode_enter_ex(Main &bmain,
|
||||
const int mode_flag = OB_MODE_SCULPT;
|
||||
Mesh *mesh = BKE_mesh_from_object(&ob);
|
||||
|
||||
/* Re-triangulating the mesh for position changes in sculpt mode isn't worth the performance
|
||||
* impact, so delay triangulation updates until the user exits sculpt mode. */
|
||||
mesh->runtime->corner_tris_cache.freeze();
|
||||
|
||||
/* Enter sculpt mode. */
|
||||
ob.mode |= mode_flag;
|
||||
|
||||
@ -450,6 +454,8 @@ void ED_object_sculptmode_exit_ex(Main &bmain, Depsgraph &depsgraph, Scene &scen
|
||||
const int mode_flag = OB_MODE_SCULPT;
|
||||
Mesh *mesh = BKE_mesh_from_object(&ob);
|
||||
|
||||
mesh->runtime->corner_tris_cache.unfreeze();
|
||||
|
||||
multires_flush_sculpt_updates(&ob);
|
||||
|
||||
/* Not needed for now. */
|
||||
|
Loading…
Reference in New Issue
Block a user
const OffsetIndices<int> faces = mesh->faces();
is now unused.