[Bf-blender-cvs] [578f5ad7bf8] temp-geometry-nodes-extrude-mesh: Deduplicate some attribute interpolation

Hans Goudey noreply at git.blender.org
Tue Jan 11 06:06:20 CET 2022


Commit: 578f5ad7bf8ed68af988b483f202af4449206aaf
Author: Hans Goudey
Date:   Mon Jan 10 23:06:08 2022 -0600
Branches: temp-geometry-nodes-extrude-mesh
https://developer.blender.org/rB578f5ad7bf8ed68af988b483f202af4449206aaf

Deduplicate some attribute interpolation

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

M	source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc

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

diff --git a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc
index 7a6b2b89732..5fa02f15683 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc
@@ -159,6 +159,44 @@ static void expand_mesh_size(Mesh &mesh,
   }
 }
 
+template<typename T> void copy_with_indices(MutableSpan<T> dst, Span<T> src, Span<int> indices)
+{
+  BLI_assert(dst.size() == indices.size());
+  for (const int i : dst.index_range()) {
+    dst[i] = src[indices[i]];
+  }
+}
+
+template<typename T> void copy_with_mask(MutableSpan<T> dst, Span<T> src, IndexMask mask)
+{
+  BLI_assert(dst.size() == mask.size());
+  threading::parallel_for(mask.index_range(), 512, [&](const IndexRange range) {
+    for (const int i : range) {
+      dst[i] = src[mask[i]];
+    }
+  });
+}
+
+/**
+ * \param get_mix_indices_fn: Returns a Span of indices of the source points to mix for every
+ * result point.
+ */
+template<typename T, typename GetMixIndicesFn>
+void copy_with_mixing(MutableSpan<T> dst, Span<T> src, GetMixIndicesFn get_mix_indices_fn)
+{
+  BLI_assert(dst.size() == mask.size());
+  threading::parallel_for(dst.index_range(), 512, [&](const IndexRange range) {
+    attribute_math::DefaultMixer<T> mixer{dst.slice(range)};
+    for (const int i_dst : IndexRange(range.size())) {
+      Span<int> src_indices = get_mix_indices_fn(range[i_dst]);
+      for (const int i_src : src_indices) {
+        mixer.mix_in(i_dst, src[i_src]);
+      }
+    }
+    mixer.finalize();
+  });
+}
+
 static Array<Vector<int>> create_vert_to_edge_map(const int vert_size,
                                                   Span<MEdge> edges,
                                                   const int vert_offset = 0)
@@ -218,26 +256,14 @@ static void extrude_mesh_vertices(MeshComponent &component,
       switch (attribute.domain()) {
         case ATTR_DOMAIN_POINT: {
           /* New vertices copy the attribute values from their source vertex. */
-          MutableSpan<T> new_data = data.slice(new_vert_range);
-          threading::parallel_for(selection.index_range(), 512, [&](const IndexRange range) {
-            for (const int i : range) {
-              new_data[i] = data[selection[i]];
-            }
-          });
+          copy_with_mask(data.slice(new_vert_range), data.as_span(), selection);
           break;
         }
         case ATTR_DOMAIN_EDGE: {
           /* New edge values are mixed from of all the edges connected to the source vertex. */
-          MutableSpan<T> new_data = data.slice(new_edge_range);
-          threading::parallel_for(selection.index_range(), 512, [&](const IndexRange range) {
-            attribute_math::DefaultMixer<T> mixer{new_data.slice(range)};
-            for (const int i : IndexRange(range.size())) {
-              const int i_src_vert = selection[range[i]];
-              for (const int i_connected_edge : vert_to_edge_map[i_src_vert]) {
-                mixer.mix_in(i, data[i_connected_edge]);
-              }
-            }
-            mixer.finalize();
+          copy_with_mixing(data.slice(new_edge_range), data.as_span(), [&](const int index) {
+            const int i_src_vert = selection[index];
+            return vert_to_edge_map[i_src_vert];
           });
           break;
         }
@@ -479,46 +505,30 @@ static void extrude_mesh_edges(MeshComponent &component,
       MutableSpan<T> data = attribute.as_span().typed<T>();
       switch (attribute.domain()) {
         case ATTR_DOMAIN_POINT: {
-          MutableSpan<T> new_data = data.slice(new_vert_range);
-          for (const int i : new_vert_orig_indices.index_range()) {
-            new_data[i] = data[new_vert_orig_indices[i]];
-          }
+          /* New vertices copy the attribute values from their source vertex. */
+          copy_with_indices(data.slice(new_vert_range), data.as_span(), new_vert_orig_indices);
           break;
         }
         case ATTR_DOMAIN_EDGE: {
+          /* Edges parallel to original edges copy the edge attributes from the original edges. */
           MutableSpan<T> duplicate_data = data.slice(duplicate_edge_range);
-          for (const int i : edge_selection.index_range()) {
-            duplicate_data[i] = data[edge_selection[i]];
-          }
+          copy_with_mask(duplicate_data, data.as_span(), edge_selection);
+
+          /* Edges connected to original vertices mix values of selected connected edges. */
           MutableSpan<T> connect_data = data.slice(connect_edge_range);
-          threading::parallel_for(connect_data.index_range(), 512, [&](const IndexRange range) {
-            attribute_math::DefaultMixer<T> mixer{connect_data.slice(range)};
-            for (const int i : IndexRange(range.size())) {
-              const int i_new_vert = range[i];
-              for (const int i_duplicate_edge : new_vert_to_duplicate_edge_map[i_new_vert]) {
-                /* Use the duplicate data rather than the original edge's data because it's
-                 * slightly simpler to access and was just filled in the previous loop. */
-                mixer.mix_in(i, duplicate_data[i_duplicate_edge]);
-              }
-            }
-            mixer.finalize();
+          copy_with_mixing(connect_data, duplicate_data.as_span(), [&](const int i_new_vert) {
+            return new_vert_to_duplicate_edge_map[i_new_vert];
           });
           break;
         }
         case ATTR_DOMAIN_FACE: {
           /* Attribute values for new faces are a mix of the values of faces connected to the its
            * original edge.  */
-          MutableSpan<T> new_data = data.slice(new_poly_range);
-          threading::parallel_for(edge_selection.index_range(), 512, [&](const IndexRange range) {
-            attribute_math::DefaultMixer<T> mixer{new_data.slice(range)};
-            for (const int i : IndexRange(range.size())) {
-              const int i_src_edge = edge_selection[range[i]];
-              for (const int i_connected_poly : edge_to_poly_map[i_src_edge]) {
-                mixer.mix_in(i, data[i_connected_poly]);
-              }
-            }
-            mixer.finalize();
+          copy_with_mixing(data.slice(new_poly_range), data.as_span(), [&](const int i) {
+            const int i_src_edge = edge_selection[i];
+            return edge_to_poly_map[i_src_edge];
           });
+
           break;
         }
         case ATTR_DOMAIN_CORNER: {
@@ -824,44 +834,25 @@ static void extrude_mesh_face_regions(MeshComponent &component,
       switch (attribute.domain()) {
         case ATTR_DOMAIN_POINT: {
           /* New vertices copy the attributes from their original vertices. */
-          MutableSpan<T> new_data = data.slice(new_vert_range);
-          for (const int i : new_vert_orig_indices.index_range()) {
-            new_data[i] = data[new_vert_orig_indices[i]];
-          }
+          copy_with_indices(data.slice(new_vert_range), data.as_span(), new_vert_orig_indices);
           break;
         }
         case ATTR_DOMAIN_EDGE: {
-          /* Two cases:
-           * - Edges parallel to original edges: Copy the edge attributes from the original edges.
-           * - Edges connected to original vertices: Mix values of selected edges that are
-           *   connected to the original vertex.
-           */
+          /* Edges parallel to original edges copy the edge attributes from the original edges. */
           MutableSpan<T> duplicate_data = data.slice(duplicate_edge_range);
+          copy_with_mask(duplicate_data, data.as_span(), edge_selection);
+
+          /* Edges connected to original vertices mix values of selected connected edges. */
           MutableSpan<T> connect_data = data.slice(connect_edge_range);
-          for (const int i : edge_selection.index_range()) {
-            duplicate_data[i] = data[edge_selection[i]];
-          }
-          threading::parallel_for(connect_data.index_range(), 512, [&](const IndexRange range) {
-            attribute_math::DefaultMixer<T> mixer{connect_data.slice(range)};
-            for (const int i : IndexRange(range.size())) {
-              const int i_new_vert = range[i];
-              for (const int i_duplicate_edge : new_vert_to_duplicate_edge_map[i_new_vert]) {
-                /* Use the duplicate data rather than the original edge's data because it's
-                 * slightly simpler to access and was just filled in the previous loop. */
-                mixer.mix_in(i, duplicate_data[i_duplicate_edge]);
-              }
-            }
-            mixer.finalize();
+          copy_with_mixing(connect_data, duplicate_data.as_span(), [&](const int i_new_vert) {
+            return new_vert_to_duplicate_edge_map[i_new_vert];
           });
           break;
         }
         case ATTR_DOMAIN_FACE: {
           /* New faces on the side of extrusions get the values from the corresponding selected
            * face. */
-          MutableSpan<T> new_data = data.slice(side_poly_range);
-          for (const int i : new_data.index_range()) {
-            new_data[i] = data[edge_orig_face_indices[i]];
-          }
+          copy_with_indices(data.slice(side_poly_range), data.as_span(), edge_orig_face_indices);
           break;
         }
         case ATTR_DOMAIN_CORNER: {



More information about the Bf-blender-cvs mailing list