[Bf-blender-cvs] [5b8cd24863d] temp-geometry-nodes-curve-deform-node: Curve deform working slightly better

Hans Goudey noreply at git.blender.org
Fri Jun 4 23:35:44 CEST 2021


Commit: 5b8cd24863dc9a66d0847fd3cbfcc8563723b87d
Author: Hans Goudey
Date:   Fri Jun 4 17:22:16 2021 -0400
Branches: temp-geometry-nodes-curve-deform-node
https://developer.blender.org/rB5b8cd24863dc9a66d0847fd3cbfcc8563723b87d

Curve deform working slightly better

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

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

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

diff --git a/source/blender/blenkernel/BKE_spline.hh b/source/blender/blenkernel/BKE_spline.hh
index a0a6834a652..92aa9313ef7 100644
--- a/source/blender/blenkernel/BKE_spline.hh
+++ b/source/blender/blenkernel/BKE_spline.hh
@@ -172,13 +172,9 @@ class Spline {
   blender::Array<float> sample_uniform_index_factors(const int samples_size) const;
 
   struct Parameter {
-    float factor;
+    /* Used as an "index factor" after the function. */
+    float length;
     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;
diff --git a/source/blender/blenkernel/intern/spline_base.cc b/source/blender/blenkernel/intern/spline_base.cc
index 316ca04b438..45238c2a45b 100644
--- a/source/blender/blenkernel/intern/spline_base.cc
+++ b/source/blender/blenkernel/intern/spline_base.cc
@@ -313,45 +313,38 @@ 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();
 
+  {
+    float last = 0.0f;
+    for (const Spline::Parameter &parameter : sample_index_factors) {
+      /* Parameters must be provided in increasing order. */
+      BLI_assert(parameter.length >= last);
+      last = parameter.length;
+    }
+    /* Parameters must be in the 0-total_length range. */
+    BLI_assert(last <= total_length);
+    BLI_assert(sample_index_factors.first().length >= 0.0f);
+  }
+
   /* 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;
+  int i_evaluated = 0;
+  for (const int i_sample : sample_index_factors.index_range()) {
+    const float sample_length = sample_index_factors[i_sample].length;
+
+    /* Skip over every evaluated point that fits before this sample. */
+    while (lengths[i_evaluated] < sample_length) {
+      prev_length = lengths[i_evaluated];
+      i_evaluated++;
     }
 
-    prev_length = length;
+    const float factor = (sample_length - prev_length) / (lengths[i_evaluated] - prev_length);
+    sample_index_factors[i_sample].length = i_evaluated + factor;
   }
 }
 
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 2b64d08ca04..4e73e767f6b 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_deform.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_deform.cc
@@ -92,12 +92,10 @@ static void geo_node_curve_deform_update(bNodeTree *UNUSED(ntree), bNode *node)
 }
 
 static void spline_deform(const Spline &spline,
-                          MutableSpan<Spline::Parameter> parameters,
-                          VMutableArray<float3> &positions)
+                          Span<Spline::Parameter> index_factors,
+                          const int axis_index,
+                          MutableSpan<float3> positions)
 {
-  spline.sample_parameters_to_index_factors(parameters);
-  MutableSpan<Spline::Parameter> index_factors = std::move(parameters);
-
   Span<float3> spline_positions = spline.evaluated_positions();
   Span<float3> spline_tangents = spline.evaluated_tangents();
   Span<float3> spline_normals = spline.evaluated_normals();
@@ -105,24 +103,84 @@ static void spline_deform(const Spline &spline,
 
   parallel_for(positions.index_range(), 1024, [&](IndexRange range) {
     for (const int i : range) {
+      const int i_position = index_factors[i].data_index;
+      float3 position = positions[i_position];
+      position[axis_index] = 0.0f;
+
       const Spline::LookupResult interp = spline.lookup_data_from_index_factor(
-          index_factors[i].factor);
+          index_factors[i].length);
       const int index = interp.evaluated_index;
       const int next_index = interp.next_evaluated_index;
+      const float factor = interp.factor;
 
       float4x4 matrix = float4x4::from_normalized_axis_data(
-          spline_positions[index], spline_normals[index], spline_tangents[index]);
-      matrix.apply_scale(radii[index]);
+          {0, 0, 0},
+          float3::interpolate(spline_normals[index], spline_normals[next_index], factor)
+              .normalized(),
+          float3::interpolate(spline_tangents[index], spline_tangents[next_index], factor)
+              .normalized());
+      matrix.apply_scale(interpf(radii[next_index], radii[index], factor));
+
+      positions[i_position] = matrix * position;
+      positions[i_position] += float3::interpolate(
+          spline_positions[index], spline_positions[next_index], factor);
+    }
+  });
+}
 
-      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 int axis_to_index(const GeometryNodeCurveDeformPositionAxis axis)
+{
+  switch (axis) {
+    case GEO_NODE_CURVE_DEFORM_POSX:
+    case GEO_NODE_CURVE_DEFORM_NEGX:
+      return 0;
+    case GEO_NODE_CURVE_DEFORM_POSY:
+    case GEO_NODE_CURVE_DEFORM_NEGY:
+      return 1;
+    case GEO_NODE_CURVE_DEFORM_POSZ:
+    case GEO_NODE_CURVE_DEFORM_NEGZ:
+      return 2;
+  }
+  BLI_assert_unreachable();
+  return -1;
+}
 
-      const float4x4 deform_matrix = float4x4::interpolate(matrix, next_matrix, interp.factor);
+static bool axis_is_negative(const GeometryNodeCurveDeformPositionAxis axis)
+{
+  switch (axis) {
+    case GEO_NODE_CURVE_DEFORM_POSX:
+    case GEO_NODE_CURVE_DEFORM_POSY:
+    case GEO_NODE_CURVE_DEFORM_POSZ:
+      return false;
+    case GEO_NODE_CURVE_DEFORM_NEGX:
+    case GEO_NODE_CURVE_DEFORM_NEGY:
+    case GEO_NODE_CURVE_DEFORM_NEGZ:
+      return true;
+  }
+  BLI_assert_unreachable();
+  return false;
+}
 
-      positions[parameters[i].data_index] = deform_matrix * positions[parameters[i].data_index];
+static float find_upper_bound(Span<float3> positions, const int index)
+{
+  float max = FLT_MIN;
+  for (const float3 &position : positions) {
+    if (position[index] > max) {
+      max = position[index];
     }
-  });
+  }
+  return max;
+}
+
+static float find_lower_bound(Span<float3> positions, const int index)
+{
+  float min = FLT_MAX;
+  for (const float3 &position : positions) {
+    if (position[index] < min) {
+      min = position[index];
+    }
+  }
+  return min;
 }
 
 static void execute_on_component(const GeoNodeExecParams &params,
@@ -131,38 +189,47 @@ static void execute_on_component(const GeoNodeExecParams &params,
 {
   const NodeGeometryCurveDeform &node_storage = *(NodeGeometryCurveDeform *)params.node().storage;
   const GeometryNodeCurveDeformMode mode = (GeometryNodeCurveDeformMode)node_storage.input_mode;
+  const GeometryNodeCurveDeformPositionAxis axis = (GeometryNodeCurveDeformPositionAxis)
+                                                       node_storage.position_axis;
+  const int axis_index = axis_to_index(axis);
 
   if (curve.splines().size() == 0) {
-    params.error_message_add(NodeWarningType::Error, TIP_("Curve does not contain a spline"));
+    BLI_assert_unreachable();
     return;
   }
 
+  const Spline &spline = *curve.splines().first();
+  const float total_length = spline.length();
+
   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});
+  OutputAttribute_Typed<float3> position_attribute =
+      component.attribute_try_get_for_output<float3>("position", ATTR_DOMAIN_POINT, {0, 0, 0});
+  MutableSpan<float3> positions = position_attribute.as_span();
 
   Array<Spline::Parameter> parameters(size);
 
   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 }
-        //   }
-        // });
-        break;
-      case GEO_NODE_CURVE_DEFORM_POSY:
-        break;
-      case GEO_NODE_CURVE_DEFORM_POSZ:
-        break;
-      case GEO_NODE_CURVE_DEFORM_NEGX:
-        break;
-      case GEO_NODE_CURVE_DEFORM_NEGY:
-        break;
-      case GEO_NODE_CURVE_DEFORM_NEGZ:
-        break;
+    if (axis_is_negative(axis)) {
+      parallel_for(positions.index_range(), 4096, [&](IndexRange range) {
+        for (const int i : range) {
+          parameters[i] = {std::clamp(positions[i][axis_index], 0.0f, total_length), i};
+        }
+      });
+    }
+    else {
+      parallel_for(positions.index_range(), 4096, [&](IndexRange range) {
+        for (const int i : range) {
+          parameters[i] = {total_length - std::clamp(positions[i][axis_index], 0.0f, total_length),
+                           i};
+        }
+      });
  

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list