[Bf-blender-cvs] [837d630466b] geometry-nodes-curve-support: Splines: Halve the size of the bezier interpolation cache

Hans Goudey noreply at git.blender.org
Sat Apr 24 22:02:13 CEST 2021


Commit: 837d630466bfb1a15b2947987ed65a04de211cda
Author: Hans Goudey
Date:   Sat Apr 24 15:01:32 2021 -0500
Branches: geometry-nodes-curve-support
https://developer.blender.org/rB837d630466bfb1a15b2947987ed65a04de211cda

Splines: Halve the size of the bezier interpolation cache

Use floats to store the control point indices and the interpolation factors.

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

M	source/blender/blenkernel/BKE_spline.hh
M	source/blender/blenkernel/intern/spline_bezier.cc
M	source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
M	source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc

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

diff --git a/source/blender/blenkernel/BKE_spline.hh b/source/blender/blenkernel/BKE_spline.hh
index 21249de57f2..78f0c33861f 100644
--- a/source/blender/blenkernel/BKE_spline.hh
+++ b/source/blender/blenkernel/BKE_spline.hh
@@ -32,23 +32,6 @@
 
 struct Curve;
 
-/**
- * Contains the information necessary to interpolate values from the original control points to
- * evaluated points.
- */
-struct PointMapping {
-  /**
-   * The index of the control point preceding the evaluated point at this index.
-   * For resolutions higher than 1, many evaluated points can share the same value.
-   */
-  int control_point_index;
-  /**
-   * This evaluated point's portion of the total length between the `control_point_index` value
-   * and the next.
-   */
-  float factor;
-};
-
 class Spline;
 using SplinePtr = std::unique_ptr<Spline>;
 
@@ -190,7 +173,7 @@ class BezierSpline final : public Spline {
   mutable bool base_cache_dirty_ = true;
   mutable std::mutex base_cache_mutex_;
   mutable blender::Vector<blender::float3> evaluated_positions_cache_;
-  mutable blender::Vector<PointMapping> evaluated_mappings_cache_;
+  mutable blender::Vector<float> evaluated_mappings_cache_;
 
  public:
   virtual SplinePtr copy() const final;
@@ -253,7 +236,7 @@ class BezierSpline final : public Spline {
   void mark_cache_invalid() final;
   int evaluated_points_size() const final;
 
-  blender::Span<PointMapping> evaluated_mappings() const;
+  blender::Span<float> evaluated_mappings() const;
   blender::Span<blender::float3> evaluated_positions() const final;
 
   virtual blender::fn::GVArrayPtr interpolate_to_evaluated_points(
@@ -269,7 +252,7 @@ class BezierSpline final : public Spline {
                                const int next_index,
                                int &offset,
                                blender::MutableSpan<blender::float3> positions,
-                               blender::MutableSpan<PointMapping> mappings) const;
+                               blender::MutableSpan<float> mappings) const;
   void evaluate_bezier_position_and_mapping() const;
 };
 
diff --git a/source/blender/blenkernel/intern/spline_bezier.cc b/source/blender/blenkernel/intern/spline_bezier.cc
index e7d59d830dc..c065f8f68cc 100644
--- a/source/blender/blenkernel/intern/spline_bezier.cc
+++ b/source/blender/blenkernel/intern/spline_bezier.cc
@@ -296,21 +296,21 @@ static void bezier_forward_difference_3d(const float3 &point_0,
 }
 
 static void evaluate_segment_mapping(Span<float3> evaluated_positions,
-                                     MutableSpan<PointMapping> mappings,
+                                     MutableSpan<float> mappings,
                                      const int index)
 {
   float length = 0.0f;
-  mappings[0] = PointMapping{index, 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] = PointMapping{index, length};
+    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 (PointMapping &mapping : mappings) {
-      mapping.factor /= length;
+    for (float &mapping : mappings) {
+      mapping = mapping / length + index;
     }
   }
 }
@@ -319,11 +319,11 @@ void BezierSpline::evaluate_bezier_segment(const int index,
                                            const int next_index,
                                            int &offset,
                                            MutableSpan<float3> positions,
-                                           MutableSpan<PointMapping> mappings) const
+                                           MutableSpan<float> mappings) const
 {
   if (this->segment_is_vector(index)) {
     positions[offset] = positions_[index];
-    mappings[offset] = PointMapping{index, 0.0f};
+    mappings[offset] = index;
     offset++;
   }
   else {
@@ -355,7 +355,7 @@ void BezierSpline::evaluate_bezier_position_and_mapping() const
   this->evaluated_mappings_cache_.resize(total);
 
   MutableSpan<float3> positions = this->evaluated_positions_cache_;
-  MutableSpan<PointMapping> mappings = this->evaluated_mappings_cache_;
+  MutableSpan<float> mappings = this->evaluated_mappings_cache_;
 
   /* TODO: It would also be possible to store an array of offsets to facilitate parallelism here,
    * maybe it is worth it? */
@@ -372,50 +372,51 @@ void BezierSpline::evaluate_bezier_position_and_mapping() const
     /* Since evaulating the bezier doesn't add the final point's position,
      * it must be added manually in the non-cyclic case. */
     positions[offset] = this->positions_.last();
-    mappings[offset] = PointMapping{i_last - 1, 1.0f};
+    mappings[offset] = i_last;
     offset++;
   }
 
+  if (this->is_cyclic) {
+    if (mappings.last() >= this->size()) {
+      mappings.last() = 0.0f;
+    }
+  }
+
   BLI_assert(offset == positions.size());
 
   this->base_cache_dirty_ = false;
 }
 
 /**
- * Returns non-owning access to the cache of mappings from the evaluated points to
- * the corresponing control points. Unless the spline is cyclic, the last control point
- * index will never be included as an index.
+ * Returns non-owning access to an array of values ontains the information necessary to
+ * interpolate values from the original control points to evaluated points. The control point
+ * index is the integer part of each value, and the factor used for interpolating to the next
+ * control point is the remaining factional part.
  */
-Span<PointMapping> BezierSpline::evaluated_mappings() const
+Span<float> BezierSpline::evaluated_mappings() const
 {
   this->evaluate_bezier_position_and_mapping();
-#ifdef DEBUG
-  if (evaluated_mappings_cache_.last().control_point_index == this->size() - 1) {
-    BLI_assert(this->is_cyclic);
-  }
-#endif
   return this->evaluated_mappings_cache_;
 }
 
 Span<float3> BezierSpline::evaluated_positions() const
 {
   this->evaluate_bezier_position_and_mapping();
-
   return this->evaluated_positions_cache_;
 }
 
 template<typename T>
-static void interpolate_to_evaluated_points_impl(Span<PointMapping> mappings,
+static void interpolate_to_evaluated_points_impl(Span<float> mappings,
                                                  const blender::VArray<T> &source_data,
                                                  MutableSpan<T> result_data)
 {
+  const int points_len = source_data.size();
   blender::attribute_math::DefaultMixer<T> mixer(result_data);
 
   for (const int i : result_data.index_range()) {
-    const PointMapping &mapping = mappings[i];
-    const int index = mapping.control_point_index;
-    const int next_index = (index + 1) % source_data.size();
-    const float factor = mapping.factor;
+    const int index = std::floor(mappings[i]);
+    const int next_index = (index == points_len - 1) ? 0 : index + 1;
+    const float factor = mappings[i] - index;
 
     const T &value = source_data[index];
     const T &next_value = source_data[next_index];
@@ -431,7 +432,7 @@ blender::fn::GVArrayPtr BezierSpline::interpolate_to_evaluated_points(
     const blender::fn::GVArray &source_data) const
 {
   BLI_assert(source_data.size() == this->size());
-  Span<PointMapping> mappings = this->evaluated_mappings();
+  Span<float> mappings = this->evaluated_mappings();
 
   blender::fn::GVArrayPtr new_varray;
   blender::attribute_math::convert_to_static_type(source_data.type(), [&](auto dummy) {
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
index dad5c579a3b..21995295898 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
@@ -59,6 +59,22 @@ static void vert_extrude_to_mesh_data(const Spline &spline,
     edge.v2 = vert_offset + i + 1;
     edge.flag = ME_LOOSEEDGE;
   }
+  // for (const int i : IndexRange(positions.size() - 1)) {
+  //   MEdge &edge = edges[edge_offset++];
+  //   edge.v1 = vert_offset + i * 3;
+  //   edge.v2 = vert_offset + i * 3 + 3;
+  //   edge.flag = ME_LOOSEEDGE;
+
+  //   MEdge &tangent_edge = edges[edge_offset++];
+  //   tangent_edge.v1 = vert_offset + i * 3;
+  //   tangent_edge.v2 = vert_offset + i * 3 + 1;
+  //   tangent_edge.flag = ME_LOOSEEDGE;
+
+  //   MEdge &normal_edge = edges[edge_offset++];
+  //   normal_edge.v1 = vert_offset + i * 3;
+  //   normal_edge.v2 = vert_offset + i * 3 + 2;
+  //   normal_edge.flag = ME_LOOSEEDGE;
+  // }
 
   if (spline.is_cyclic) {
     MEdge &edge = edges[edge_offset++];
@@ -71,6 +87,18 @@ static void vert_extrude_to_mesh_data(const Spline &spline,
     MVert &vert = verts[vert_offset++];
     copy_v3_v3(vert.co, positions[i] + profile_vert);
   }
+  // Span<float3> tangents = spline.evaluated_tangents();
+  // Span<float3> normals = spline.evaluated_normals();
+  // for (const int i : positions.index_range()) {
+  //   MVert &vert = verts[vert_offset++];
+  //   copy_v3_v3(vert.co, positions[i] + profile_vert);
+
+  //   MVert &tangent_vert = verts[vert_offset++];
+  //   copy_v3_v3(tangent_vert.co, tangents[i] + vert.co);
+
+  //   MVert &normal_vert = verts[vert_offset++];
+  //   copy_v3_v3(normal_vert.co, normals[i] + vert.co);
+  // }
 }
 
 static void mark_edges_sharp(MutableSpan<MEdge> edges)
@@ -202,11 +230,11 @@ static void spline_extrude_to_mesh_data(const Spline &spline,
   /* Mark edge loops from sharp vector control points sharp. */
   if (profile_spline.type() == Spline::Bezier) {
     const BezierSpline &bezier_spline = static_cast<const BezierSpline &>(profile_spline);
-    Span<PointMapping> mappings = bezier_spline.evaluated_mappings();
+    Span<float> mappings = bezier_spline.evaluated_mappings();
     for (const int i_profile : mappings.index_range()) {
-      const PointMapping &mapping = mappings[i_profile];
-      if (mapping.factor == 0.0f) {
-        if (bezier_spline.point_is_sharp(mapping.control_point_index)) {
+      const float index = std::floor(mappings[i_profile]);
+      if ((mappings[i_profile] - index) == 0.0f) {
+        if (bezier

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list