[Bf-blender-cvs] [de30fda04e8] master: Fix T74686: Loading btx file in multires modifier is not working

Sergey Sharybin noreply at git.blender.org
Fri Mar 13 16:15:36 CET 2020


Commit: de30fda04e8d84a173e929a0f3d9d8c71bcc4bbf
Author: Sergey Sharybin
Date:   Fri Mar 13 16:13:32 2020 +0100
Branches: master
https://developer.blender.org/rBde30fda04e8d84a173e929a0f3d9d8c71bcc4bbf

Fix T74686: Loading btx file in multires modifier is not working

Was happening when object does not have CD_MDISPS allocated yet.
Need to make sure totdisp and level is specified on CD_MDISPS data
prior to loading (as the load expects them to be properly set).

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

M	source/blender/blenkernel/BKE_multires.h
M	source/blender/blenkernel/intern/mesh_evaluate.c
M	source/blender/blenkernel/intern/multires.c
M	source/blender/blenkernel/intern/multires_reshape.c
M	source/blender/blenkernel/intern/subdiv_displacement_multires.c

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

diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h
index 941675489c1..4ee255d4e61 100644
--- a/source/blender/blenkernel/BKE_multires.h
+++ b/source/blender/blenkernel/BKE_multires.h
@@ -130,6 +130,10 @@ int multires_mdisp_corners(struct MDisps *s);
 /* update multires data after topology changing */
 void multires_topology_changed(struct Mesh *me);
 
+void multires_ensure_external_read(struct Mesh *mesh, int top_level);
+void multiresModifier_ensure_external_read(struct Mesh *mesh,
+                                           const struct MultiresModifierData *mmd);
+
 /**** interpolation stuff ****/
 void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u, float v);
 int mdisp_rot_face_to_crn(struct MVert *mvert,
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index 7b655b2d8fc..e14803e4193 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -3576,6 +3576,7 @@ void BKE_mesh_convert_mfaces_to_mpolys_ex(ID *id,
 
   if (id) {
     /* ensure external data is transferred */
+    /* TODO(sergey): Use multiresModifier_ensure_external_read(). */
     CustomData_external_read(fdata, id, CD_MASK_MDISPS, totface_i);
   }
 
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index 70061c155d3..4e97d0fc05c 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -647,7 +647,7 @@ static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl)
   GridPaintMask *gpm;
 
   multires_set_tot_mdisps(me, mmd->totlvl);
-  CustomData_external_read(&me->ldata, &me->id, CD_MASK_MDISPS, me->totloop);
+  multiresModifier_ensure_external_read(me, mmd);
   mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
   gpm = CustomData_get_layer(&me->ldata, CD_GRID_PAINT_MASK);
 
@@ -713,7 +713,7 @@ void multiresModifier_del_levels(MultiresModifierData *mmd,
   MDisps *mdisps;
 
   multires_set_tot_mdisps(me, mmd->totlvl);
-  CustomData_external_read(&me->ldata, &me->id, CD_MASK_MDISPS, me->totloop);
+  multiresModifier_ensure_external_read(me, mmd);
   mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
 
   multires_force_sculpt_rebuild(ob);
@@ -1144,7 +1144,7 @@ void multires_modifier_update_mdisps(struct DerivedMesh *dm, Scene *scene)
   me = ccgdm->multires.ob->data;
   mmd = ccgdm->multires.mmd;
   multires_set_tot_mdisps(me, mmd->totlvl);
-  CustomData_external_read(&me->ldata, &me->id, CD_MASK_MDISPS, me->totloop);
+  multiresModifier_ensure_external_read(me, mmd);
   mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
 
   if (mdisps) {
@@ -1372,7 +1372,7 @@ DerivedMesh *multires_make_derived_from_derived(
   }
 
   multires_set_tot_mdisps(me, mmd->totlvl);
-  CustomData_external_read(&me->ldata, &me->id, CD_MASK_MDISPS, me->totloop);
+  multiresModifier_ensure_external_read(me, mmd);
 
   /*run displacement*/
   multiresModifier_disp_run(result, ob->data, dm, APPLY_DISPLACEMENTS, subGridData, mmd->totlvl);
@@ -2224,7 +2224,7 @@ static void multires_apply_smat(struct Depsgraph *UNUSED(depsgraph),
   }
   /* Make sure layer present. */
   Mesh *mesh = (Mesh *)object->data;
-  CustomData_external_read(&mesh->ldata, &mesh->id, CD_MASK_MDISPS, mesh->totloop);
+  multiresModifier_ensure_external_read(mesh, mmd);
   if (!CustomData_get_layer(&mesh->ldata, CD_MDISPS)) {
     return;
   }
@@ -2318,6 +2318,44 @@ void multires_topology_changed(Mesh *me)
   }
 }
 
+/* Makes sure data from an external file is fully read.
+ *
+ * Since the multires data files only contain displacement vectors without knowledge about
+ * subdivision level some extra work is needed. Namely make is to all displacement grids have
+ * proper level and number of displacement vectors set.  */
+void multires_ensure_external_read(struct Mesh *mesh, int top_level)
+{
+  if (!CustomData_external_test(&mesh->ldata, CD_MDISPS)) {
+    return;
+  }
+
+  MDisps *mdisps = CustomData_get_layer(&mesh->ldata, CD_MDISPS);
+  if (mdisps == NULL) {
+    mdisps = CustomData_add_layer(&mesh->ldata, CD_MDISPS, CD_DEFAULT, NULL, mesh->totloop);
+  }
+
+  const int totloop = mesh->totloop;
+
+  for (int i = 0; i < totloop; ++i) {
+    if (mdisps[i].level != top_level) {
+      MEM_SAFE_FREE(mdisps[i].disps);
+    }
+
+    /* NOTE: CustomData_external_read will take care of allocation of displacement vectors if
+     * they are missing. */
+
+    const int totdisp = multires_grid_tot[top_level];
+    mdisps[i].totdisp = totdisp;
+    mdisps[i].level = top_level;
+  }
+
+  CustomData_external_read(&mesh->ldata, &mesh->id, CD_MASK_MDISPS, mesh->totloop);
+}
+void multiresModifier_ensure_external_read(struct Mesh *mesh, const MultiresModifierData *mmd)
+{
+  multires_ensure_external_read(mesh, mmd->totlvl);
+}
+
 /***************** Multires interpolation stuff *****************/
 
 /* Find per-corner coordinate with given per-face UV coord */
diff --git a/source/blender/blenkernel/intern/multires_reshape.c b/source/blender/blenkernel/intern/multires_reshape.c
index eef35aead28..a29398b24a0 100644
--- a/source/blender/blenkernel/intern/multires_reshape.c
+++ b/source/blender/blenkernel/intern/multires_reshape.c
@@ -149,8 +149,7 @@ bool multiresModifier_reshapeFromCCG(const int tot_level,
     return false;
   }
 
-  CustomData_external_read(
-      &coarse_mesh->ldata, &coarse_mesh->id, CD_MASK_MDISPS, coarse_mesh->totloop);
+  multires_ensure_external_read(coarse_mesh, reshape_context.top.level);
 
   multires_reshape_store_original_grids(&reshape_context);
   multires_reshape_ensure_grids(coarse_mesh, reshape_context.top.level);
diff --git a/source/blender/blenkernel/intern/subdiv_displacement_multires.c b/source/blender/blenkernel/intern/subdiv_displacement_multires.c
index 1f78cf4eb3b..50b2b3c7c46 100644
--- a/source/blender/blenkernel/intern/subdiv_displacement_multires.c
+++ b/source/blender/blenkernel/intern/subdiv_displacement_multires.c
@@ -47,6 +47,7 @@ typedef struct MultiresDisplacementData {
   int grid_size;
   /* Mesh is used to read external displacement. */
   Mesh *mesh;
+  const MultiresModifierData *mmd;
   const MPoly *mpoly;
   const MDisps *mdisps;
   /* Indexed by ptex face index, contains polygon/corner which corresponds
@@ -328,9 +329,7 @@ static int displacement_get_face_corner(MultiresDisplacementData *data,
 static void initialize(SubdivDisplacement *displacement)
 {
   MultiresDisplacementData *data = displacement->user_data;
-  Mesh *mesh = data->mesh;
-  /* Make sure external displacement is read. */
-  CustomData_external_read(&mesh->ldata, &mesh->id, CD_MASK_MDISPS, mesh->totloop);
+  multiresModifier_ensure_external_read(data->mesh, data->mmd);
   data->is_initialized = true;
 }
 
@@ -421,6 +420,7 @@ static void displacement_init_data(SubdivDisplacement *displacement,
   data->subdiv = subdiv;
   data->grid_size = BKE_subdiv_grid_size_from_level(mmd->totlvl);
   data->mesh = mesh;
+  data->mmd = mmd;
   data->mpoly = mesh->mpoly;
   data->mdisps = CustomData_get_layer(&mesh->ldata, CD_MDISPS);
   data->face_ptex_offset = BKE_subdiv_face_ptex_offset_get(subdiv);



More information about the Bf-blender-cvs mailing list