Mesh: Avoid copying positions in object mode modifier stack
Remove the use of a separate contiguous positions array now that they are stored that way in the first place. This allows removing the complexity of tracking whether it is allocated and deformed in the mesh modifier stack. Instead of deferring the creation of the final mesh until after the positions have been copied and deformed, create the final mesh first and then deform its positions. Since vertex and face normals are calculated lazily, we can rely on individual modifiers to calculate them as necessary and simplify the modifier stack. This was hard to change before because of the separate array of deformed positions. Differential Revision: https://developer.blender.org/D16971
This commit is contained in:
parent
a38d99e0b2
commit
d20f992322
Notes:
blender-bot
2023-10-17 10:35:30 +02:00
Referenced by issue #103789, Remove unnecessary mesh position copying Referenced by issue #106802, Regression: sculpt with shape keys looses deformation of previous stroke Referenced by issue #112448, Regression: Child hair particles set to "Interpolated" causes jittering when the based vertex changes position Referenced by pull request #113679, Fix #112448: Leading deform modifiers skip adding original coordinates Referenced by commit9b0188db03
, Fix #112448: Leading deform modifiers skip adding original coordinates Referenced by commitd7e501ce3b
, Fix #112448: Leading deform modifiers skip adding original coordinates
|
@ -661,23 +661,17 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
|
|||
GeometrySet **r_geometry_set)
|
||||
{
|
||||
using namespace blender::bke;
|
||||
/* Input and final mesh. Final mesh is only created the moment the first
|
||||
* constructive modifier is executed, or a deform modifier needs normals
|
||||
* or certain data layers. */
|
||||
/* Input mesh shouldn't be modified. */
|
||||
Mesh *mesh_input = (Mesh *)ob->data;
|
||||
/* The final mesh is the result of calculating all enabled modifiers. */
|
||||
Mesh *mesh_final = nullptr;
|
||||
/* The result of calculating all leading deform modifiers. */
|
||||
Mesh *mesh_deform = nullptr;
|
||||
/* This geometry set contains the non-mesh data that might be generated by modifiers. */
|
||||
GeometrySet geometry_set_final;
|
||||
|
||||
BLI_assert((mesh_input->id.tag & LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT) == 0);
|
||||
|
||||
/* TODO: Remove use of `deformed_verts` in mesh modifier stack
|
||||
* since mesh positions are now stored in a contiguous array. */
|
||||
float(*deformed_verts)[3] = nullptr;
|
||||
int num_deformed_verts = mesh_input->totvert;
|
||||
bool isPrevDeform = false;
|
||||
|
||||
/* Mesh with constructive modifiers but no deformation applied. Tracked
|
||||
* along with final mesh if undeformed / orco coordinates are requested
|
||||
* for texturing. */
|
||||
|
@ -761,20 +755,15 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
|
|||
|
||||
if (mti->type == eModifierTypeType_OnlyDeform && !sculpt_dyntopo) {
|
||||
blender::bke::ScopedModifierTimer modifier_timer{*md};
|
||||
if (!deformed_verts) {
|
||||
deformed_verts = BKE_mesh_vert_coords_alloc(mesh_input, &num_deformed_verts);
|
||||
if (!mesh_final) {
|
||||
mesh_final = BKE_mesh_copy_for_eval(mesh_input, true);
|
||||
ASSERT_IS_VALID_MESH(mesh_final);
|
||||
}
|
||||
else if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
|
||||
if (mesh_final == nullptr) {
|
||||
mesh_final = BKE_mesh_copy_for_eval(mesh_input, true);
|
||||
ASSERT_IS_VALID_MESH(mesh_final);
|
||||
}
|
||||
BKE_mesh_vert_coords_apply(mesh_final, deformed_verts);
|
||||
}
|
||||
|
||||
BKE_modifier_deform_verts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts);
|
||||
|
||||
isPrevDeform = true;
|
||||
BKE_modifier_deform_verts(md,
|
||||
&mectx,
|
||||
mesh_final,
|
||||
BKE_mesh_vert_positions_for_write(mesh_final),
|
||||
mesh_final->totvert);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
|
@ -786,10 +775,6 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
|
|||
* coordinates (like vertex paint). */
|
||||
if (r_deform) {
|
||||
mesh_deform = BKE_mesh_copy_for_eval(mesh_input, true);
|
||||
|
||||
if (deformed_verts) {
|
||||
BKE_mesh_vert_coords_apply(mesh_deform, deformed_verts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -858,36 +843,19 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
|
|||
}
|
||||
}
|
||||
|
||||
/* How to apply modifier depends on (a) what we already have as
|
||||
* a result of previous modifiers (could be a Mesh or just
|
||||
* deformed vertices) and (b) what type the modifier is. */
|
||||
if (mti->type == eModifierTypeType_OnlyDeform) {
|
||||
/* No existing verts to deform, need to build them. */
|
||||
if (!deformed_verts) {
|
||||
if (mesh_final) {
|
||||
/* Deforming a mesh, read the vertex locations
|
||||
* out of the mesh and deform them. Once done with this
|
||||
* run of deformers verts will be written back. */
|
||||
deformed_verts = BKE_mesh_vert_coords_alloc(mesh_final, &num_deformed_verts);
|
||||
}
|
||||
else {
|
||||
deformed_verts = BKE_mesh_vert_coords_alloc(mesh_input, &num_deformed_verts);
|
||||
}
|
||||
if (!mesh_final) {
|
||||
mesh_final = BKE_mesh_copy_for_eval(mesh_input, true);
|
||||
ASSERT_IS_VALID_MESH(mesh_final);
|
||||
}
|
||||
/* if this is not the last modifier in the stack then recalculate the normals
|
||||
* to avoid giving bogus normals to the next modifier see: T23673. */
|
||||
else if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
|
||||
if (mesh_final == nullptr) {
|
||||
mesh_final = BKE_mesh_copy_for_eval(mesh_input, true);
|
||||
ASSERT_IS_VALID_MESH(mesh_final);
|
||||
}
|
||||
BKE_mesh_vert_coords_apply(mesh_final, deformed_verts);
|
||||
}
|
||||
BKE_modifier_deform_verts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts);
|
||||
BKE_modifier_deform_verts(md,
|
||||
&mectx,
|
||||
mesh_final,
|
||||
BKE_mesh_vert_positions_for_write(mesh_final),
|
||||
mesh_final->totvert);
|
||||
}
|
||||
else {
|
||||
bool check_for_needs_mapping = false;
|
||||
/* apply vertex coordinates or build a Mesh as necessary */
|
||||
if (mesh_final != nullptr) {
|
||||
if (have_non_onlydeform_modifiers_appled == false) {
|
||||
/* If we only deformed, we won't have initialized #CD_ORIGINDEX.
|
||||
|
@ -901,10 +869,6 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
|
|||
check_for_needs_mapping = true;
|
||||
}
|
||||
|
||||
if (deformed_verts) {
|
||||
BKE_mesh_vert_coords_apply(mesh_final, deformed_verts);
|
||||
}
|
||||
|
||||
have_non_onlydeform_modifiers_appled = true;
|
||||
|
||||
/* determine which data layers are needed by following modifiers */
|
||||
|
@ -985,11 +949,6 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
|
|||
BKE_id_free(nullptr, mesh_final);
|
||||
}
|
||||
mesh_final = mesh_next;
|
||||
|
||||
if (deformed_verts) {
|
||||
MEM_freeN(deformed_verts);
|
||||
deformed_verts = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* create an orco mesh in parallel */
|
||||
|
@ -1060,8 +1019,6 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
|
|||
mesh_final->runtime->deformed_only = false;
|
||||
}
|
||||
|
||||
isPrevDeform = (mti->type == eModifierTypeType_OnlyDeform);
|
||||
|
||||
if (sculpt_mode && md->type == eModifierType_Multires) {
|
||||
multires_applied = true;
|
||||
}
|
||||
|
@ -1073,22 +1030,14 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
|
|||
BKE_modifier_free_temporary_data(md);
|
||||
}
|
||||
|
||||
/* Yay, we are done. If we have a Mesh and deformed vertices,
|
||||
* we need to apply these back onto the Mesh. If we have no
|
||||
* Mesh then we need to build one. */
|
||||
if (mesh_final == nullptr) {
|
||||
if (deformed_verts == nullptr && allow_shared_mesh) {
|
||||
if (allow_shared_mesh) {
|
||||
mesh_final = mesh_input;
|
||||
}
|
||||
else {
|
||||
mesh_final = BKE_mesh_copy_for_eval(mesh_input, true);
|
||||
}
|
||||
}
|
||||
if (deformed_verts) {
|
||||
BKE_mesh_vert_coords_apply(mesh_final, deformed_verts);
|
||||
MEM_freeN(deformed_verts);
|
||||
deformed_verts = nullptr;
|
||||
}
|
||||
|
||||
/* Denotes whether the object which the modifier stack came from owns the mesh or whether the
|
||||
* mesh is shared across multiple objects since there are no effective modifiers. */
|
||||
|
|
|
@ -1017,6 +1017,9 @@ void BKE_modifier_deform_verts(ModifierData *md,
|
|||
modwrap_dependsOnNormals(me);
|
||||
}
|
||||
mti->deformVerts(md, ctx, me, vertexCos, numVerts);
|
||||
if (me) {
|
||||
BKE_mesh_tag_coords_changed(me);
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_modifier_deform_vertsEM(ModifierData *md,
|
||||
|
|
Loading…
Reference in New Issue