[Bf-blender-cvs] [81eac17737d] blender-v3.2-release: Fix T98975: Broken vertex paint mode operators

Hans Goudey noreply at git.blender.org
Fri Jun 24 23:04:48 CEST 2022


Commit: 81eac17737da467b3c10974c4dc03dd85e0fc622
Author: Hans Goudey
Date:   Thu Jun 23 11:32:53 2022 -0500
Branches: blender-v3.2-release
https://developer.blender.org/rB81eac17737da467b3c10974c4dc03dd85e0fc622

Fix T98975: Broken vertex paint mode operators

All of the operators in vertex paint mode didn't work properly with
the new color attribute system. They only worked on byte color type
attributes on the face corner domain.

Since there are four possible combinations of domains and types now,
it mostly ended up being simpler to convert the code to C++ and use
the geometry component API for retrieving attributes, interpolating
between domains, etc. The code changes ended up being fairly large,
but the result should be simpler now.

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

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

M	release/scripts/startup/bl_operators/vertexpaint_dirt.py
M	source/blender/editors/sculpt_paint/CMakeLists.txt
M	source/blender/editors/sculpt_paint/paint_intern.h
M	source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc
D	source/blender/editors/sculpt_paint/paint_vertex_color_utils.c

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

diff --git a/release/scripts/startup/bl_operators/vertexpaint_dirt.py b/release/scripts/startup/bl_operators/vertexpaint_dirt.py
index 8089a65960c..1a7394e03af 100644
--- a/release/scripts/startup/bl_operators/vertexpaint_dirt.py
+++ b/release/scripts/startup/bl_operators/vertexpaint_dirt.py
@@ -4,15 +4,10 @@
 # <pep8 compliant>
 
 
-def get_vcolor_layer_data(me):
-    for lay in me.vertex_colors:
-        if lay.active:
-            return lay.data
-
-    lay = me.vertex_colors.new()
-    lay.active = True
-    return lay.data
-
+def ensure_active_color_attribute(me):
+    if me.attributes.active_color:
+        return me.attributes.active_color
+    return me.color_attributes.new("Color", 'BYTE_COLOR', 'FACE_CORNER')
 
 def applyVertexDirt(me, blur_iterations, blur_strength, clamp_dirt, clamp_clean, dirt_only, normalize):
     from mathutils import Vector
@@ -101,17 +96,21 @@ def applyVertexDirt(me, blur_iterations, blur_strength, clamp_dirt, clamp_clean,
     else:
         tone_range = 1.0 / tone_range
 
-    active_col_layer = get_vcolor_layer_data(me)
-    if not active_col_layer:
+    active_color_attribute = ensure_active_color_attribute(me)
+    if not active_color_attribute:
         return {'CANCELLED'}
 
+    point_domain = active_color_attribute.domain == 'POINT'
+
+    attribute_data = active_color_attribute.data
+
     use_paint_mask = me.use_paint_mask
     for i, p in enumerate(me.polygons):
         if not use_paint_mask or p.select:
             for loop_index in p.loop_indices:
                 loop = me.loops[loop_index]
                 v = loop.vertex_index
-                col = active_col_layer[loop_index].color
+                col = attribute_data[v if point_domain else loop_index].color
                 tone = vert_tone[v]
                 tone = (tone - min_tone) * tone_range
 
diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index 64517560256..b2a7334a13e 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -50,7 +50,6 @@ set(SRC
   paint_utils.c
   paint_vertex.cc
   paint_vertex_color_ops.cc
-  paint_vertex_color_utils.c
   paint_vertex_proj.c
   paint_vertex_weight_ops.c
   paint_vertex_weight_utils.c
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index 187f793eefe..e11e6c1850b 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -135,18 +135,10 @@ void PAINT_OT_vertex_paint(struct wmOperatorType *ot);
 
 unsigned int vpaint_get_current_color(struct Scene *scene, struct VPaint *vp, bool secondary);
 
-/* paint_vertex_color_utils.c */
-
 /**
  * \note weight-paint has an equivalent function: #ED_wpaint_blend_tool
  */
 unsigned int ED_vpaint_blend_tool(int tool, uint col, uint paintcol, int alpha_i);
-/**
- * Apply callback to each vertex of the active vertex color layer.
- */
-bool ED_vpaint_color_transform(struct Object *ob,
-                               VPaintTransform_Callback vpaint_tx_fn,
-                               const void *user_data);
 
 /* paint_vertex_weight_utils.c */
 
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc
index 6a47aceb2b0..f5652384177 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc
+++ b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc
@@ -12,11 +12,15 @@
 #include "DNA_scene_types.h"
 
 #include "BLI_array.hh"
+#include "BLI_index_mask_ops.hh"
 #include "BLI_math_base.h"
 #include "BLI_math_color.h"
+#include "BLI_vector.hh"
 
+#include "BKE_attribute_math.hh"
 #include "BKE_context.h"
 #include "BKE_deform.h"
+#include "BKE_geometry_set.hh"
 #include "BKE_mesh.h"
 
 #include "DEG_depsgraph.h"
@@ -32,6 +36,10 @@
 #include "paint_intern.h" /* own include */
 
 using blender::Array;
+using blender::ColorGeometry4f;
+using blender::GMutableSpan;
+using blender::IndexMask;
+using blender::Vector;
 
 /* -------------------------------------------------------------------- */
 /** \name Internal Utility Functions
@@ -62,34 +70,57 @@ static void tag_object_after_update(Object *object)
 
 static bool vertex_paint_from_weight(Object *ob)
 {
-  Mesh *me;
-  const MPoly *mp;
-  int vgroup_active;
+  using namespace blender;
 
+  Mesh *me;
   if (((me = BKE_mesh_from_object(ob)) == nullptr ||
        (ED_mesh_color_ensure(me, nullptr)) == false)) {
     return false;
   }
 
-  /* TODO: respect selection. */
-  /* TODO: Do we want to take weights from evaluated mesh instead? 2.7x was not doing it anyway. */
-  mp = me->mpoly;
-  vgroup_active = me->vertex_group_active_index - 1;
-  for (int i = 0; i < me->totpoly; i++, mp++) {
-    MLoopCol *lcol = &me->mloopcol[mp->loopstart];
-    uint j = 0;
-    do {
-      uint vidx = me->mloop[mp->loopstart + j].v;
-      const float weight = BKE_defvert_find_weight(&me->dvert[vidx], vgroup_active);
-      const uchar grayscale = weight * 255;
-      lcol->r = grayscale;
-      lcol->b = grayscale;
-      lcol->g = grayscale;
-      lcol++;
-      j++;
-    } while (j < mp->totloop);
+  const CustomDataLayer *active_color_layer = BKE_id_attributes_active_color_get(&me->id);
+  if (active_color_layer == nullptr) {
+    BLI_assert_unreachable();
+    return false;
+  }
+
+  const int active_vertex_group_index = me->vertex_group_active_index - 1;
+  const bDeformGroup *deform_group = static_cast<const bDeformGroup *>(
+      BLI_findlink(&me->vertex_group_names, active_vertex_group_index));
+  if (deform_group == nullptr) {
+    BLI_assert_unreachable();
+    return false;
+  }
+
+  MeshComponent component;
+  component.replace(me, GeometryOwnershipType::Editable);
+
+  bke::WriteAttributeLookup color_attribute = component.attribute_try_get_for_write(
+      active_color_layer->name);
+  if (!color_attribute) {
+    BLI_assert_unreachable();
+    return false;
+  }
+
+  /* Retrieve the vertex group with the domain and type of the existing color
+   * attribute, in order to let the attribute API handle both conversions. */
+  const GVArray vertex_group = component.attribute_get_for_read(
+      deform_group->name,
+      ATTR_DOMAIN_POINT,
+      bke::cpp_type_to_custom_data_type(color_attribute.varray.type()));
+  if (!vertex_group) {
+    BLI_assert_unreachable();
+    return false;
   }
 
+  GVArray_GSpan interpolated{component.attribute_try_adapt_domain(
+      vertex_group, ATTR_DOMAIN_POINT, color_attribute.domain)};
+
+  color_attribute.varray.set_all(interpolated.data());
+
+  if (color_attribute.tag_modified_fn) {
+    color_attribute.tag_modified_fn();
+  }
   tag_object_after_update(ob);
 
   return true;
@@ -128,99 +159,81 @@ void PAINT_OT_vertex_color_from_weight(wmOperatorType *ot)
 /** \name Smooth Vertex Colors Operator
  * \{ */
 
-static void vertex_color_smooth_looptag(Mesh *me, const bool *mlooptag)
+static IndexMask get_selected_indices(const Mesh &mesh,
+                                      const AttributeDomain domain,
+                                      Vector<int64_t> &indices)
 {
-  const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
-  const MPoly *mp;
-  bool has_shared = false;
+  using namespace blender;
+  Span<MVert> verts(mesh.mvert, mesh.totvert);
+  Span<MPoly> faces(mesh.mpoly, mesh.totpoly);
+
+  MeshComponent component;
+  component.replace(&const_cast<Mesh &>(mesh), GeometryOwnershipType::ReadOnly);
+
+  if (mesh.editflag & ME_EDIT_PAINT_FACE_SEL) {
+    const VArray<bool> selection = component.attribute_try_adapt_domain(
+        VArray<bool>::ForFunc(faces.size(),
+                              [&](const int i) { return faces[i].flag & ME_FACE_SEL; }),
+        ATTR_DOMAIN_FACE,
+        domain);
+
+    return index_mask_ops::find_indices_based_on_predicate(
+        IndexMask(component.attribute_domain_size(domain)), 4096, indices, [&](const int i) {
+          return selection[i];
+        });
+  }
+  if (mesh.editflag & ME_EDIT_PAINT_VERT_SEL) {
+    const VArray<bool> selection = component.attribute_try_adapt_domain(
+        VArray<bool>::ForFunc(verts.size(), [&](const int i) { return verts[i].flag & SELECT; }),
+        ATTR_DOMAIN_POINT,
+        domain);
+
+    return index_mask_ops::find_indices_based_on_predicate(
+        IndexMask(component.attribute_domain_size(domain)), 4096, indices, [&](const int i) {
+          return selection[i];
+        });
+  }
+  return IndexMask(component.attribute_domain_size(domain));
+}
 
-  if (me->mloopcol == nullptr || me->totvert == 0 || me->totpoly == 0) {
+static void face_corner_color_equalize_vertices(Mesh &mesh, const IndexMask selection)
+{
+  using namespace blender;
+
+  const CustomDataLayer *active_color_layer = BKE_id_attributes_active_color_get(&mesh.id);
+  if (active_color_layer == nullptr) {
+    BLI_assert_unreachable();
     return;
   }
 
-  int(*scol)[4] = static_cast<int(*)[4]>(MEM_callocN(sizeof(int) * me->totvert * 5, "scol"));
-
-  int i;
-  for (i = 0, mp = me->mpoly; i < me->totpoly; i++, mp++) {
-    if ((use_face_sel == false) || (mp->flag & ME_FACE_SEL)) {
-      const MLoop *ml = me->mloop + mp->loopstart;
-      MLoopCol *lcol = me->mloopcol + mp->loopstart;
-      for (int j = 0; j < mp->totloop; j++, ml++, lcol++) {
-        scol[ml->v][0] += lcol->r;
-        scol[ml->v][1] += lcol->g;
-        scol[ml->v][2] += lcol->b;
-        scol[ml->v][3] += 1;
-        has_shared = 1;
-      }
-    }
+  MeshComponent component;
+  component.replace(&mesh, GeometryOwnershipType::Editable);
+
+  if (component.attribute_get_meta_data(active_color_layer->name)->domain == ATTR_DOMAIN_POINT) {
+    return;
   }
 
-  if (has_shared) {
-    for (i = 0; i < me->totvert; i++) {
-      if (scol[i][3] != 0) {
-        scol[i][0] = divide_round_i(scol[i][0], scol[i][3]);
-        scol[i][1] = divide_round_i(scol[i][1], scol[i][3]);
-        scol[i][2] = divide_round_i(scol[i][2], scol[i][3]);
-      }
-    }
+  GVArray color_attribute_point = component.attribute_try_get_for_read(active_color_layer->name,
+                            

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list