[Bf-blender-cvs] [ff34a3a6127] geometry-nodes-curve-support: Geometry Nodes Curves: Refactor, mapping from evaluated to control points

Hans Goudey noreply at git.blender.org
Thu Apr 8 07:39:53 CEST 2021


Commit: ff34a3a61273cb0ab357dfddf7d752030f7aa6a1
Author: Hans Goudey
Date:   Thu Apr 8 00:39:46 2021 -0500
Branches: geometry-nodes-curve-support
https://developer.blender.org/rBff34a3a61273cb0ab357dfddf7d752030f7aa6a1

Geometry Nodes Curves: Refactor, mapping from evaluated to control points

Also include some incomplete handling of radius in the curve to mesh node.
I'm not sure how much of the changes will stick around, but the reshuffling
of virtual vs. final methods will stay, and the separated caches probably
makes sense too.

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

M	source/blender/blenkernel/BKE_derived_curve.hh
M	source/blender/blenkernel/intern/derived_curve.cc
M	source/blender/blenlib/BLI_float4x4.hh
M	source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc

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

diff --git a/source/blender/blenkernel/BKE_derived_curve.hh b/source/blender/blenkernel/BKE_derived_curve.hh
index bc8f7bd80c3..355e3881913 100644
--- a/source/blender/blenkernel/BKE_derived_curve.hh
+++ b/source/blender/blenkernel/BKE_derived_curve.hh
@@ -29,6 +29,13 @@
 
 struct Curve;
 
+struct PointMapping {
+  int control_point_index;
+  /* Linear interpolation factor starting at this control point with the index in
+   * `control_point_index`, and ending with the next control point. */
+  float factor;
+};
+
 struct BezierPoint {
   enum HandleType {
     Free,
@@ -36,16 +43,23 @@ struct BezierPoint {
     Vector,
     Align,
   };
+
+  /* The first handle. */
+  HandleType handle_type_a;
   blender::float3 handle_position_a;
+
   blender::float3 position;
-  blender::float3 handle_position_b;
-  HandleType handle_type_a;
+
+  /* The second handle. */
   HandleType handle_type_b;
+  blender::float3 handle_position_b;
+
   float radius;
   /* User defined tilt in radians, added on top of the auto-calculated tilt. */
   float tilt;
 };
 
+/* TODO: Think about storing each data type from each control point separately. */
 class Spline {
  public:
   enum Type {
@@ -56,77 +70,88 @@ class Spline {
   Type type;
   bool is_cyclic = false;
 
+ protected:
+  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_mapping_cache_;
+
+  mutable bool tangent_cache_dirty_ = true;
+  mutable std::mutex tangent_cache_mutex_;
+  mutable blender::Vector<blender::float3> evaluated_tangents_cache_;
+
+  mutable bool normal_cache_dirty_ = true;
+  mutable std::mutex normal_cache_mutex_;
+  mutable blender::Vector<blender::float3> evaluated_normals_cache_;
+
+  mutable bool length_cache_dirty_ = true;
+  mutable std::mutex length_cache_mutex_;
+  mutable blender::Vector<float> evaluated_length_cache_;
+
+ public:
   virtual ~Spline() = default;
 
   virtual int size() const = 0;
   virtual int resolution() const = 0;
   virtual void set_resolution(const int value) = 0;
-  virtual void mark_cache_invalid() = 0;
 
+  virtual void mark_cache_invalid();
   virtual int evaluated_points_size() const = 0;
-  virtual void ensure_evaluation_cache() const = 0;
-  virtual blender::Span<blender::float3> evaluated_positions() const = 0;
-  virtual blender::Span<blender::float3> evaluated_tangents() const = 0;
-  virtual blender::Span<blender::float3> evaluated_normals() const = 0;
-};
-
-class BezierSpline : public Spline {
- public:
-  /* TODO: Figure out if I want to store this as a few separate vectors directly in the spline. */
-  blender::Vector<BezierPoint> control_points;
-  int resolution_u;
 
-  static constexpr inline Type static_type = Spline::Type::Bezier;
-
- private:
-  mutable std::mutex cache_mutex_;
-  mutable bool cache_dirty_ = true;
-  mutable blender::Vector<blender::float3> evaluated_positions_cache_;
-  mutable blender::Vector<blender::float3> evaluated_tangents_cache_;
-  mutable blender::Vector<blender::float3> evaluated_normals_cache_;
-
- public:
-  int size() const final
+  blender::Span<blender::float3> evaluated_positions() const
   {
-    return control_points.size();
+    this->ensure_base_cache();
+    return evaluated_positions_cache_;
   }
-
-  int resolution() const final
+  blender::Span<float> evaluated_length() const
   {
-    return resolution_u;
+    this->ensure_length_cache();
+    return evaluated_length_cache_;
   }
-  void set_resolution(const int value) final
+  blender::Span<blender::float3> evaluated_tangents() const
   {
-    resolution_u = value;
+    this->ensure_tangent_cache();
+    return evaluated_tangents_cache_;
   }
-
-  void mark_cache_invalid() final
+  blender::Span<blender::float3> evaluated_normals() const
   {
-    cache_dirty_ = true;
+    this->ensure_normal_cache();
+    return evaluated_normals_cache_;
   }
 
-  int evaluated_points_size() const final;
-  void ensure_evaluation_cache() const final;
+  /* TODO: I'm not sure this is the best abstraction here. Indeed, all of the `PointMapping`
+   * stuff might be a bit suspect. */
+  float get_evaluated_point_radius(const int index) const;
 
-  blender::Span<blender::float3> evaluated_positions() const final
-  {
-    this->ensure_evaluation_cache();
-    return evaluated_positions_cache_;
-  }
+ protected:
+  virtual void ensure_base_cache() const = 0;
+  virtual void ensure_tangent_cache() const = 0;
+  void ensure_normal_cache() const;
+  void ensure_length_cache() const;
 
-  blender::Span<blender::float3> evaluated_tangents() const final
-  {
-    this->ensure_evaluation_cache();
-    return evaluated_tangents_cache_;
-  }
+  virtual float control_point_radius(const int index) const = 0;
+};
 
-  blender::Span<blender::float3> evaluated_normals() const final
-  {
-    this->ensure_evaluation_cache();
-    return evaluated_normals_cache_;
-  }
+class BezierSpline : public Spline {
+ public:
+  blender::Vector<BezierPoint> control_points;
+
+ private:
+  int resolution_u;
 
+ public:
   ~BezierSpline() = default;
+
+  int size() const final;
+  int resolution() const final;
+  void set_resolution(const int value) final;
+  int evaluated_points_size() const final;
+
+ private:
+  void ensure_base_cache() const final;
+  void ensure_tangent_cache() const final;
+
+  float control_point_radius(const int index) const final;
 };
 
 struct NURBSPoint {
@@ -138,60 +163,39 @@ struct NURBSPoint {
   float tilt;
 };
 
-class SplineNURBS : public Spline {
+class NURBSPline : public Spline {
  public:
   blender::Vector<NURBSPoint> control_points;
+
+ private:
   int32_t flag; /* Cyclic, smooth. */
   int resolution_u;
   uint8_t order;
 
-  int size() const final
-  {
-    return control_points.size();
-  }
-
-  int resolution() const final
-  {
-    return resolution_u;
-  }
-  void set_resolution(const int value) final
-  {
-    resolution_u = value;
-  }
-
-  int evaluated_points_size() const final
-  {
-    return 0;
-  }
-  void ensure_evaluation_cache() const final
-  {
-  }
-
-  blender::Span<blender::float3> evaluated_positions() const final
-  {
-    return {};
-  }
+ public:
+  int size() const final;
+  int resolution() const final;
+  void set_resolution(const int value) final;
+  int evaluated_points_size() const final;
 
-  blender::Span<blender::float3> evaluated_tangents() const final
-  {
-    return {};
-  }
+ protected:
+  void ensure_base_cache() const final;
+  void ensure_tangent_cache() const final;
 
-  blender::Span<blender::float3> evaluated_normals() const final
-  {
-    return {};
-  }
+  float control_point_radius(const int index) const final;
 };
 
 /* Proposed name to be different from DNA type. */
 struct DCurve {
   blender::Vector<Spline *> splines;
-  int32_t flag; /* 2D. */
 
-  /* Attributes. */
-  //   AttributeStorage attributes;
-  //   CustomData *control_point_data;
-  //   CustomData *spline_data;
+  // enum TangentMethod {
+  //   ZUp,
+  //   Minimum,
+  //   Tangent,
+  // };
+
+  // bool is_2d;
 
   ~DCurve()
   {
diff --git a/source/blender/blenkernel/intern/derived_curve.cc b/source/blender/blenkernel/intern/derived_curve.cc
index 5346692cdde..e0f3d0e642a 100644
--- a/source/blender/blenkernel/intern/derived_curve.cc
+++ b/source/blender/blenkernel/intern/derived_curve.cc
@@ -29,8 +29,6 @@ using blender::IndexRange;
 using blender::MutableSpan;
 using blender::Span;
 
-/** \} */
-
 /* -------------------------------------------------------------------- */
 /** \name General Curve Functions
  * \{ */
@@ -66,6 +64,10 @@ DCurve *dcurve_from_dna_curve(const Curve &dna_curve)
   LISTBASE_FOREACH (const Nurb *, nurb, nurbs) {
     if (nurb->type == CU_BEZIER) {
       BezierSpline *spline = new BezierSpline();
+      spline->set_resolution(nurb->resolu);
+      spline->type = Spline::Type::Bezier;
+      spline->is_cyclic = nurb->flagu & CU_NURB_CYCLIC;
+
       for (const BezTriple &bezt : Span(nurb->bezt, nurb->pntsu)) {
         BezierPoint point;
         point.handle_position_a = bezt.vec[0];
@@ -78,12 +80,6 @@ DCurve *dcurve_from_dna_curve(const Curve &dna_curve)
         spline->control_points.append(std::move(point));
       }
 
-      spline->resolution_u = nurb->resolu;
-      // spline.resolution_v = nurb->resolv;
-      spline->type = Spline::Type::Bezier;
-
-      spline->is_cyclic = nurb->flagu & CU_NURB_CYCLIC;
-
       curve->splines.append(spline);
     }
     else if (nurb->type == CU_NURBS) {
@@ -95,10 +91,258 @@ DCurve *dcurve_from_dna_curve(const Curve &dna_curve)
   return curve;
 }
 
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Spline
+ * \{ */
+
+static void accumulate_lengths(Span<float3> positions, MutableSpan<float> r_lengths)
+{
+  float length = 0.0f;
+  r_lengths[0] = length;
+  for (const int i : IndexRange(1, positions.size() - 1)) {
+    r_lengths[i] = length;
+    length += float3::distance(positions[i - 1], positions[i]);
+  }
+}
+
+void Spline::ensure_length_cache() const
+{
+  if (!this->length_cache_dirty_) {
+    return;
+  }
+
+  std::lock_guard<std::mutex> lock(this->length_cache_mutex_);
+  if (!this->length_cache_dirty_) {
+    return;
+  }
+
+  const int total = this->evaluated_points_size();
+  this->evaluated_length_cache_.resize(total);
+
+  Span<float3> positions = this->evaluated_positions();
+  accumulate_lengths(positions, this->evaluated_length_cache_);
+
+  this->length_cache_dirty_ = false;
+}
+
+static float3 initial_normal(const float3 first_tangent)
+{
+  /* TODO: Should be is "almost" zero. */
+  if (first_tangent.is_zero()) {
+    return float3(0.0f, 0.0f, 1.0f);
+  }
+
+  const float3 normal = float3::cross(first_tangent, float3(0.0f, 0.0f, 1.0f));
+  if (!normal.is_zero()) {
+    return normal.normalized();
+  }
+
+  return float3::cross(first_tangent, float3(0.0f, 1.0f, 0.0f)).normalized();
+}
+
+static float3 rotate_around_axis(const float3 dir, const float3 axis, const float angle)
+{
+  // cdef void rotateAroundAxisVec3(Vector3 *target, Vector3 *v, Vector3 *axis, float angle):
+  //   cdef Vector3 n
+  //   normalizeVec3(&n, axis)
+  //   cdef Vector3 d
+  //

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list