[Bf-blender-cvs] [5e332fd700f] master: Fix T67934: Weight paint doesn't work with Subsurf/Multires

Sergey Sharybin noreply at git.blender.org
Thu Sep 19 12:01:58 CEST 2019


Commit: 5e332fd700fbddfbc4c7e543daa1d852809ad1c1
Author: Sergey Sharybin
Date:   Wed Sep 11 11:14:06 2019 +0200
Branches: master
https://developer.blender.org/rB5e332fd700fbddfbc4c7e543daa1d852809ad1c1

Fix T67934: Weight paint doesn't work with Subsurf/Multires

This is a regression since PBVH was introduced for weight paint.

The solution is: treat subsurf and multires modifiers as deforming
ones for the weight painting. This is an easiest solution to make
PBVH use subdivided location of original vertices.

This change could simplify some of the weight paint by removing
the grids check, since PBVH is not supposed to be built from grids
in this case anymore.

Differential Revision: https://developer.blender.org/D5751

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

M	source/blender/blenkernel/intern/crazyspace.c
M	source/blender/blenkernel/intern/paint.c

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

diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c
index bb87243c2c0..6740fc985e9 100644
--- a/source/blender/blenkernel/intern/crazyspace.c
+++ b/source/blender/blenkernel/intern/crazyspace.c
@@ -342,6 +342,28 @@ static void crazyspace_init_object_for_eval(struct Depsgraph *depsgraph,
   }
 }
 
+static void crazyspace_init_verts_and_matrices(const Mesh *mesh,
+                                               float (**deformmats)[3][3],
+                                               float (**deformcos)[3])
+{
+  int num_verts;
+  *deformcos = BKE_mesh_vert_coords_alloc(mesh, &num_verts);
+  *deformmats = MEM_callocN(sizeof(**deformmats) * num_verts, "defmats");
+  for (int a = 0; a < num_verts; a++) {
+    unit_m3((*deformmats)[a]);
+  }
+  BLI_assert(num_verts == mesh->totvert);
+}
+
+static bool crazyspace_modifier_supports_deform(ModifierData *md)
+{
+  if (ELEM(md->type, eModifierType_Subsurf, eModifierType_Multires)) {
+    return true;
+  }
+  const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+  return (mti->type == eModifierTypeType_OnlyDeform);
+}
+
 int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph,
                                          Scene *scene,
                                          Object *object,
@@ -349,25 +371,23 @@ int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph,
                                          float (**deformcos)[3])
 {
   ModifierData *md;
-  Mesh *me_eval;
-  int a, numVerts = 0;
+  Mesh *me_eval = NULL;
   float(*defmats)[3][3] = NULL, (*deformedVerts)[3] = NULL;
   int numleft = 0;
   VirtualModifierData virtualModifierData;
   Object object_eval;
   crazyspace_init_object_for_eval(depsgraph, object, &object_eval);
   MultiresModifierData *mmd = get_multires_modifier(scene, &object_eval, 0);
+  const bool is_sculpt_mode = (object->mode & OB_MODE_SCULPT) != 0;
   const bool has_multires = mmd != NULL && mmd->sculptlvl > 0;
   const ModifierEvalContext mectx = {depsgraph, &object_eval, 0};
 
-  if (has_multires) {
+  if (is_sculpt_mode && has_multires) {
     *deformmats = NULL;
     *deformcos = NULL;
     return numleft;
   }
 
-  me_eval = NULL;
-
   md = modifiers_getVirtualModifierList(&object_eval, &virtualModifierData);
 
   for (; md; md = md->next) {
@@ -378,41 +398,37 @@ int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph,
     }
 
     if (mti->type == eModifierTypeType_OnlyDeform) {
-      if (!defmats) {
+      if (defmats == NULL) {
         /* NOTE: Evaluated object si re-set to its original undeformed
          * state. */
         Mesh *me = object_eval.data;
         me_eval = BKE_mesh_copy_for_eval(me, true);
-        deformedVerts = BKE_mesh_vert_coords_alloc(me, &numVerts);
-        defmats = MEM_callocN(sizeof(*defmats) * numVerts, "defmats");
-
-        for (a = 0; a < numVerts; a++) {
-          unit_m3(defmats[a]);
-        }
+        crazyspace_init_verts_and_matrices(me_eval, &defmats, &deformedVerts);
       }
 
       if (mti->deformMatrices) {
-        mti->deformMatrices(md, &mectx, me_eval, deformedVerts, defmats, numVerts);
+        mti->deformMatrices(md, &mectx, me_eval, deformedVerts, defmats, me_eval->totvert);
       }
       else {
         break;
       }
     }
+    else {
+      break;
+    }
   }
 
   for (; md; md = md->next) {
-    const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
-
     if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) {
       continue;
     }
 
-    if (mti->type == eModifierTypeType_OnlyDeform) {
+    if (crazyspace_modifier_supports_deform(md)) {
       numleft++;
     }
   }
 
-  if (me_eval) {
+  if (me_eval != NULL) {
     BKE_id_free(NULL, me_eval);
   }
 
@@ -435,6 +451,13 @@ void BKE_crazyspace_build_sculpt(struct Depsgraph *depsgraph,
     /* there are deformation modifier which doesn't support deformation matrices
      * calculation. Need additional crazyspace correction */
 
+    Mesh *mesh = (Mesh *)object->data;
+    Mesh *mesh_eval = NULL;
+
+    if (*deformcos == NULL) {
+      crazyspace_init_verts_and_matrices(mesh, deformmats, deformcos);
+    }
+
     float(*deformedVerts)[3] = *deformcos;
     float(*origVerts)[3] = MEM_dupallocN(deformedVerts);
     float(*quats)[4];
@@ -444,23 +467,26 @@ void BKE_crazyspace_build_sculpt(struct Depsgraph *depsgraph,
     crazyspace_init_object_for_eval(depsgraph, object, &object_eval);
     ModifierData *md = modifiers_getVirtualModifierList(&object_eval, &virtualModifierData);
     const ModifierEvalContext mectx = {depsgraph, &object_eval, 0};
-    Mesh *mesh = (Mesh *)object->data;
 
     for (; md; md = md->next) {
-      const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
-
       if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) {
         continue;
       }
 
-      if (mti->type == eModifierTypeType_OnlyDeform) {
+      if (crazyspace_modifier_supports_deform(md)) {
+        const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+
         /* skip leading modifiers which have been already
          * handled in sculpt_get_first_deform_matrices */
         if (mti->deformMatrices && !deformed) {
           continue;
         }
 
-        mti->deformVerts(md, &mectx, NULL, deformedVerts, mesh->totvert);
+        if (mesh_eval == NULL) {
+          mesh_eval = BKE_mesh_copy_for_eval(mesh, true);
+        }
+
+        mti->deformVerts(md, &mectx, mesh_eval, deformedVerts, mesh_eval->totvert);
         deformed = 1;
       }
     }
@@ -479,6 +505,10 @@ void BKE_crazyspace_build_sculpt(struct Depsgraph *depsgraph,
 
     MEM_freeN(origVerts);
     MEM_freeN(quats);
+
+    if (mesh_eval != NULL) {
+      BKE_id_free(NULL, mesh_eval);
+    }
   }
 
   if (*deformmats == NULL) {
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 9c56e505d91..983127372ca 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -1104,6 +1104,12 @@ MultiresModifierData *BKE_sculpt_multires_active(Scene *scene, Object *ob)
     return NULL;
   }
 
+  /* Weight paint operates on original vertices, and needs to treat multires as regular modifier
+   * to make it so that PBVH vertices are at the multires surface. */
+  if ((ob->mode & OB_MODE_SCULPT) == 0) {
+    return NULL;
+  }
+
   for (md = modifiers_getVirtualModifierList(ob, &virtualModifierData); md; md = md->next) {
     if (md->type == eModifierType_Multires) {
       MultiresModifierData *mmd = (MultiresModifierData *)md;
@@ -1149,7 +1155,10 @@ static bool sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob)
     if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) {
       continue;
     }
-    if (ELEM(md->type, eModifierType_ShapeKey, eModifierType_Multires)) {
+    if (md->type == eModifierType_Multires && (ob->mode & OB_MODE_SCULPT)) {
+      continue;
+    }
+    if (md->type == eModifierType_ShapeKey) {
       continue;
     }
 
@@ -1199,8 +1208,9 @@ static void sculpt_update_object(
 
   ss->kb = (mmd == NULL) ? BKE_keyblock_from_object(ob) : NULL;
 
-  /* VWPaint require mesh info for loop lookup, so require sculpt mode here */
-  if (mmd && ob->mode & OB_MODE_SCULPT) {
+  /* NOTE: Weight pPaint require mesh info for loop lookup, but it never uses multires code path,
+   * so no extra checks is needed here. */
+  if (mmd) {
     ss->multires = mmd;
     ss->totvert = me_eval->totvert;
     ss->totpoly = me_eval->totpoly;



More information about the Bf-blender-cvs mailing list