Fix #107185: Edit mode or existing attribute break rest position

After e45ed69349 we need to remove the existing attribute
when adding the rest position before evaluating modifiers. Also, adding
the rest position attribute was completely skipped in edit mode.

Pull Request: https://projects.blender.org/blender/blender/pulls/107190
This commit is contained in:
Hans Goudey
2023-04-20 20:18:02 +02:00
committed by Hans Goudey
parent 2f4a8ecf18
commit 82ca3d3604

View File

@@ -569,6 +569,27 @@ static Mesh *modifier_modify_mesh_and_geometry_set(ModifierData *md,
return mesh_output;
}
static void set_rest_position(Mesh &mesh)
{
using namespace blender;
using namespace blender::bke;
MutableAttributeAccessor attributes = mesh.attributes_for_write();
const AttributeReader positions = attributes.lookup<float3>("position");
attributes.remove("rest_position");
if (positions) {
if (positions.sharing_info && positions.varray.is_span()) {
attributes.add<float3>("rest_position",
ATTR_DOMAIN_POINT,
AttributeInitShared(positions.varray.get_internal_span().data(),
*positions.sharing_info));
}
else {
attributes.add<float3>(
"rest_position", ATTR_DOMAIN_POINT, AttributeInitVArray(positions.varray));
}
}
}
static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
const Scene *scene,
Object *ob,
@@ -657,20 +678,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
mesh_final = BKE_mesh_copy_for_eval(mesh_input);
ASSERT_IS_VALID_MESH(mesh_final);
}
MutableAttributeAccessor attributes = mesh_final->attributes_for_write();
const AttributeReader positions = attributes.lookup<float3>("position");
if (positions) {
if (positions.sharing_info && positions.varray.is_span()) {
attributes.add<float3>("rest_position",
ATTR_DOMAIN_POINT,
AttributeInitShared(positions.varray.get_internal_span().data(),
*positions.sharing_info));
}
else {
attributes.add<float3>(
"rest_position", ATTR_DOMAIN_POINT, AttributeInitVArray(positions.varray));
}
}
set_rest_position(*mesh_final);
}
/* Apply all leading deform modifiers. */
@@ -1194,6 +1202,14 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
/* Clear errors before evaluation. */
BKE_modifiers_clear_errors(ob);
if (ob->modifier_flag & OB_MODIFIER_FLAG_ADD_REST_POSITION) {
if (mesh_final == nullptr) {
mesh_final = BKE_mesh_from_bmesh_for_eval_nomain(em_input->bm, nullptr, mesh_input);
ASSERT_IS_VALID_MESH(mesh_final);
}
set_rest_position(*mesh_final);
}
for (int i = 0; md; i++, md = md->next, md_datamask = md_datamask->next) {
const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type);