[Bf-blender-cvs] [24e44143a19] master: Multires: Fix Apply Base when there are deform modifiers

Sergey Sharybin noreply at git.blender.org
Tue Mar 17 16:41:55 CET 2020


Commit: 24e44143a192053f552e4c4b1655146be3aaed61
Author: Sergey Sharybin
Date:   Tue Mar 17 16:08:31 2020 +0100
Branches: master
https://developer.blender.org/rB24e44143a192053f552e4c4b1655146be3aaed61

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.

===================================================================

M	source/blender/blenkernel/intern/multires_reshape.c
M	source/blender/blenkernel/intern/multires_reshape.h
M	source/blender/blenkernel/intern/multires_reshape_apply_base.c
M	source/blender/blenkernel/intern/multires_reshape_util.c

===================================================================

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);



More information about the Bf-blender-cvs mailing list