Cleanup: Move mesh update tags to DNA struct

This is similar to other update tags and update tags for other geometry types.
This commit is contained in:
Hans Goudey
2023-12-12 15:38:42 -05:00
parent 6e0037e54d
commit 1d0179adbb
37 changed files with 102 additions and 120 deletions
-33
View File
@@ -50,39 +50,6 @@ typedef enum eMeshBatchDirtyMode {
BKE_MESH_BATCH_DIRTY_UVEDIT_SELECT,
} eMeshBatchDirtyMode;
/* mesh_runtime.cc */
/**
* Call after changing vertex positions to tag lazily calculated caches for recomputation.
*/
void BKE_mesh_tag_positions_changed(struct Mesh *mesh);
/**
* The same as #BKE_mesh_tag_positions_changed but doesn't tag normals dirty, instead expecting
* them to be updated separately.
*/
void BKE_mesh_tag_positions_changed_no_normals(struct Mesh *mesh);
/**
* Call after moving every mesh vertex by the same translation.
*/
void BKE_mesh_tag_positions_changed_uniformly(struct Mesh *mesh);
void BKE_mesh_tag_topology_changed(struct Mesh *mesh);
/**
* Call when new edges and vertices have been created but positions and faces haven't changed.
*/
void BKE_mesh_tag_edges_split(struct Mesh *mesh);
/** Call when changing "sharp_face" or "sharp_edge" data. */
void BKE_mesh_tag_sharpness_changed(struct Mesh *mesh);
/**
* Call when face vertex order has changed but positions and faces haven't changed
*/
void BKE_mesh_tag_face_winding_changed(struct Mesh *mesh);
/* `mesh.cc` */
struct BMesh *BKE_mesh_to_bmesh_ex(const struct Mesh *mesh,
@@ -31,7 +31,7 @@ void BKE_mesh_runtime_ensure_edit_data(Mesh *mesh);
* directly or making other large changes to topology. It does not need to be called on new meshes.
*
* For "smaller" changes to meshes like updating positions, consider calling a more specific update
* function like #BKE_mesh_tag_positions_changed.
* function like #Mesh::tag_positions_changed().
*
* Also note that some derived caches like #CD_TANGENT are stored directly in #CustomData.
*/
@@ -393,7 +393,7 @@ static Mesh *create_orco_mesh(Object *ob, Mesh *mesh, BMEditMesh *em, int layer)
if (orco) {
orco_mesh->vert_positions_for_write().copy_from(
{reinterpret_cast<const float3 *>(orco), orco_mesh->totvert});
BKE_mesh_tag_positions_changed(orco_mesh);
orco_mesh->tag_positions_changed();
if (free) {
MEM_freeN(orco);
}
@@ -1161,7 +1161,7 @@ static void editbmesh_calc_modifiers(Depsgraph *depsgraph,
else {
BKE_mesh_wrapper_ensure_mdata(mesh_final);
BKE_modifier_deform_verts(md, &mectx, mesh_final, mesh_final->vert_positions_for_write());
BKE_mesh_tag_positions_changed(mesh_final);
mesh_final->tag_positions_changed();
}
}
else {
+1 -1
View File
@@ -1173,7 +1173,7 @@ static Mesh *cloth_make_rest_mesh(ClothModifierData *clmd, Mesh *mesh)
for (const int i : positions.index_range()) {
positions[i] = verts[i].xrest;
}
BKE_mesh_tag_positions_changed(new_mesh);
new_mesh->tag_positions_changed();
return new_mesh;
}
+1 -1
View File
@@ -744,7 +744,7 @@ static blender::bke::GeometrySet curve_calc_modifiers_post(Depsgraph *depsgraph,
if (mti->type == ModifierTypeType::OnlyDeform) {
mti->deform_verts(md, &mectx_deform, mesh, mesh->vert_positions_for_write());
BKE_mesh_tag_positions_changed(mesh);
mesh->tag_positions_changed();
}
else {
Mesh *output_mesh = mti->modify_mesh(md, &mectx_apply, mesh);
@@ -2042,13 +2042,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_tag_positions_changed(result);
result->tag_positions_changed();
}
/* displace */
if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) {
dynamicPaint_applySurfaceDisplace(surface, result);
BKE_mesh_tag_positions_changed(result);
result->tag_positions_changed();
}
}
}
+1 -1
View File
@@ -2127,7 +2127,7 @@ static void emit_from_mesh(
/* Calculate emission map bounds. */
bb_boundInsert(bb, positions[i]);
}
BKE_mesh_tag_positions_changed(mesh);
mesh->tag_positions_changed();
mul_m4_v3(flow_ob->object_to_world, flow_center);
manta_pos_to_cell(fds, flow_center);
@@ -854,14 +854,14 @@ static void tag_component_positions_changed(void *owner)
{
Mesh *mesh = static_cast<Mesh *>(owner);
if (mesh != nullptr) {
BKE_mesh_tag_positions_changed(mesh);
mesh->tag_positions_changed();
}
}
static void tag_component_sharpness_changed(void *owner)
{
if (Mesh *mesh = static_cast<Mesh *>(owner)) {
BKE_mesh_tag_sharpness_changed(mesh);
mesh->tag_sharpness_changed();
}
}
+1 -1
View File
@@ -1606,7 +1606,7 @@ float *BKE_key_evaluate_object_ex(
const int totvert = min_ii(tot, mesh->totvert);
mesh->vert_positions_for_write().take_front(totvert).copy_from(
{reinterpret_cast<const blender::float3 *>(out), totvert});
BKE_mesh_tag_positions_changed(mesh);
mesh->tag_positions_changed();
break;
}
case ID_LT: {
+1 -1
View File
@@ -652,7 +652,7 @@ void BKE_mball_data_update(Depsgraph *depsgraph, Scene *scene, Object *ob)
0,
nullptr,
1.0f);
BKE_mesh_tag_positions_changed(mesh);
mesh->tag_positions_changed();
}
ob->runtime->geometry_set_eval = new GeometrySet(GeometrySet::from_mesh(mesh));
+2 -2
View File
@@ -1125,7 +1125,7 @@ void BKE_mesh_transform(Mesh *mesh, const float mat[4][4], bool do_keys)
}
}
BKE_mesh_tag_positions_changed(mesh);
mesh->tag_positions_changed();
}
static void translate_positions(MutableSpan<float3> positions, const float3 &translation)
@@ -1157,7 +1157,7 @@ void BKE_mesh_translate(Mesh *mesh, const float offset[3], const bool do_keys)
}
}
BKE_mesh_tag_positions_changed_uniformly(mesh);
mesh->tag_positions_changed_uniformly();
if (bounds) {
bounds->min += offset;
@@ -92,7 +92,7 @@ void mesh_flip_faces(Mesh &mesh, const IndexMask &selection)
return true;
});
BKE_mesh_tag_face_winding_changed(&mesh);
mesh.tag_face_winding_changed();
}
} // namespace blender::bke
@@ -245,7 +245,7 @@ void BKE_mesh_calc_edges_legacy(Mesh *mesh)
&mesh->edge_data, CD_MEDGE, edges, totedge, nullptr);
mesh->totedge = totedge;
BKE_mesh_tag_topology_changed(mesh);
mesh->tag_topology_changed();
BKE_mesh_strip_loose_faces(mesh);
}
@@ -318,73 +318,73 @@ void BKE_mesh_runtime_clear_geometry(Mesh *mesh)
mesh->flag &= ~ME_NO_OVERLAPPING_TOPOLOGY;
}
void BKE_mesh_tag_edges_split(Mesh *mesh)
void Mesh::tag_edges_split()
{
/* Triangulation didn't change because vertex positions and loop vertex indices didn't change. */
free_bvh_cache(*mesh->runtime);
mesh->runtime->vert_normals_cache.tag_dirty();
mesh->runtime->subdiv_ccg.reset();
mesh->runtime->vert_to_face_offset_cache.tag_dirty();
mesh->runtime->vert_to_face_map_cache.tag_dirty();
mesh->runtime->vert_to_corner_map_cache.tag_dirty();
if (mesh->runtime->loose_edges_cache.is_cached() &&
mesh->runtime->loose_edges_cache.data().count != 0)
free_bvh_cache(*this->runtime);
this->runtime->vert_normals_cache.tag_dirty();
this->runtime->subdiv_ccg.reset();
this->runtime->vert_to_face_offset_cache.tag_dirty();
this->runtime->vert_to_face_map_cache.tag_dirty();
this->runtime->vert_to_corner_map_cache.tag_dirty();
if (this->runtime->loose_edges_cache.is_cached() &&
this->runtime->loose_edges_cache.data().count != 0)
{
mesh->runtime->loose_edges_cache.tag_dirty();
this->runtime->loose_edges_cache.tag_dirty();
}
if (mesh->runtime->loose_verts_cache.is_cached() &&
mesh->runtime->loose_verts_cache.data().count != 0)
if (this->runtime->loose_verts_cache.is_cached() &&
this->runtime->loose_verts_cache.data().count != 0)
{
mesh->runtime->loose_verts_cache.tag_dirty();
this->runtime->loose_verts_cache.tag_dirty();
}
if (mesh->runtime->verts_no_face_cache.is_cached() &&
mesh->runtime->verts_no_face_cache.data().count != 0)
if (this->runtime->verts_no_face_cache.is_cached() &&
this->runtime->verts_no_face_cache.data().count != 0)
{
mesh->runtime->verts_no_face_cache.tag_dirty();
this->runtime->verts_no_face_cache.tag_dirty();
}
mesh->runtime->subsurf_face_dot_tags.clear_and_shrink();
mesh->runtime->subsurf_optimal_display_edges.clear_and_shrink();
mesh->runtime->shrinkwrap_data.reset();
this->runtime->subsurf_face_dot_tags.clear_and_shrink();
this->runtime->subsurf_optimal_display_edges.clear_and_shrink();
this->runtime->shrinkwrap_data.reset();
}
void BKE_mesh_tag_sharpness_changed(Mesh *mesh)
void Mesh::tag_sharpness_changed()
{
mesh->runtime->corner_normals_cache.tag_dirty();
this->runtime->corner_normals_cache.tag_dirty();
}
void BKE_mesh_tag_face_winding_changed(Mesh *mesh)
void Mesh::tag_face_winding_changed()
{
mesh->runtime->vert_normals_cache.tag_dirty();
mesh->runtime->face_normals_cache.tag_dirty();
mesh->runtime->corner_normals_cache.tag_dirty();
mesh->runtime->vert_to_corner_map_cache.tag_dirty();
this->runtime->vert_normals_cache.tag_dirty();
this->runtime->face_normals_cache.tag_dirty();
this->runtime->corner_normals_cache.tag_dirty();
this->runtime->vert_to_corner_map_cache.tag_dirty();
}
void BKE_mesh_tag_positions_changed(Mesh *mesh)
void Mesh::tag_positions_changed()
{
mesh->runtime->vert_normals_cache.tag_dirty();
mesh->runtime->face_normals_cache.tag_dirty();
mesh->runtime->corner_normals_cache.tag_dirty();
BKE_mesh_tag_positions_changed_no_normals(mesh);
this->runtime->vert_normals_cache.tag_dirty();
this->runtime->face_normals_cache.tag_dirty();
this->runtime->corner_normals_cache.tag_dirty();
this->tag_positions_changed_no_normals();
}
void BKE_mesh_tag_positions_changed_no_normals(Mesh *mesh)
void Mesh::tag_positions_changed_no_normals()
{
free_bvh_cache(*mesh->runtime);
mesh->runtime->looptris_cache.tag_dirty();
mesh->runtime->bounds_cache.tag_dirty();
free_bvh_cache(*this->runtime);
this->runtime->looptris_cache.tag_dirty();
this->runtime->bounds_cache.tag_dirty();
}
void BKE_mesh_tag_positions_changed_uniformly(Mesh *mesh)
void Mesh::tag_positions_changed_uniformly()
{
/* The normals and triangulation didn't change, since all verts moved by the same amount. */
free_bvh_cache(*mesh->runtime);
mesh->runtime->bounds_cache.tag_dirty();
free_bvh_cache(*this->runtime);
this->runtime->bounds_cache.tag_dirty();
}
void BKE_mesh_tag_topology_changed(Mesh *mesh)
void Mesh::tag_topology_changed()
{
BKE_mesh_runtime_clear_geometry(mesh);
BKE_mesh_runtime_clear_geometry(this);
}
/** \} */
@@ -193,7 +193,7 @@ void BKE_mesh_wrapper_tag_positions_changed(Mesh *mesh)
break;
case ME_WRAPPER_TYPE_MDATA:
case ME_WRAPPER_TYPE_SUBD:
BKE_mesh_tag_positions_changed(mesh);
mesh->tag_positions_changed();
break;
}
}
+1 -1
View File
@@ -943,7 +943,7 @@ void BKE_modifier_deform_verts(ModifierData *md,
}
mti->deform_verts(md, ctx, mesh, positions);
if (mesh) {
BKE_mesh_tag_positions_changed(mesh);
mesh->tag_positions_changed();
}
}
@@ -142,7 +142,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_tag_positions_changed(base_mesh);
base_mesh->tag_positions_changed();
}
void multires_reshape_apply_base_refine_from_base(MultiresReshapeContext *reshape_context)
@@ -3534,7 +3534,7 @@ static void do_hair_dynamics(ParticleSimulationData *sim)
sim->ob,
psys->hair_in_mesh,
reinterpret_cast<float(*)[3]>(psys->hair_out_mesh->vert_positions_for_write().data()));
BKE_mesh_tag_positions_changed(psys->hair_out_mesh);
psys->hair_out_mesh->tag_positions_changed();
/* restore cloth effector weights */
psys->clmd->sim_parms->effector_weights = clmd_effweights;
@@ -1541,7 +1541,7 @@ void BKE_shrinkwrap_mesh_nearest_surface_deform(Depsgraph *depsgraph,
-1,
reinterpret_cast<float(*)[3]>(src_me->vert_positions_for_write().data()),
src_me->totvert);
BKE_mesh_tag_positions_changed(src_me);
src_me->tag_positions_changed();
}
void BKE_shrinkwrap_remesh_target_project(Mesh *src_me, Mesh *target_me, Object *ob_target)
@@ -1578,5 +1578,5 @@ void BKE_shrinkwrap_remesh_target_project(Mesh *src_me, Mesh *target_me, Object
BKE_shrinkwrap_free_tree(&tree);
}
BKE_mesh_tag_positions_changed(src_me);
src_me->tag_positions_changed();
}
@@ -552,7 +552,7 @@ void ED_object_data_xform_by_mat4(XFormObjectData *xod_base, const float mat[4][
for (const int i : positions.index_range()) {
mul_v3_m4v3(positions[i], mat, xod->elem_array[i]);
}
BKE_mesh_tag_positions_changed(mesh);
mesh->tag_positions_changed();
}
if (key != nullptr) {
@@ -661,7 +661,7 @@ void ED_object_data_xform_restore(XFormObjectData *xod_base)
else {
mesh->vert_positions_for_write().copy_from(
{reinterpret_cast<const blender::float3 *>(xod->elem_array), mesh->totvert});
BKE_mesh_tag_positions_changed(mesh);
mesh->tag_positions_changed();
}
if ((key != nullptr) && (xod->key_data != nullptr)) {
@@ -812,7 +812,7 @@ static Mesh *create_applied_mesh_for_modifier(Depsgraph *depsgraph,
if (mti->type == ModifierTypeType::OnlyDeform) {
result = mesh_temp;
mti->deform_verts(md_eval, &mectx, result, deformedVerts);
BKE_mesh_tag_positions_changed(result);
result->tag_positions_changed();
if (build_shapekey_layers) {
add_shapekey_layers(*result, *mesh);
@@ -3176,7 +3176,7 @@ void SCULPT_vertcos_to_key(Object *ob, KeyBlock *kb, const Span<float3> vertCos)
/* Modifying of basis key should update mesh. */
if (kb == mesh->key->refkey) {
mesh->vert_positions_for_write().copy_from(vertCos);
BKE_mesh_tag_positions_changed(mesh);
mesh->tag_positions_changed();
}
/* Apply new coords on active key block, no need to re-allocate kb->data here! */
@@ -5263,7 +5263,7 @@ void SCULPT_flush_update_step(bContext *C, SculptUpdateType update_flags)
* the mesh's bounds eagerly here since they are trivial to access from the PBVH. Updating
* the object's evaluated geometry bounding box is necessary because sculpt strokes don't
* cause an object reevaluation. */
BKE_mesh_tag_positions_changed_no_normals(mesh);
mesh->tag_positions_changed_no_normals();
mesh->bounds_set_eager(BKE_pbvh_bounding_box(ob->sculpt->pbvh));
if (ob->runtime->bounds_eval) {
ob->runtime->bounds_eval = mesh->bounds_min_max();
@@ -1072,7 +1072,7 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, UndoSculpt &usculpt)
if (tag_update) {
Mesh *mesh = static_cast<Mesh *>(ob->data);
if (changed_position) {
BKE_mesh_tag_positions_changed(mesh);
mesh->tag_positions_changed();
BKE_sculptsession_free_deformMats(ss);
}
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
@@ -595,7 +595,7 @@ void split_edges(Mesh &mesh,
const Array<int> vert_map = offsets_to_map(affected_verts, new_verts_by_affected_vert);
propagate_vert_attributes(mesh, vert_map);
BKE_mesh_tag_edges_split(&mesh);
mesh.tag_edges_split();
debug_randomize_vert_order(&mesh);
debug_randomize_edge_order(&mesh);
+3 -3
View File
@@ -104,7 +104,7 @@ void debug_randomize_vert_order(Mesh *mesh)
v = new_by_old_map[v];
}
BKE_mesh_tag_topology_changed(mesh);
mesh->tag_topology_changed();
}
void debug_randomize_edge_order(Mesh *mesh)
@@ -122,7 +122,7 @@ void debug_randomize_edge_order(Mesh *mesh)
e = new_by_old_map[e];
}
BKE_mesh_tag_topology_changed(mesh);
mesh->tag_topology_changed();
}
static Array<int> make_new_offset_indices(const OffsetIndices<int> old_offsets,
@@ -177,7 +177,7 @@ void debug_randomize_face_order(Mesh *mesh)
mesh->face_offsets_for_write().copy_from(new_face_offsets);
BKE_mesh_tag_topology_changed(mesh);
mesh->tag_topology_changed();
}
void debug_randomize_point_order(PointCloud *pointcloud)
@@ -156,7 +156,7 @@ static void read_mverts(CDStreamConfig &config, const AbcMeshData &mesh_data)
const double weight = mesh_data.interpolation_settings->weight;
read_mverts_interp(vert_positions, positions, mesh_data.ceil_positions, weight);
BKE_mesh_tag_positions_changed(config.mesh);
config.mesh->tag_positions_changed();
return;
}
@@ -171,7 +171,7 @@ void read_mverts(Mesh &mesh, const P3fArraySamplePtr positions, const N3fArraySa
copy_zup_from_yup(vert_positions[i], pos_in.getValue());
}
BKE_mesh_tag_positions_changed(&mesh);
mesh.tag_positions_changed();
if (normals) {
Vector<float3> vert_normals(mesh.totvert);
@@ -853,7 +853,7 @@ void USDMeshReader::read_mesh_sample(ImportSettings *settings,
for (int i = 0; i < positions_.size(); i++) {
vert_positions[i] = {positions_[i][0], positions_[i][1], positions_[i][2]};
}
BKE_mesh_tag_positions_changed(mesh);
mesh->tag_positions_changed();
read_vertex_creases(mesh, motionSampleTime);
}
+15
View File
@@ -395,6 +395,21 @@ typedef struct Mesh {
* using #face_normals() or #vert_normals() when possible (see #normals_domain()).
*/
blender::Span<blender::float3> corner_normals() const;
/** Call after changing vertex positions to tag lazily calculated caches for recomputation. */
void tag_positions_changed();
/** Call after moving every mesh vertex by the same translation. */
void tag_positions_changed_uniformly();
/** Like #tag_positions_changed but doesn't tag normals; they must be updated separately. */
void tag_positions_changed_no_normals();
/** Call when changing "sharp_face" or "sharp_edge" data. */
void tag_sharpness_changed();
/** Call when face vertex order has changed but positions and faces haven't changed. */
void tag_face_winding_changed();
/** Call when new edges and vertices have been created but vertices and faces haven't changed. */
void tag_edges_split();
/** Call for topology updates not described by other update tags. */
void tag_topology_changed();
#endif
} Mesh;
+3 -3
View File
@@ -266,7 +266,7 @@ static void rna_Mesh_update_facemask(Main *bmain, Scene *scene, PointerRNA *ptr)
static void rna_Mesh_update_positions_tag(Main *bmain, Scene *scene, PointerRNA *ptr)
{
Mesh *mesh = rna_mesh(ptr);
BKE_mesh_tag_positions_changed(mesh);
mesh->tag_positions_changed();
rna_Mesh_update_data_legacy_deg_tag_all(bmain, scene, ptr);
}
@@ -596,7 +596,7 @@ static void rna_MeshPolygon_use_smooth_set(PointerRNA *ptr, bool value)
const int index = rna_MeshPolygon_index_get(ptr);
if (value == sharp_faces[index]) {
sharp_faces[index] = !value;
BKE_mesh_tag_sharpness_changed(mesh);
mesh->tag_sharpness_changed();
}
}
@@ -1344,7 +1344,7 @@ static void rna_MeshEdge_use_edge_sharp_set(PointerRNA *ptr, bool value)
const int index = rna_MeshEdge_index_get(ptr);
if (value != sharp_edge[index]) {
sharp_edge[index] = value;
BKE_mesh_tag_sharpness_changed(mesh);
mesh->tag_sharpness_changed();
}
}
@@ -151,7 +151,7 @@ static Mesh *get_quick_mesh(
mul_m4_v3(omat, positions[i]);
}
BKE_mesh_tag_positions_changed(result);
result->tag_positions_changed();
}
break;
+1 -1
View File
@@ -115,7 +115,7 @@ static void deform_verts(ModifierData *md,
}
mesh->vert_positions_for_write().copy_from(positions);
BKE_mesh_tag_positions_changed(mesh);
mesh->tag_positions_changed();
clothModifier_do(clmd,
ctx->depsgraph,
@@ -110,7 +110,7 @@ static void deform_verts(ModifierData *md,
int mvert_num = 0;
mesh->vert_positions_for_write().copy_from(positions);
BKE_mesh_tag_positions_changed(mesh);
mesh->tag_positions_changed();
current_time = DEG_get_ctime(ctx->depsgraph);
+1 -1
View File
@@ -453,7 +453,7 @@ static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mes
}
}
BKE_mesh_tag_positions_changed(mesh);
mesh->tag_positions_changed();
if (allocated_ocean) {
BKE_ocean_free(omd->ocean);
@@ -148,7 +148,7 @@ static void deform_verts(ModifierData *md,
/* make new mesh */
psmd->mesh_final = BKE_mesh_copy_for_eval(mesh);
psmd->mesh_final->vert_positions_for_write().copy_from(positions);
BKE_mesh_tag_positions_changed(psmd->mesh_final);
psmd->mesh_final->tag_positions_changed();
BKE_mesh_tessface_ensure(psmd->mesh_final);
@@ -119,7 +119,7 @@ static void deform_verts(ModifierData *md,
int init = 0;
surmd->runtime.mesh->vert_positions_for_write().copy_from(positions);
BKE_mesh_tag_positions_changed(surmd->runtime.mesh);
surmd->runtime.mesh->tag_positions_changed();
mesh_verts_num = surmd->runtime.mesh->totvert;
@@ -193,7 +193,7 @@ static void scale_vertex_islands_uniformly(Mesh &mesh,
}
});
BKE_mesh_tag_positions_changed(&mesh);
mesh.tag_positions_changed();
}
static void scale_vertex_islands_on_axis(Mesh &mesh,
@@ -239,7 +239,7 @@ static void scale_vertex_islands_on_axis(Mesh &mesh,
}
});
BKE_mesh_tag_positions_changed(&mesh);
mesh.tag_positions_changed();
}
static Vector<ElementIsland> prepare_face_islands(const Mesh &mesh,
@@ -63,7 +63,7 @@ static void transform_positions(MutableSpan<float3> positions, const float4x4 &m
static void transform_mesh(Mesh &mesh, const float4x4 &transform)
{
transform_positions(mesh.vert_positions_for_write(), transform);
BKE_mesh_tag_positions_changed(&mesh);
mesh.tag_positions_changed();
}
static void translate_pointcloud(PointCloud &pointcloud, const float3 translation)