[Bf-blender-cvs] [a51584dc70a] master: Geometry Nodes: transfer corner and point attributes in Point Distribute node

Jacques Lucke noreply at git.blender.org
Fri Jan 15 12:01:04 CET 2021


Commit: a51584dc70ac4162227abc6256c414a15f418573
Author: Jacques Lucke
Date:   Fri Jan 15 12:00:30 2021 +0100
Branches: master
https://developer.blender.org/rBa51584dc70ac4162227abc6256c414a15f418573

Geometry Nodes: transfer corner and point attributes in Point Distribute node

If the mesh has any corner or point attributes (e.g. vertex weights or
uv maps), those attributes will now be available on the generated points
as well.

Other domains can be supported as well. I just did not implement those yet,
because we don't have a use case for them.

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

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

A	source/blender/blenkernel/BKE_attribute_math.hh
M	source/blender/blenkernel/CMakeLists.txt
M	source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc

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

diff --git a/source/blender/blenkernel/BKE_attribute_math.hh b/source/blender/blenkernel/BKE_attribute_math.hh
new file mode 100644
index 00000000000..b8bb2048d9d
--- /dev/null
+++ b/source/blender/blenkernel/BKE_attribute_math.hh
@@ -0,0 +1,94 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "BLI_color.hh"
+#include "BLI_float2.hh"
+#include "BLI_float3.hh"
+#include "DNA_customdata_types.h"
+
+namespace blender::attribute_math {
+
+/**
+ * Utility function that simplifies calling a templated function based on a custom data type.
+ */
+template<typename Func>
+void convert_to_static_type(const CustomDataType data_type, const Func &func)
+{
+  switch (data_type) {
+    case CD_PROP_FLOAT:
+      func(float());
+      break;
+    case CD_PROP_FLOAT2:
+      func(float2());
+      break;
+    case CD_PROP_FLOAT3:
+      func(float3());
+      break;
+    case CD_PROP_INT32:
+      func(int());
+      break;
+    case CD_PROP_BOOL:
+      func(bool());
+      break;
+    case CD_PROP_COLOR:
+      func(Color4f());
+      break;
+    default:
+      BLI_assert(false);
+      break;
+  }
+}
+
+/* Interpolate between three values. */
+template<typename T> T mix3(const float3 &weights, const T &v0, const T &v1, const T &v2);
+
+template<> inline bool mix3(const float3 &weights, const bool &v0, const bool &v1, const bool &v2)
+{
+  return (weights.x * v0 + weights.y * v1 + weights.z * v2) >= 0.5f;
+}
+
+template<> inline int mix3(const float3 &weights, const int &v0, const int &v1, const int &v2)
+{
+  return static_cast<int>(weights.x * v0 + weights.y * v1 + weights.z * v2);
+}
+
+template<>
+inline float mix3(const float3 &weights, const float &v0, const float &v1, const float &v2)
+{
+  return weights.x * v0 + weights.y * v1 + weights.z * v2;
+}
+
+template<>
+inline float2 mix3(const float3 &weights, const float2 &v0, const float2 &v1, const float2 &v2)
+{
+  return weights.x * v0 + weights.y * v1 + weights.z * v2;
+}
+
+template<>
+inline float3 mix3(const float3 &weights, const float3 &v0, const float3 &v1, const float3 &v2)
+{
+  return weights.x * v0 + weights.y * v1 + weights.z * v2;
+}
+
+template<>
+inline Color4f mix3(const float3 &weights, const Color4f &v0, const Color4f &v1, const Color4f &v2)
+{
+  Color4f result;
+  interp_v4_v4v4v4(result, v0, v1, v2, weights);
+  return result;
+}
+
+}  // namespace blender::attribute_math
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 5021736dbfe..82f985a3227 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -275,6 +275,7 @@ set(SRC
   BKE_asset.h
   BKE_attribute.h
   BKE_attribute_access.hh
+  BKE_attribute_math.hh
   BKE_autoexec.h
   BKE_blender.h
   BKE_blender_copybuffer.h
diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
index 5e9b780db6d..eaf13b94eb9 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
@@ -26,6 +26,7 @@
 #include "DNA_meshdata_types.h"
 #include "DNA_pointcloud_types.h"
 
+#include "BKE_attribute_math.hh"
 #include "BKE_bvhutils.h"
 #include "BKE_deform.h"
 #include "BKE_mesh.h"
@@ -217,14 +218,16 @@ BLI_NOINLINE static void eliminate_points_based_on_mask(Span<bool> elimination_m
   }
 }
 
-BLI_NOINLINE static void compute_special_attributes(const Mesh &mesh,
-                                                    Span<float3> bary_coords,
-                                                    Span<int> looptri_indices,
-                                                    MutableSpan<float3> r_normals,
-                                                    MutableSpan<int> r_ids,
-                                                    MutableSpan<float3> r_rotations)
+template<typename T>
+BLI_NOINLINE static void interpolate_attribute_point(const Mesh &mesh,
+                                                     const Span<float3> bary_coords,
+                                                     const Span<int> looptri_indices,
+                                                     const Span<T> data_in,
+                                                     MutableSpan<T> data_out)
 {
+  BLI_assert(data_in.size() == mesh.totvert);
   Span<MLoopTri> looptris = get_mesh_looptris(mesh);
+
   for (const int i : bary_coords.index_range()) {
     const int looptri_index = looptri_indices[i];
     const MLoopTri &looptri = looptris[looptri_index];
@@ -233,20 +236,111 @@ BLI_NOINLINE static void compute_special_attributes(const Mesh &mesh,
     const int v0_index = mesh.mloop[looptri.tri[0]].v;
     const int v1_index = mesh.mloop[looptri.tri[1]].v;
     const int v2_index = mesh.mloop[looptri.tri[2]].v;
-    const float3 v0_pos = mesh.mvert[v0_index].co;
-    const float3 v1_pos = mesh.mvert[v1_index].co;
-    const float3 v2_pos = mesh.mvert[v2_index].co;
 
-    r_ids[i] = (int)(bary_coord.hash()) + looptri_index;
-    normal_tri_v3(r_normals[i], v0_pos, v1_pos, v2_pos);
-    r_rotations[i] = normal_to_euler_rotation(r_normals[i]);
+    const T &v0 = data_in[v0_index];
+    const T &v1 = data_in[v1_index];
+    const T &v2 = data_in[v2_index];
+
+    const T interpolated_value = attribute_math::mix3(bary_coord, v0, v1, v2);
+    data_out[i] = interpolated_value;
   }
 }
 
-BLI_NOINLINE static void add_remaining_point_attributes(const Mesh &mesh,
-                                                        GeometryComponent &component,
-                                                        Span<float3> bary_coords,
-                                                        Span<int> looptri_indices)
+template<typename T>
+BLI_NOINLINE static void interpolate_attribute_corner(const Mesh &mesh,
+                                                      const Span<float3> bary_coords,
+                                                      const Span<int> looptri_indices,
+                                                      const Span<T> data_in,
+                                                      MutableSpan<T> data_out)
+{
+  BLI_assert(data_in.size() == mesh.totloop);
+  Span<MLoopTri> looptris = get_mesh_looptris(mesh);
+
+  for (const int i : bary_coords.index_range()) {
+    const int looptri_index = looptri_indices[i];
+    const MLoopTri &looptri = looptris[looptri_index];
+    const float3 &bary_coord = bary_coords[i];
+
+    const int loop_index_0 = looptri.tri[0];
+    const int loop_index_1 = looptri.tri[1];
+    const int loop_index_2 = looptri.tri[2];
+
+    const T &v0 = data_in[loop_index_0];
+    const T &v1 = data_in[loop_index_1];
+    const T &v2 = data_in[loop_index_2];
+
+    const T interpolated_value = attribute_math::mix3(bary_coord, v0, v1, v2);
+    data_out[i] = interpolated_value;
+  }
+}
+
+BLI_NOINLINE static void interpolate_attribute(const Mesh &mesh,
+                                               Span<float3> bary_coords,
+                                               Span<int> looptri_indices,
+                                               const StringRef attribute_name,
+                                               const ReadAttribute &attribute_in,
+                                               GeometryComponent &component)
+{
+  const CustomDataType data_type = attribute_in.custom_data_type();
+  const AttributeDomain domain = attribute_in.domain();
+  if (!ELEM(domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_CORNER)) {
+    /* Not supported currently. */
+    return;
+  }
+
+  OutputAttributePtr attribute_out = component.attribute_try_get_for_output(
+      attribute_name, ATTR_DOMAIN_POINT, data_type);
+  if (!attribute_out) {
+    return;
+  }
+
+  attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
+    using T = decltype(dummy);
+
+    Span data_in = attribute_in.get_span<T>();
+    MutableSpan data_out = attribute_out->get_span_for_write_only<T>();
+
+    switch (domain) {
+      case ATTR_DOMAIN_POINT: {
+        interpolate_attribute_point<T>(mesh, bary_coords, looptri_indices, data_in, data_out);
+        break;
+      }
+      case ATTR_DOMAIN_CORNER: {
+        interpolate_attribute_corner<T>(mesh, bary_coords, looptri_indices, data_in, data_out);
+        break;
+      }
+      default: {
+        BLI_assert(false);
+        break;
+      }
+    }
+  });
+  attribute_out.apply_span_and_save();
+}
+
+BLI_NOINLINE static void interpolate_existing_attributes(const MeshComponent &mesh_component,
+                                                         GeometryComponent &component,
+                                                         Span<float3> bary_coords,
+                                                         Span<int> looptri_indices)
+{
+  const Mesh &mesh = *mesh_component.get_for_read();
+
+  Set<std::string> attribute_names = mesh_component.attribute_names();
+  for (StringRefNull attribute_name : attribute_names) {
+    if (ELEM(attribute_name, "position", "normal", "id")) {
+      continue;
+    }
+
+    ReadAttributePtr attribute_in = mesh_component.attribute_try_get_for_read(attribute_name);
+    interpolate_attribute(
+        mesh, bary_coords, looptri_indices, attribute_name, *attribute_in, component);
+  }
+}
+
+BLI_NOINLINE static void compute_special_attributes(const Mesh &mesh,
+                                                    GeometryComponent &component,
+                                                    Span<float3> b

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list