Multires: Properly support virtual modifiers for Apply Base

The initial code from earlier from today didn't really work reliable
since it is not possible to apply virtual modifiers but not the real
multires one (in a situation like mesh with shapekeys and multires).

New code uses less memory and has better performance for the case
when there are actual modifiers leading the multires. The case when
there is only multires will not be as performant as possible at this
moment.
This commit is contained in:
Sergey Sharybin 2020-03-17 17:34:04 +01:00
parent 1504cb26b0
commit f958560a99
Notes: blender-bot 2023-02-14 10:29:30 +01:00
Referenced by issue #74748, Apply Base (Multiresolution Modifier) on mesh with shape keys distorts the mesh
3 changed files with 53 additions and 25 deletions

View File

@ -96,11 +96,12 @@ struct Mesh *BKE_multires_create_mesh(struct Depsgraph *depsgraph,
struct Object *object,
struct MultiresModifierData *mmd);
/* Creates mesh with all deform modifiers leading the multires one applied.
/* Get coordinates of a deformed base mesh which is an ionput to the given multires modifier.
* NOTE: The modifiers will be re-evaluated. */
struct Mesh *BKE_multires_create_deformed_base_mesh(struct Depsgraph *depsgraph,
struct Object *object,
struct MultiresModifierData *mmd);
float (*BKE_multires_create_deformed_base_mesh_vert_coords(struct Depsgraph *depsgraph,
struct Object *object,
struct MultiresModifierData *mmd,
int *r_num_deformed_verts))[3];
void multiresModifier_del_levels(struct MultiresModifierData *mmd,
struct Scene *scene,

View File

@ -293,23 +293,55 @@ Mesh *BKE_multires_create_mesh(struct Depsgraph *depsgraph,
return result;
}
Mesh *BKE_multires_create_deformed_base_mesh(struct Depsgraph *depsgraph,
Object *object,
MultiresModifierData *mmd)
float (*BKE_multires_create_deformed_base_mesh_vert_coords(struct Depsgraph *depsgraph,
struct Object *object,
struct MultiresModifierData *mmd,
int *r_num_deformed_verts))[3]
{
Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
Object *object_eval = DEG_get_evaluated_object(depsgraph, object);
const int mmd_index = BLI_findindex(&object->modifiers, &mmd->modifier);
BLI_assert(mmd_index != -1);
Object object_for_eval = *object_eval;
object_for_eval.data = object->data;
Mesh *base_mesh = mesh_create_eval_final_view_index(
depsgraph, scene_eval, object, &CD_MASK_BAREMESH, mmd_index - 1);
const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
ModifierEvalContext mesh_eval_context = {depsgraph, &object_for_eval, 0};
if (use_render) {
mesh_eval_context.flag |= MOD_APPLY_RENDER;
}
const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime;
return base_mesh;
VirtualModifierData virtual_modifier_data;
ModifierData *first_md = modifiers_getVirtualModifierList(&object_for_eval,
&virtual_modifier_data);
Mesh *base_mesh = object->data;
int num_deformed_verts;
float(*deformed_verts)[3] = BKE_mesh_vert_coords_alloc(base_mesh, &num_deformed_verts);
for (ModifierData *md = first_md; md != NULL; md = md->next) {
const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
if (md == &mmd->modifier) {
break;
}
if (!modifier_isEnabled(scene_eval, md, required_mode)) {
continue;
}
if (mti->type != eModifierTypeType_OnlyDeform) {
break;
}
modwrap_deformVerts(md, &mesh_eval_context, base_mesh, deformed_verts, num_deformed_verts);
}
if (r_num_deformed_verts != NULL) {
*r_num_deformed_verts = num_deformed_verts;
}
return deformed_verts;
}
MultiresModifierData *find_multires_modifier_before(Scene *scene, ModifierData *lastmd)

View File

@ -189,16 +189,11 @@ void multires_reshape_apply_base_refine_from_deform(MultiresReshapeContext *resh
BLI_assert(object != NULL);
BLI_assert(mmd != NULL);
/* If there are no modifiers prior to the multires can use base mesh as it have all the updated
* vertices already. */
if (mmd->modifier.prev == NULL) {
BKE_subdiv_eval_update_from_mesh(reshape_context->subdiv, reshape_context->base_mesh, NULL);
}
else {
/* TODO(sergey): Possible optimization is to only evaluate new verticies positions without
* construction of the entire mesh. */
Mesh *deformed_base_mesh = BKE_multires_create_deformed_base_mesh(depsgraph, object, mmd);
BKE_subdiv_eval_update_from_mesh(reshape_context->subdiv, deformed_base_mesh, NULL);
BKE_id_free(NULL, deformed_base_mesh);
}
float(*deformed_verts)[3] = BKE_multires_create_deformed_base_mesh_vert_coords(
depsgraph, object, mmd, NULL);
BKE_subdiv_eval_update_from_mesh(
reshape_context->subdiv, reshape_context->base_mesh, deformed_verts);
MEM_freeN(deformed_verts);
}