[Bf-blender-cvs] [4cc8f098430] temp-geometry-nodes-curve-deform-node: Progress, theoretically working for attribute mode, needs debugging

Hans Goudey noreply at git.blender.org
Fri May 28 18:40:51 CEST 2021


Commit: 4cc8f098430425d2a4a28087e335a5dbfdd0fa7f
Author: Hans Goudey
Date:   Thu May 27 23:40:30 2021 -0400
Branches: temp-geometry-nodes-curve-deform-node
https://developer.blender.org/rB4cc8f098430425d2a4a28087e335a5dbfdd0fa7f

Progress, theoretically working for attribute mode, needs debugging

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

M	source/blender/blenkernel/BKE_spline.hh
M	source/blender/blenkernel/intern/spline_base.cc
M	source/blender/nodes/geometry/nodes/node_geo_curve_deform.cc
M	source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc

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

diff --git a/source/blender/blenkernel/BKE_spline.hh b/source/blender/blenkernel/BKE_spline.hh
index ef76c699cbb..17908973ea9 100644
--- a/source/blender/blenkernel/BKE_spline.hh
+++ b/source/blender/blenkernel/BKE_spline.hh
@@ -171,6 +171,19 @@ class Spline {
   LookupResult lookup_evaluated_length(const float length) const;
 
   blender::Array<float> sample_uniform_index_factors(const int samples_size) const;
+
+  struct Parameter {
+    float factor;
+    int data_index;
+
+    friend bool operator<(const Parameter &a, const Parameter &b)
+    {
+      return a.factor < b.factor;
+    }
+  };
+  void sample_parameters_to_index_factors(
+      blender::MutableSpan<Parameter> sample_index_factors) const;
+
   LookupResult lookup_data_from_index_factor(const float index_factor) const;
 
   /**
@@ -180,6 +193,11 @@ class Spline {
    */
   virtual blender::fn::GVArrayPtr interpolate_to_evaluated_points(
       const blender::fn::GVArray &source_data) const = 0;
+  template<typename T>
+  blender::fn::GVArrayPtr interpolate_to_evaluated_points(blender::Span<T> source_data) const
+  {
+    return this->interpolate_to_evaluated_points(blender::fn::GVArray_For_GSpan(source_data));
+  }
 
  protected:
   virtual void correct_end_tangents() const = 0;
diff --git a/source/blender/blenkernel/intern/spline_base.cc b/source/blender/blenkernel/intern/spline_base.cc
index 11620a30948..316ca04b438 100644
--- a/source/blender/blenkernel/intern/spline_base.cc
+++ b/source/blender/blenkernel/intern/spline_base.cc
@@ -313,6 +313,48 @@ Array<float> Spline::sample_uniform_index_factors(const int samples_size) const
   return samples;
 }
 
+static void verify_parameters_assert(Span<Spline::Parameter> parameters)
+{
+  float last = 0.0f;
+  for (const Spline::Parameter &parameter : parameters) {
+    BLI_assert(parameter.factor >= last);
+    last = parameter.factor;
+  }
+  BLI_assert(last <= 1.0f);
+}
+
+void Spline::sample_parameters_to_index_factors(MutableSpan<Parameter> sample_index_factors) const
+{
+  const Span<float> lengths = this->evaluated_lengths();
+
+  verify_parameters_assert(sample_index_factors);
+
+  const int samples_size = sample_index_factors.size();
+  const float total_length = this->length();
+
+  /* Store the length at the previous evaluated point in a variable so it can
+   * start out at zero (the lengths array doesn't contain 0 for the first point). */
+  float prev_length = 0.0f;
+  int i_sample = 0;
+  for (const int i_evaluated : IndexRange(this->evaluated_edges_size())) {
+    const float length = lengths[i_evaluated];
+    const float sample_length = sample_index_factors[i_sample].factor * total_length;
+
+    /* Add every sample that fits in this evaluated edge. */
+    while ((sample_length * i_sample) < length && i_sample < samples_size) {
+      const float factor = (sample_length * i_sample - prev_length) / (length - prev_length);
+      sample_index_factors[i_sample].factor = i_evaluated + factor;
+      i_sample++;
+    }
+
+    if (i_sample >= samples_size) {
+      break;
+    }
+
+    prev_length = length;
+  }
+}
+
 Spline::LookupResult Spline::lookup_data_from_index_factor(const float index_factor) const
 {
   const int points_len = this->evaluated_points_size();
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_deform.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_deform.cc
index 881c6876c6f..2b64d08ca04 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_deform.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_deform.cc
@@ -15,6 +15,7 @@
  */
 
 #include "BLI_array.hh"
+#include "BLI_float4x4.hh"
 #include "BLI_task.hh"
 #include "BLI_timeit.hh"
 
@@ -27,14 +28,15 @@
 
 #include "node_geometry_util.hh"
 
+using blender::float4x4;
 using blender::bke::GeometryInstanceGroup;
 
 static bNodeSocketTemplate geo_node_curve_deform_in[] = {
     {SOCK_GEOMETRY, N_("Geometry")},
     {SOCK_GEOMETRY, N_("Curve")},
-    {SOCK_STRING, N_("Parameter")},
-    {SOCK_FLOAT, N_("Parameter"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX},
-    {SOCK_BOOLEAN, N_("Use Radius")},
+    {SOCK_STRING, N_("Factor")},
+    {SOCK_FLOAT, N_("Factor"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX},
+    // {SOCK_BOOLEAN, N_("Use Radius")},
     {-1, ""},
 };
 
@@ -57,7 +59,7 @@ static void geo_node_curve_deform_layout(uiLayout *layout, bContext *UNUSED(C),
   else {
     uiLayoutSetPropSep(layout, true);
     uiLayoutSetPropDecorate(layout, false);
-    uiItemR(layout, ptr, "attribute_input_type", 0, nullptr, ICON_NONE);
+    uiItemR(layout, ptr, "attribute_input_type", 0, IFACE_("Factor"), ICON_NONE);
   }
 }
 
@@ -84,45 +86,71 @@ static void geo_node_curve_deform_update(bNodeTree *UNUSED(ntree), bNode *node)
   nodeSetSocketAvailability(attribute_socket, mode == GEO_NODE_CURVE_DEFORM_ATTRIBUTE);
   update_attribute_input_socket_availabilities(
       *node,
-      "Parameter",
+      "Factor",
       (GeometryNodeAttributeInputMode)node_storage.attribute_input_type,
       mode == GEO_NODE_CURVE_DEFORM_ATTRIBUTE);
 }
 
-namespace {
-struct Parameter {
-  float parameter;
-  int index;
-};
-}  // namespace
-
-static void spline_deform(VArray<float3> &positions, Span<float> parameters, const Spline &spline)
+static void spline_deform(const Spline &spline,
+                          MutableSpan<Spline::Parameter> parameters,
+                          VMutableArray<float3> &positions)
 {
-}
+  spline.sample_parameters_to_index_factors(parameters);
+  MutableSpan<Spline::Parameter> index_factors = std::move(parameters);
 
-struct CurveDeformInput {
-  GeometryNodeAttributeInputMode mode;
-  std::optional<GeometryNodeCurveDeformPositionAxis> position_axis;
-  std::optional<std::string> attribute_name;
-};
+  Span<float3> spline_positions = spline.evaluated_positions();
+  Span<float3> spline_tangents = spline.evaluated_tangents();
+  Span<float3> spline_normals = spline.evaluated_normals();
+  GVArray_Typed<float> radii{spline.interpolate_to_evaluated_points(spline.radii())};
+
+  parallel_for(positions.index_range(), 1024, [&](IndexRange range) {
+    for (const int i : range) {
+      const Spline::LookupResult interp = spline.lookup_data_from_index_factor(
+          index_factors[i].factor);
+      const int index = interp.evaluated_index;
+      const int next_index = interp.next_evaluated_index;
+
+      float4x4 matrix = float4x4::from_normalized_axis_data(
+          spline_positions[index], spline_normals[index], spline_tangents[index]);
+      matrix.apply_scale(radii[index]);
+
+      float4x4 next_matrix = float4x4::from_normalized_axis_data(
+          spline_positions[next_index], spline_normals[next_index], spline_tangents[next_index]);
+      matrix.apply_scale(radii[next_index]);
 
-static void execute_on_component(GeometryComponent &component,
-                                 const CurveDeformInput &input,
-                                 const CurveEval &curve)
+      const float4x4 deform_matrix = float4x4::interpolate(matrix, next_matrix, interp.factor);
+
+      positions[parameters[i].data_index] = deform_matrix * positions[parameters[i].data_index];
+    }
+  });
+}
+
+static void execute_on_component(const GeoNodeExecParams &params,
+                                 const CurveEval &curve,
+                                 GeometryComponent &component)
 {
-  GVArray_Typed<float3> positions = component.attribute_get_for_read<float3>(
+  const NodeGeometryCurveDeform &node_storage = *(NodeGeometryCurveDeform *)params.node().storage;
+  const GeometryNodeCurveDeformMode mode = (GeometryNodeCurveDeformMode)node_storage.input_mode;
+
+  if (curve.splines().size() == 0) {
+    params.error_message_add(NodeWarningType::Error, TIP_("Curve does not contain a spline"));
+    return;
+  }
+
+  const int size = component.attribute_domain_size(ATTR_DOMAIN_POINT);
+  OutputAttribute_Typed<float3> positions = component.attribute_try_get_for_output<float3>(
       "position", ATTR_DOMAIN_POINT, {0, 0, 0});
 
-  Array<Parameter> parameters(positions.size());
+  Array<Spline::Parameter> parameters(size);
 
-  if (input.mode == GEO_NODE_CURVE_DEFORM_POSITION) {
-    switch (*input.position_axis) {
+  if (mode == GEO_NODE_CURVE_DEFORM_POSITION) {
+    switch ((GeometryNodeCurveDeformPositionAxis)node_storage.position_axis) {
       case GEO_NODE_CURVE_DEFORM_POSX:
-        parallel_for(positions.index_range(), 4096, [&](IndexRange range) {
-          for (const int i : range) {
-            parameters[i] = { positions }
-          }
-        });
+        // parallel_for(positions.index_range(), 4096, [&](IndexRange range) {
+        //   for (const int i : range) {
+        //     parameters[i] = { positions }
+        //   }
+        // });
         break;
       case GEO_NODE_CURVE_DEFORM_POSY:
         break;
@@ -136,6 +164,26 @@ static void execute_on_component(GeometryComponent &component,
         break;
     }
   }
+  else {
+    BLI_assert(mode == GEO_NODE_CURVE_DEFORM_ATTRIBUTE);
+    GVArrayPtr attribute = params.get_input_attribute(
+        "Factor", component, ATTR_DOMAIN_POINT, CD_PROP_FLOAT, nullptr);
+    if (!attribute) {
+      return;
+    }
+
+    /* Sanitize attribute input. */
+    GVArray_Typed<float> parameter_attribute{*attribute};
+    for (const int i : IndexRange(size)) {
+      parameters[i] = {std::clamp(parameter_attribute[i], 0.0f, 1.0f), i};
+    }
+  }
+
+  std::sort(parameters.begin(), parameters.end());
+
+  spline_deform(*curve.splines().first(), parameters, *positions);
+
+  positions.save();
 }
 
 static void geo_node_curve_deform_exec(GeoNodeExecParams params)
@@ -144,27 +192,30 @@ static void geo_node_curve_deform_exec(GeoNodeExecParams params)
   GeometrySet curve_geometry_set = params.extract_input<GeometrySet>("Curve");
 
   deform_geometry_set = bke::geometry_set_realize_instances(deform_geometry_set);
+
+  /* TODO: Theoretically this could be easily avoided. */
   curve_geometry_set = bke::geometry_set_realize_instances(curve_geometry_set);
 
   const CurveEval *curve = curve_geometry_set.get_curve_for_read();
   if (curve == nullptr) {
-    params.error_message_add(NodeWarningType::Error, TIP_("Curve input must contain curve data"));
+    params.set_output("Geometry

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list