[Bf-blender-cvs] [399aed9a81d] geometry-nodes-curve-support: Splines: Fix interpolation for bezier splines

Hans Goudey noreply at git.blender.org
Mon Apr 26 21:17:31 CEST 2021


Commit: 399aed9a81d17960a0a0cbec7f145bf0bcb1868b
Author: Hans Goudey
Date:   Mon Apr 26 14:17:25 2021 -0500
Branches: geometry-nodes-curve-support
https://developer.blender.org/rB399aed9a81d17960a0a0cbec7f145bf0bcb1868b

Splines: Fix interpolation for bezier splines

Also parallelize some of the calculations, since I was reworking
how the mapping was calculated anyway. I still haven't tuned the
grain size.

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

M	source/blender/blenkernel/BKE_spline.hh
M	source/blender/blenkernel/intern/spline_bezier.cc
M	source/blender/blenkernel/intern/spline_nurbs.cc

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

diff --git a/source/blender/blenkernel/BKE_spline.hh b/source/blender/blenkernel/BKE_spline.hh
index 4e4b6eed156..c06273db828 100644
--- a/source/blender/blenkernel/BKE_spline.hh
+++ b/source/blender/blenkernel/BKE_spline.hh
@@ -90,18 +90,6 @@ class Spline {
   Spline(Spline &other)
       : type_(other.type_), is_cyclic(other.is_cyclic), normal_mode(other.normal_mode)
   {
-    if (!other.tangent_cache_dirty_) {
-      evaluated_tangents_cache_ = other.evaluated_tangents_cache_;
-      tangent_cache_dirty_ = false;
-    }
-    if (!other.normal_cache_dirty_) {
-      evaluated_normals_cache_ = other.evaluated_normals_cache_;
-      normal_cache_dirty_ = false;
-    }
-    if (!other.length_cache_dirty_) {
-      evaluated_lengths_cache_ = other.evaluated_lengths_cache_;
-      length_cache_dirty_ = false;
-    }
   }
 
   virtual SplinePtr copy() const = 0;
@@ -188,12 +176,19 @@ class BezierSpline final : public Spline {
   blender::Vector<blender::float3> handle_positions_end_;
   blender::Vector<float> radii_;
   blender::Vector<float> tilts_;
-  int resolution_u_;
+  int resolution_;
 
-  mutable bool base_cache_dirty_ = true;
-  mutable std::mutex base_cache_mutex_;
-  mutable blender::Vector<blender::float3> evaluated_positions_cache_;
-  mutable blender::Vector<float> evaluated_mappings_cache_;
+  mutable bool offset_cache_dirty_ = true;
+  mutable std::mutex offset_cache_mutex_;
+  mutable blender::Vector<int> offset_cache_;
+
+  mutable bool position_cache_dirty_ = true;
+  mutable std::mutex position_cache_mutex_;
+  mutable blender::Vector<blender::float3> evaluated_position_cache_;
+
+  mutable bool mapping_cache_dirty_ = true;
+  mutable std::mutex mapping_cache_mutex_;
+  mutable blender::Vector<float> evaluated_mapping_cache_;
 
  public:
   virtual SplinePtr copy() const final;
@@ -207,13 +202,8 @@ class BezierSpline final : public Spline {
         handle_positions_end_(other.handle_positions_end_),
         radii_(other.radii_),
         tilts_(other.tilts_),
-        resolution_u_(other.resolution_u_)
+        resolution_(other.resolution_)
   {
-    if (!other.base_cache_dirty_) {
-      evaluated_positions_cache_ = other.evaluated_positions_cache_;
-      evaluated_mappings_cache_ = other.evaluated_mappings_cache_;
-      base_cache_dirty_ = false;
-    }
   }
 
   int size() const final;
@@ -256,6 +246,7 @@ class BezierSpline final : public Spline {
   void mark_cache_invalid() final;
   int evaluated_points_size() const final;
 
+  blender::Span<int> control_point_offsets() const;
   blender::Span<float> evaluated_mappings() const;
   blender::Span<blender::float3> evaluated_positions() const final;
   struct InterpolationData {
@@ -268,18 +259,13 @@ class BezierSpline final : public Spline {
   virtual blender::fn::GVArrayPtr interpolate_to_evaluated_points(
       const blender::fn::GVArray &source_data) const;
 
- protected:
-  void correct_final_tangents() const;
-
  private:
   void correct_end_tangents() const final;
   bool segment_is_vector(const int start_index) const;
   void evaluate_bezier_segment(const int index,
                                const int next_index,
-                               int &offset,
-                               blender::MutableSpan<blender::float3> positions,
-                               blender::MutableSpan<float> mappings) const;
-  void evaluate_bezier_position_and_mapping() const;
+                               blender::MutableSpan<blender::float3> positions) const;
+  blender::Array<int> evaluated_point_offsets() const;
 };
 
 /**
@@ -307,7 +293,7 @@ class NURBSpline final : public Spline {
   blender::Vector<float> radii_;
   blender::Vector<float> tilts_;
   blender::Vector<float> weights_;
-  int resolution_u_;
+  int resolution_;
   uint8_t order_;
 
   mutable bool knots_dirty_ = true;
@@ -316,7 +302,7 @@ class NURBSpline final : public Spline {
 
   mutable bool position_cache_dirty_ = true;
   mutable std::mutex position_cache_mutex_;
-  mutable blender::Vector<blender::float3> evaluated_positions_cache_;
+  mutable blender::Vector<blender::float3> evaluated_position_cache_;
 
   mutable bool basis_cache_dirty_ = true;
   mutable std::mutex basis_cache_mutex_;
@@ -331,7 +317,7 @@ class NURBSpline final : public Spline {
         radii_(other.radii_),
         tilts_(other.tilts_),
         weights_(other.weights_),
-        resolution_u_(other.resolution_u_),
+        resolution_(other.resolution_),
         order_(other.order_)
   {
   }
diff --git a/source/blender/blenkernel/intern/spline_bezier.cc b/source/blender/blenkernel/intern/spline_bezier.cc
index dea91b2c0fd..4a3f5cdbf19 100644
--- a/source/blender/blenkernel/intern/spline_bezier.cc
+++ b/source/blender/blenkernel/intern/spline_bezier.cc
@@ -16,6 +16,7 @@
 
 #include "BLI_array.hh"
 #include "BLI_span.hh"
+#include "BLI_task.hh"
 
 #include "BKE_spline.hh"
 
@@ -46,12 +47,12 @@ int BezierSpline::size() const
 
 int BezierSpline::resolution() const
 {
-  return this->resolution_u_;
+  return this->resolution_;
 }
 
 void BezierSpline::set_resolution(const int value)
 {
-  this->resolution_u_ = value;
+  this->resolution_ = value;
   this->mark_cache_invalid();
 }
 
@@ -197,7 +198,9 @@ bool BezierSpline::segment_is_vector(const int index) const
 
 void BezierSpline::mark_cache_invalid()
 {
-  this->base_cache_dirty_ = true;
+  this->offset_cache_dirty_ = true;
+  this->position_cache_dirty_ = true;
+  this->mapping_cache_dirty_ = true;
   this->tangent_cache_dirty_ = true;
   this->normal_cache_dirty_ = true;
   this->length_cache_dirty_ = true;
@@ -205,45 +208,15 @@ void BezierSpline::mark_cache_invalid()
 
 int BezierSpline::evaluated_points_size() const
 {
-  BLI_assert(this->size() > 0);
-#ifndef DEBUG
-  if (!this->base_cache_dirty_) {
-    /* In a non-debug build, assume that the cache size has not changed, and that any operation
-     * that would cause the cache to change its length would also mark the cache dirty. This
-     * assumption is checked at the end of this function in a debug build. */
-    return this->evaluated_positions_cache_.size();
-  }
-#endif
-
-  int total_len = 0;
-  for (const int i : IndexRange(this->size() - 1)) {
-    if (this->segment_is_vector(i)) {
-      total_len += 1;
-    }
-    else {
-      total_len += this->resolution_u_;
-    }
-  }
+  const int points_len = this->size();
+  BLI_assert(points_len > 0);
 
+  const int last_offset = this->control_point_offsets().last();
   if (this->is_cyclic) {
-    if (segment_is_vector(this->size() - 1)) {
-      total_len++;
-    }
-    else {
-      total_len += this->resolution_u_;
-    }
-  }
-  else {
-    /* Since evaulating the bezier doesn't add the final point's position,
-     * it must be added manually in the non-cyclic case. */
-    total_len++;
+    return last_offset + (this->segment_is_vector(points_len - 1) ? 0 : this->resolution_);
   }
 
-  if (!this->base_cache_dirty_) {
-    BLI_assert(this->evaluated_positions_cache_.size() == total_len);
-  }
-
-  return total_len;
+  return last_offset + 1;
 }
 
 /**
@@ -291,95 +264,52 @@ static void bezier_forward_difference_3d(const float3 &point_0,
   }
 }
 
-static void evaluate_segment_mapping(Span<float3> evaluated_positions,
-                                     MutableSpan<float> mappings,
-                                     const int index)
-{
-  float length = 0.0f;
-  mappings[0] = index;
-  for (const int i : IndexRange(1, mappings.size() - 1)) {
-    length += float3::distance(evaluated_positions[i - 1], evaluated_positions[i]);
-    mappings[i] = length;
-  }
-
-  /* To get the factors instead of the accumulated lengths, divide the mapping factors by the
-   * accumulated length. */
-  if (length != 0.0f) {
-    for (float &mapping : mappings) {
-      mapping = mapping / length + index;
-    }
-  }
-}
-
 void BezierSpline::evaluate_bezier_segment(const int index,
                                            const int next_index,
-                                           int &offset,
-                                           MutableSpan<float3> positions,
-                                           MutableSpan<float> mappings) const
+                                           MutableSpan<float3> positions) const
 {
   if (this->segment_is_vector(index)) {
-    positions[offset] = positions_[index];
-    mappings[offset] = index;
-    offset++;
+    positions.first() = this->positions_[index];
   }
   else {
     bezier_forward_difference_3d(this->positions_[index],
                                  this->handle_positions_end_[index],
                                  this->handle_positions_start_[next_index],
                                  this->positions_[next_index],
-                                 positions.slice(offset, this->resolution_u_));
-    evaluate_segment_mapping(positions.slice(offset, this->resolution_u_),
-                             mappings.slice(offset, this->resolution_u_),
-                             index);
-    offset += this->resolution_u_;
+                                 positions);
   }
 }
 
-void BezierSpline::evaluate_bezier_position_and_mapping() const
+/**
+ * Returns access to a cache of offsets into the evaluated point array for each control point.
+ * This is important because while most control point edges generate the number of edges specified
+ * by the resolution, vector segments only generate one edge.
+ */
+Span<int> BezierSpline::control_point_offsets() const
 {
-  if (!this->base_cache_dirty_) {
-    return;
+  if (!this->offset_cache_dirty_) {
+    return this->offset_cache_;
   }
 
-  std::lock_guard lock{this->base_cache_mutex_};
-  if (!this->base_cache_dirty_) {
-    return;
+  std::lock_guard lock{this->offset_cache_mutex_};
+  if (!this->offset_cache_dirty_) {
+    return this->offset_cache_;
   }
 
-  const int total = this->evaluated_points_size();
-  this->evaluated_positions_cache_.resize(total);
-  this->evaluated_mappings_cache_.resize(total);
+  const int points_len = this->size();
+  this->offset_cache_.resize(points_len);
 
-  MutableSpan<float3> positions = this->evaluated_positions_cache_;
-  MutableSpan<float> mappings = this->evaluated_mappings_cache_;
+  MutableSpan<int> offsets

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list