diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2020-03-17 18:08:31 +0300 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2020-03-17 18:41:43 +0300 |
commit | 24e44143a192053f552e4c4b1655146be3aaed61 (patch) | |
tree | cd0e026b8f0f7c9cd9d7b0cb4f67225d85266e05 | |
parent | 628d799c85965191d5f6231b3433bbae425e59f0 (diff) |
Multires: Fix Apply Base when there are deform modifiers
Their effect was applied twice after hitting Apply Base since the
operator was also applying deformation caused by those modifiers.
4 files changed, 99 insertions, 10 deletions
diff --git a/source/blender/blenkernel/intern/multires_reshape.c b/source/blender/blenkernel/intern/multires_reshape.c index 6097121fefd..53e1af15192 100644 --- a/source/blender/blenkernel/intern/multires_reshape.c +++ b/source/blender/blenkernel/intern/multires_reshape.c @@ -224,10 +224,35 @@ void multiresModifier_base_apply(struct Depsgraph *depsgraph, return; } + multires_reshape_store_original_grids(&reshape_context); + + /* At this point base_mesh is object's mesh, the subdiv is initialized to the deformed state of + * the base mesh. + * Store coordinates of top level grids in object space which will define true shape we would + * want to reshape to after modifying the base mesh. */ multires_reshape_assign_final_coords_from_mdisps(&reshape_context); + + /* For modifying base mesh we only want to consider deformation caused by multires displacement + * and ignore all deformation which might be caused by deformation modifiers leading the multires + * one. + * So refine the subdiv to the original mesh verticies positions, which will also need to make + * it so object space displacement is re-evaluated for them (as in, can not re-use any knowledge + * from the final coordinates in the object space ). */ + multires_reshape_apply_base_refine_from_base(&reshape_context); + + /* Modify original mesh coordinates. This happens in two steps: + * - Coordinates are set to their final location, where they are intended to be in the final + * result. + * - Heuristic moves them a bit, kind of canceling out the effect of subsurf (so then when + * multires modifier applies subsurf vertices are placed at the desired location). */ multires_reshape_apply_base_update_mesh_coords(&reshape_context); multires_reshape_apply_base_refit_base_mesh(&reshape_context); - multires_reshape_apply_base_refine_subdiv(&reshape_context); + + /* Reshape to the stored final state. + * Not that the base changed, so the subdiv is to be refined to the new positions. Unfortunately, + * this can not be done foe entirely cheap: if there were deformation modifiers prior to the + * multires they need to be re-evaluated for the new base mesh. */ + multires_reshape_apply_base_refine_from_deform(&reshape_context); multires_reshape_object_grids_to_tangent_displacement(&reshape_context); multires_reshape_context_free(&reshape_context); diff --git a/source/blender/blenkernel/intern/multires_reshape.h b/source/blender/blenkernel/intern/multires_reshape.h index bdadc1f2800..deeb885e15a 100644 --- a/source/blender/blenkernel/intern/multires_reshape.h +++ b/source/blender/blenkernel/intern/multires_reshape.h @@ -36,6 +36,11 @@ struct Subdiv; struct SubdivCCG; typedef struct MultiresReshapeContext { + /* NOTE: Only available when context is initialized from object. */ + struct Depsgraph *depsgraph; + struct Object *object; + struct MultiresModifierData *mmd; + /* Base mesh from original object. * NOTE: Does NOT include any leading modifiers in it. */ struct Mesh *base_mesh; @@ -142,6 +147,9 @@ struct Subdiv *multires_reshape_create_subdiv(struct Depsgraph *depsgraph, struct Object *object, const struct MultiresModifierData *mmd); +/* NOTE: Initialized base mesh to object's mesh, the Subdiv is created from the deformed + * mesh prior to the multires modifier if depsgraph is not NULL. If the depsgraph is NULL + * then Subdiv is created from base mesh (without any deformation applied). */ bool multires_reshape_context_create_from_object(MultiresReshapeContext *reshape_context, struct Depsgraph *depsgraph, struct Object *object, @@ -302,6 +310,12 @@ void multires_reshape_apply_base_update_mesh_coords(MultiresReshapeContext *resh void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape_context); /* Refine subdivision surface to the new positions of the base mesh. */ -void multires_reshape_apply_base_refine_subdiv(MultiresReshapeContext *reshape_context); +void multires_reshape_apply_base_refine_from_base(MultiresReshapeContext *reshape_context); + +/* Refine subdivision surface to the new positions of the deformed mesh (base mesh with all + * modifiers leading the multires applied). + * + * NOTE: Will re-evaluate all leading modifiers, so it's not cheap. */ +void multires_reshape_apply_base_refine_from_deform(MultiresReshapeContext *reshape_context); #endif /* __BKE_INTERN_MULTIRES_RESHAPE_H__ */ diff --git a/source/blender/blenkernel/intern/multires_reshape_apply_base.c b/source/blender/blenkernel/intern/multires_reshape_apply_base.c index e05b5bb3179..958fb60bbdc 100644 --- a/source/blender/blenkernel/intern/multires_reshape_apply_base.c +++ b/source/blender/blenkernel/intern/multires_reshape_apply_base.c @@ -27,23 +27,46 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" #include "BLI_math_vector.h" +#include "BLI_listbase.h" +#include "BKE_customdata.h" +#include "BKE_lib_id.h" #include "BKE_mesh.h" +#include "BKE_mesh_runtime.h" #include "BKE_mesh_mapping.h" +#include "BKE_multires.h" #include "BKE_subdiv_eval.h" +#include "DEG_depsgraph_query.h" + void multires_reshape_apply_base_update_mesh_coords(MultiresReshapeContext *reshape_context) { Mesh *base_mesh = reshape_context->base_mesh; - const int grid_size = reshape_context->top.grid_size; - const int grid_index = grid_size * grid_size - 1; - for (int i = 0; i < base_mesh->totloop; ++i) { - MDisps *displacement_grid = &reshape_context->mdisps[i]; - const MLoop *loop = &base_mesh->mloop[i]; - MVert *vert = &base_mesh->mvert[loop->v]; - copy_v3_v3(vert->co, displacement_grid->disps[grid_index]); + const MLoop *mloop = base_mesh->mloop; + MVert *mvert = base_mesh->mvert; + for (int loop_index = 0; loop_index < base_mesh->totloop; ++loop_index) { + const MLoop *loop = &mloop[loop_index]; + MVert *vert = &mvert[loop->v]; + + GridCoord grid_coord; + grid_coord.grid_index = loop_index; + grid_coord.u = 1.0f; + grid_coord.v = 1.0f; + + float P[3]; + float tangent_matrix[3][3]; + multires_reshape_evaluate_limit_at_grid(reshape_context, &grid_coord, P, tangent_matrix); + + ReshapeConstGridElement grid_element = multires_reshape_orig_grid_element_for_grid_coord( + reshape_context, &grid_coord); + float D[3]; + mul_v3_m3v3(D, tangent_matrix, grid_element.displacement); + + add_v3_v3v3(vert->co, P, D); } } @@ -152,7 +175,30 @@ void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape BKE_mesh_calc_normals(base_mesh); } -void multires_reshape_apply_base_refine_subdiv(MultiresReshapeContext *reshape_context) +void multires_reshape_apply_base_refine_from_base(MultiresReshapeContext *reshape_context) { BKE_subdiv_eval_update_from_mesh(reshape_context->subdiv, reshape_context->base_mesh, NULL); } + +void multires_reshape_apply_base_refine_from_deform(MultiresReshapeContext *reshape_context) +{ + struct Depsgraph *depsgraph = reshape_context->depsgraph; + Object *object = reshape_context->object; + MultiresModifierData *mmd = reshape_context->mmd; + BLI_assert(depsgraph != NULL); + 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); + } +} diff --git a/source/blender/blenkernel/intern/multires_reshape_util.c b/source/blender/blenkernel/intern/multires_reshape_util.c index 175b0ee9187..5401fe2dcda 100644 --- a/source/blender/blenkernel/intern/multires_reshape_util.c +++ b/source/blender/blenkernel/intern/multires_reshape_util.c @@ -163,6 +163,10 @@ bool multires_reshape_context_create_from_object(MultiresReshapeContext *reshape Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); Mesh *base_mesh = (Mesh *)object->data; + reshape_context->depsgraph = depsgraph; + reshape_context->object = object; + reshape_context->mmd = mmd; + reshape_context->base_mesh = base_mesh; reshape_context->subdiv = multires_reshape_create_subdiv(depsgraph, object, mmd); |