Mesh: Add an explicit "positions changed" function

We store various lazily calculated caches on meshes, some of which
depend on the vertex positions staying the same. The current API to
invalidate these caches is a bit confusing. With an explicit set of
functions modeled after the functions in `BKE_node_tree_update.h`,
it becomes clear which function to call. This may become more
important if more lazy caches are added in the future.

Differential Revision: https://developer.blender.org/D14760
This commit is contained in:
Hans Goudey 2022-06-23 12:00:25 -05:00
parent 3e5a4d1412
commit 54182e4925
13 changed files with 57 additions and 24 deletions

View File

@ -52,6 +52,18 @@ extern "C" {
# define BKE_MESH_OMP_LIMIT 10000
#endif
/* mesh_runtime.cc */
/**
* Call after changing vertex positions to tag lazily calculated caches for recomputation.
*/
void BKE_mesh_tag_coords_changed(struct Mesh *mesh);
/**
* Call after moving every mesh vertex by the same translation.
*/
void BKE_mesh_tag_coords_changed_uniformly(struct Mesh *mesh);
/* *** mesh.c *** */
struct BMesh *BKE_mesh_to_bmesh_ex(const struct Mesh *me,

View File

@ -1171,7 +1171,7 @@ static Mesh *cloth_make_rest_mesh(ClothModifierData *clmd, Mesh *mesh)
for (unsigned i = 0; i < mesh->totvert; i++, verts++) {
copy_v3_v3(mvert[i].co, verts->xrest);
}
BKE_mesh_normals_tag_dirty(new_mesh);
BKE_mesh_tag_coords_changed(new_mesh);
return new_mesh;
}

View File

@ -2024,13 +2024,13 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object *
settings.use_threading = (sData->total_points > 1000);
BLI_task_parallel_range(
0, sData->total_points, &data, dynamic_paint_apply_surface_wave_cb, &settings);
BKE_mesh_normals_tag_dirty(result);
BKE_mesh_tag_coords_changed(result);
}
/* displace */
if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) {
dynamicPaint_applySurfaceDisplace(surface, result);
BKE_mesh_normals_tag_dirty(result);
BKE_mesh_tag_coords_changed(result);
}
}
}

View File

@ -864,11 +864,11 @@ static void set_vertex_position(MVert &vert, float3 position)
copy_v3_v3(vert.co, position);
}
static void tag_normals_dirty_when_writing_position(GeometryComponent &component)
static void tag_component_positions_changed(GeometryComponent &component)
{
Mesh *mesh = get_mesh_from_component_for_write(component);
if (mesh != nullptr) {
BKE_mesh_normals_tag_dirty(mesh);
BKE_mesh_tag_coords_changed(mesh);
}
}
@ -1213,7 +1213,7 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
point_access,
make_derived_read_attribute<MVert, float3, get_vertex_position>,
make_derived_write_attribute<MVert, float3, get_vertex_position, set_vertex_position>,
tag_normals_dirty_when_writing_position);
tag_component_positions_changed);
static NormalAttributeProvider normal;

View File

@ -1684,7 +1684,7 @@ void BKE_mesh_transform(Mesh *me, const float mat[4][4], bool do_keys)
mul_m3_v3(m3, *lnors);
}
}
BKE_mesh_normals_tag_dirty(me);
BKE_mesh_tag_coords_changed(me);
}
void BKE_mesh_translate(Mesh *me, const float offset[3], const bool do_keys)
@ -1706,6 +1706,7 @@ void BKE_mesh_translate(Mesh *me, const float offset[3], const bool do_keys)
}
}
}
BKE_mesh_tag_coords_changed_uniformly(me);
}
void BKE_mesh_tessface_ensure(Mesh *mesh)
@ -1904,7 +1905,7 @@ void BKE_mesh_vert_coords_apply(Mesh *mesh, const float (*vert_coords)[3])
for (int i = 0; i < mesh->totvert; i++, mv++) {
copy_v3_v3(mv->co, vert_coords[i]);
}
BKE_mesh_normals_tag_dirty(mesh);
BKE_mesh_tag_coords_changed(mesh);
}
void BKE_mesh_vert_coords_apply_with_mat4(Mesh *mesh,
@ -1918,7 +1919,7 @@ void BKE_mesh_vert_coords_apply_with_mat4(Mesh *mesh,
for (int i = 0; i < mesh->totvert; i++, mv++) {
mul_v3_m4v3(mv->co, mat, vert_coords[i]);
}
BKE_mesh_normals_tag_dirty(mesh);
BKE_mesh_tag_coords_changed(mesh);
}
void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spacearr)

View File

@ -244,11 +244,8 @@ bool BKE_mesh_runtime_clear_edit_data(Mesh *mesh)
void BKE_mesh_runtime_clear_geometry(Mesh *mesh)
{
if (mesh->runtime.bvh_cache) {
bvhcache_free(mesh->runtime.bvh_cache);
mesh->runtime.bvh_cache = nullptr;
}
MEM_SAFE_FREE(mesh->runtime.looptris.array);
BKE_mesh_tag_coords_changed(mesh);
/* TODO(sergey): Does this really belong here? */
if (mesh->runtime.subdiv_ccg != nullptr) {
BKE_subdiv_ccg_destroy(mesh->runtime.subdiv_ccg);
@ -259,6 +256,24 @@ void BKE_mesh_runtime_clear_geometry(Mesh *mesh)
MEM_SAFE_FREE(mesh->runtime.subsurf_face_dot_tags);
}
void BKE_mesh_tag_coords_changed(Mesh *mesh)
{
BKE_mesh_normals_tag_dirty(mesh);
MEM_SAFE_FREE(mesh->runtime.looptris.array);
if (mesh->runtime.bvh_cache) {
bvhcache_free(mesh->runtime.bvh_cache);
mesh->runtime.bvh_cache = nullptr;
}
}
void BKE_mesh_tag_coords_changed_uniformly(Mesh *mesh)
{
BKE_mesh_tag_coords_changed(mesh);
/* The normals didn't change, since all vertices moved by the same amount. */
BKE_mesh_poly_normals_clear_dirty(mesh);
BKE_mesh_vertex_normals_clear_dirty(mesh);
}
/** \} */
/* -------------------------------------------------------------------- */

View File

@ -156,7 +156,7 @@ void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape
/* Vertices were moved around, need to update normals after all the vertices are updated
* Probably this is possible to do in the loop above, but this is rather tricky because
* we don't know all needed vertices' coordinates there yet. */
BKE_mesh_normals_tag_dirty(base_mesh);
BKE_mesh_tag_coords_changed(base_mesh);
}
void multires_reshape_apply_base_refine_from_base(MultiresReshapeContext *reshape_context)

View File

@ -3116,7 +3116,7 @@ void SCULPT_vertcos_to_key(Object *ob, KeyBlock *kb, const float (*vertCos)[3])
for (a = 0; a < me->totvert; a++, mvert++) {
copy_v3_v3(mvert->co, vertCos[a]);
}
BKE_mesh_normals_tag_dirty(me);
BKE_mesh_tag_coords_changed(me);
}
/* Apply new coords on active key block, no need to re-allocate kb->data here! */

View File

@ -855,7 +855,7 @@ static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase
if (tag_update) {
Mesh *mesh = ob->data;
BKE_mesh_normals_tag_dirty(mesh);
BKE_mesh_tag_coords_changed(mesh);
BKE_sculptsession_free_deformMats(ss);
}

View File

@ -295,6 +295,13 @@ static void rna_Mesh_update_facemask(Main *bmain, Scene *scene, PointerRNA *ptr)
rna_Mesh_update_draw(bmain, scene, ptr);
}
static void rna_Mesh_update_positions_tag(Main *bmain, Scene *scene, PointerRNA *ptr)
{
Mesh *mesh = (Mesh *)ptr->data;
BKE_mesh_tag_coords_changed(mesh);
rna_Mesh_update_data_legacy_deg_tag_all(bmain, scene, ptr);
}
/** \} */
/* -------------------------------------------------------------------- */
@ -1727,7 +1734,7 @@ static void rna_def_mvert(BlenderRNA *brna)
prop = RNA_def_property(srna, "co", PROP_FLOAT, PROP_TRANSLATION);
RNA_def_property_ui_text(prop, "Location", "");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data_legacy_deg_tag_all");
RNA_def_property_update(prop, 0, "rna_Mesh_update_positions_tag");
prop = RNA_def_property(srna, "normal", PROP_FLOAT, PROP_DIRECTION);
RNA_def_property_array(prop, 3);

View File

@ -146,7 +146,7 @@ static Mesh *get_quick_mesh(
mul_m4_v3(omat, mv->co);
}
BKE_mesh_normals_tag_dirty(result);
BKE_mesh_tag_coords_changed(result);
}
break;

View File

@ -469,7 +469,7 @@ static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mes
}
}
BKE_mesh_normals_tag_dirty(mesh);
BKE_mesh_tag_coords_changed(mesh);
if (allocated_ocean) {
BKE_ocean_free(omd->ocean);

View File

@ -183,8 +183,7 @@ static void scale_vertex_islands_uniformly(Mesh &mesh,
}
});
/* Positions have changed, so the normals will have to be recomputed. */
BKE_mesh_normals_tag_dirty(&mesh);
BKE_mesh_tag_coords_changed(&mesh);
}
static void scale_vertex_islands_on_axis(Mesh &mesh,
@ -228,8 +227,7 @@ static void scale_vertex_islands_on_axis(Mesh &mesh,
}
});
/* Positions have changed, so the normals will have to be recomputed. */
BKE_mesh_normals_tag_dirty(&mesh);
BKE_mesh_tag_coords_changed(&mesh);
}
static Vector<ElementIsland> prepare_face_islands(const Mesh &mesh, const IndexMask face_selection)