[Bf-blender-cvs] [073bf63a9db] geometry-nodes-curve-support: Geometry Nodes Curves: Cleanup, progres on evaluation for bezier splines

Hans Goudey noreply at git.blender.org
Mon Apr 5 06:09:26 CEST 2021


Commit: 073bf63a9dbe69a3f2a6c8899832ade978d7cfc5
Author: Hans Goudey
Date:   Sun Apr 4 23:09:20 2021 -0500
Branches: geometry-nodes-curve-support
https://developer.blender.org/rB073bf63a9dbe69a3f2a6c8899832ade978d7cfc5

Geometry Nodes Curves: Cleanup, progres on evaluation for bezier splines

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

M	source/blender/blenkernel/BKE_derived_curve.hh
M	source/blender/blenkernel/intern/derived_curve.cc
M	source/blender/blenlib/BLI_float3.hh
M	source/blender/blenlib/BLI_span.hh
M	source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
M	source/blender/nodes/geometry/nodes/node_geo_transform.cc

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

diff --git a/source/blender/blenkernel/BKE_derived_curve.hh b/source/blender/blenkernel/BKE_derived_curve.hh
index bbe06eb6a0e..0f0b228b7ac 100644
--- a/source/blender/blenkernel/BKE_derived_curve.hh
+++ b/source/blender/blenkernel/BKE_derived_curve.hh
@@ -29,33 +29,23 @@
 
 struct Curve;
 
-enum class BezierHandleType {
-  Free,
-  Auto,
-  Vector,
-  Align,
-};
-
-struct ControlPoint {
+struct BezierPoint {
+  enum HandleType {
+    Free,
+    Auto,
+    Vector,
+    Align,
+  };
+  blender::float3 handle_position_a;
   blender::float3 position;
+  blender::float3 handle_position_b;
+  HandleType handle_type_a;
+  HandleType handle_type_b;
   float radius;
   /* User defined tilt in radians, added on top of the auto-calculated tilt. */
   float tilt;
 };
 
-struct ControlPointBezier : ControlPoint {
-  blender::float3 handle_position_a;
-  blender::float3 handle_position_b;
-  BezierHandleType handle_type_a;
-  BezierHandleType handle_type_b;
-};
-
-struct ControlPointNURBS : ControlPoint {
-  blender::float3 position;
-  float radius;
-  float weight;
-};
-
 class Spline {
  public:
   enum Type {
@@ -73,23 +63,26 @@ class Spline {
   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<ControlPointBezier> control_points;
+  blender::Vector<BezierPoint> control_points;
   int resolution_u;
 
   static constexpr inline Type static_type = Spline::Type::Bezier;
 
  private:
-  bool cache_dirty = true;
-
-  int32_t flag; /* Cyclic, smooth. */
+  bool is_cyclic = false;
 
-  std::mutex cache_mutex;
-  blender::Vector<blender::float3> evaluated_spline_cache;
+  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
@@ -117,15 +110,36 @@ class BezierSpline : public Spline {
   blender::Span<blender::float3> evaluated_positions() const final
   {
     this->ensure_evaluation_cache();
-    return evaluated_spline_cache;
+    return evaluated_positions_cache;
+  }
+
+  blender::Span<blender::float3> evaluated_tangents() const final
+  {
+    this->ensure_evaluation_cache();
+    return evaluated_tangents_cache;
+  }
+
+  blender::Span<blender::float3> evaluated_normals() const final
+  {
+    this->ensure_evaluation_cache();
+    return evaluated_normals_cache;
   }
 
   ~BezierSpline() = default;
 };
 
+struct NURBSPoint {
+  blender::float3 position;
+  float radius;
+  float weight;
+
+  /* User defined tilt in radians, added on top of the auto-calculated tilt. */
+  float tilt;
+};
+
 class SplineNURBS : public Spline {
  public:
-  blender::Vector<ControlPointNURBS> control_points;
+  blender::Vector<NURBSPoint> control_points;
   int32_t flag; /* Cyclic, smooth. */
   int resolution_u;
   uint8_t order;
@@ -156,6 +170,16 @@ class SplineNURBS : public Spline {
   {
     return {};
   }
+
+  blender::Span<blender::float3> evaluated_tangents() const final
+  {
+    return {};
+  }
+
+  blender::Span<blender::float3> evaluated_normals() const final
+  {
+    return {};
+  }
 };
 
 /* Proposed name to be different from DNA type. */
diff --git a/source/blender/blenkernel/intern/derived_curve.cc b/source/blender/blenkernel/intern/derived_curve.cc
index e4efff12308..bcebd07ebff 100644
--- a/source/blender/blenkernel/intern/derived_curve.cc
+++ b/source/blender/blenkernel/intern/derived_curve.cc
@@ -29,24 +29,30 @@ using blender::IndexRange;
 using blender::MutableSpan;
 using blender::Span;
 
-static BezierHandleType handle_type_from_dna_bezt(const eBezTriple_Handle dna_handle_type)
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name General Curve Functions
+ * \{ */
+
+static BezierPoint::HandleType handle_type_from_dna_bezt(const eBezTriple_Handle dna_handle_type)
 {
   switch (dna_handle_type) {
     case HD_FREE:
-      return BezierHandleType::Free;
+      return BezierPoint::Free;
     case HD_AUTO:
-      return BezierHandleType::Auto;
+      return BezierPoint::Auto;
     case HD_VECT:
-      return BezierHandleType::Vector;
+      return BezierPoint::Vector;
     case HD_ALIGN:
-      return BezierHandleType::Align;
+      return BezierPoint::Align;
     case HD_AUTO_ANIM:
-      return BezierHandleType::Auto;
+      return BezierPoint::Auto;
     case HD_ALIGN_DOUBLESIDE:
-      return BezierHandleType::Align;
+      return BezierPoint::Align;
   }
   BLI_assert_unreachable();
-  return BezierHandleType::Free;
+  return BezierPoint::Free;
 }
 
 DCurve *dcurve_from_dna_curve(const Curve &dna_curve)
@@ -61,7 +67,7 @@ DCurve *dcurve_from_dna_curve(const Curve &dna_curve)
     if (nurb->type == CU_BEZIER) {
       BezierSpline *spline = new BezierSpline();
       for (const BezTriple &bezt : Span(nurb->bezt, nurb->pntsu)) {
-        ControlPointBezier point;
+        BezierPoint point;
         point.handle_position_a = bezt.vec[0];
         point.position = bezt.vec[1];
         point.handle_position_b = bezt.vec[2];
@@ -87,12 +93,46 @@ DCurve *dcurve_from_dna_curve(const Curve &dna_curve)
   return curve;
 }
 
-static void evaluate_bezier_part_3d(const float3 point_0,
-                                    const float3 point_1,
-                                    const float3 point_2,
-                                    const float3 point_3,
+/* -------------------------------------------------------------------- */
+/** \name Bezier Spline
+ * \{ */
+
+static bool segment_is_vector(const BezierPoint &point_a, const BezierPoint &point_b)
+{
+  return point_a.handle_type_b == BezierPoint::HandleType::Vector &&
+         point_b.handle_type_a == BezierPoint::HandleType::Vector;
+}
+
+int BezierSpline::evaluated_points_size() const
+{
+  BLI_assert(control_points.size() > 0);
+
+  int total_len = 1;
+  for (const int i : IndexRange(1, this->control_points.size() - 1)) {
+    const BezierPoint &point_prev = this->control_points[i - 1];
+    const BezierPoint &point = this->control_points[i];
+    if (segment_is_vector(point_prev, point)) {
+      total_len += 1;
+    }
+    else {
+      total_len += this->resolution_u;
+    }
+  }
+
+  if (!this->is_cyclic) {
+    total_len++;
+  }
+
+  return total_len;
+}
+
+static void evaluate_bezier_part_3d(const float3 &point_0,
+                                    const float3 &point_1,
+                                    const float3 &point_2,
+                                    const float3 &point_3,
                                     MutableSpan<float3> result)
 {
+  /* TODO: This can probably be vectorized... no one has done this already? */
   float *data = (float *)result.data();
   for (const int axis : {0, 1, 2}) {
     BKE_curve_forward_diff_bezier(point_0[axis],
@@ -105,61 +145,161 @@ static void evaluate_bezier_part_3d(const float3 point_0,
   }
 }
 
-int BezierSpline::evaluated_points_size() const
+static void evaluate_segment_positions(const BezierPoint &point,
+                                       const BezierPoint &next,
+                                       const int resolution,
+                                       int &offset,
+                                       MutableSpan<float3> positions)
 {
-  BLI_assert(control_points.size() > 0);
+  if (segment_is_vector(point, next)) {
+    positions[offset] = point.position;
+    offset++;
+  }
+  else {
+    evaluate_bezier_part_3d(point.position,
+                            point.handle_position_b,
+                            next.handle_position_a,
+                            next.position,
+                            positions.slice(offset, resolution));
+    offset += resolution;
+  }
+}
 
-  int total_len = 1;
-  for (const int i : IndexRange(1, this->control_points.size() - 1)) {
-    const ControlPointBezier &point_prev = this->control_points[i - 1];
-    const ControlPointBezier &point = this->control_points[i];
-    if (point_prev.handle_type_b == BezierHandleType::Vector &&
-        point.handle_type_a == BezierHandleType::Vector) {
-      total_len += 1;
+static void evaluate_positions(Span<BezierPoint> control_points,
+                               const int resolution,
+                               const bool is_cyclic,
+                               MutableSpan<float3> positions)
+{
+  int offset = 0;
+  for (const int i : IndexRange(1, control_points.size() - 1)) {
+    const BezierPoint &point_prev = control_points[i - 1];
+    const BezierPoint &point = control_points[i];
+    evaluate_segment_positions(point_prev, point, resolution, offset, positions);
+  }
+
+  if (is_cyclic) {
+    const BezierPoint &last_point = control_points.last();
+    const BezierPoint &first_point = control_points.first();
+    evaluate_segment_positions(last_point, first_point, resolution, offset, positions);
+  }
+  else {
+    /* Since evaulating the bezier doesn't add the final point's position,
+     * it must be added manually in the non-cyclic case. */
+    positions[offset] = control_points.last().position;
+    offset++;
+  }
+
+  BLI_assert(offset == positions.size());
+}
+
+static float3 direction_bisect(const float3 &prev, const float3 &middle, const float3 &next)
+{
+  const float3 dir_prev = (middle - prev).normalized();
+  const float3 dir_next = (next - middle).normalized();
+
+  return (dir_prev + dir_next).normalized();
+}
+
+static void calculate_tangents(Span<BezierPoint> control_points,
+                               Span<float3> positions,
+                               const bool is_cyclic,
+                               MutableSpan<float3> tangents)
+{
+  for (const int i : IndexRange(1, positions.size() - 2)) {
+    tangents[i] = direction_bisect(positions[i - 1], posi

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list