[Bf-blender-cvs] [bb04d1c2c83] geometry-nodes-curve-support: Geometry Nodes Curves: Add structure for curve trim node

Hans Goudey noreply at git.blender.org
Mon Apr 12 06:28:50 CEST 2021


Commit: bb04d1c2c83b3c31a8770108a9984409e2f94359
Author: Hans Goudey
Date:   Sun Apr 11 23:28:40 2021 -0500
Branches: geometry-nodes-curve-support
https://developer.blender.org/rBbb04d1c2c83b3c31a8770108a9984409e2f94359

Geometry Nodes Curves: Add structure for curve trim node

The node doesn't do anything yet because the last level needs to
be implemented, but the majority of the necessary changes are done.

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

M	release/scripts/startup/nodeitems_builtins.py
M	source/blender/blenkernel/BKE_derived_curve.hh
M	source/blender/blenkernel/BKE_node.h
M	source/blender/blenkernel/intern/derived_curve.cc
M	source/blender/blenkernel/intern/geometry_component_curve.cc
M	source/blender/blenkernel/intern/node.cc
M	source/blender/makesdna/DNA_node_types.h
M	source/blender/makesrna/intern/rna_nodetree.c
M	source/blender/nodes/CMakeLists.txt
M	source/blender/nodes/NOD_geometry.h
M	source/blender/nodes/NOD_static_types.h
M	source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
M	source/blender/nodes/geometry/nodes/node_geo_curve_transform_test.cc
A	source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc

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

diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index f76d9547ec1..4cb4929b98d 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -507,6 +507,7 @@ geometry_node_categories = [
     GeometryNodeCategory("GEO_CURVE", "Curve", items=[
         NodeItem("GeometryNodeCurveToMesh"),
         NodeItem("GeometryNodeTransformTest"),
+        NodeItem("GeometryNodeCurveTrim"),
     ]),
     GeometryNodeCategory("GEO_GEOMETRY", "Geometry", items=[
         NodeItem("GeometryNodeBoundBox"),
diff --git a/source/blender/blenkernel/BKE_derived_curve.hh b/source/blender/blenkernel/BKE_derived_curve.hh
index 8512cfc022f..57054d8333c 100644
--- a/source/blender/blenkernel/BKE_derived_curve.hh
+++ b/source/blender/blenkernel/BKE_derived_curve.hh
@@ -36,6 +36,7 @@ struct PointMapping {
   float factor;
 };
 
+/* TODO: Think about storing each data type from each control point separately. */
 struct BezierPoint {
   enum HandleType {
     Free,
@@ -65,7 +66,13 @@ struct BezierPoint {
   }
 };
 
-/* TODO: Think about storing each data type from each control point separately. */
+/**
+ * A spline is an abstraction of a curve section, its evaluation methods, and data.
+ * The spline data itself is just control points and a set of attributes.
+ *
+ * Common evaluated data is stored in caches on the spline itself. This way operations on splines
+ * don't need to worry about taking ownership of evaluated data when they don't need to.
+ */
 class Spline {
  public:
   enum Type {
@@ -110,6 +117,7 @@ class Spline {
 
   virtual void mark_cache_invalid();
   virtual int evaluated_points_size() const = 0;
+  int evaluated_edges_size() const;
 
   blender::Span<blender::float3> evaluated_positions() const;
   blender::Span<PointMapping> evaluated_mappings() const;
@@ -117,10 +125,11 @@ class Spline {
   blender::Span<blender::float3> evaluated_tangents() const;
   blender::Span<blender::float3> evaluated_normals() const;
 
-  /* TODO: I'm not sure this is the best abstraction here. Indeed, all of the `PointMapping`
-   * stuff might be a bit suspect. */
+  /* TODO: I'm not sure this is the best abstraction here, maybe we want another cache. */
   float get_evaluated_point_radius(const int index) const;
 
+  void trim_lengths(const float start_length, const float end_length);
+
  protected:
   virtual void correct_end_tangents() const = 0;
   virtual void ensure_base_cache() const = 0;
@@ -188,12 +197,6 @@ class NURBSPline : public Spline {
 struct DCurve {
   blender::Vector<Spline *> splines;
 
-  // enum TangentMethod {
-  //   ZUp,
-  //   Minimum,
-  //   Tangent,
-  // };
-
   // bool is_2d;
 
   // DCurve *copy();
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 6c6f4c539e2..3cbf5147c88 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -1401,6 +1401,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
 #define GEO_NODE_BOUNDING_BOX 1042
 #define GEO_NODE_CURVE_TO_MESH 1043
 #define GEO_NODE_CURVE_TRANSFORM_TEST 1044
+#define GEO_NODE_CURVE_TRIM 1045
 
 /** \} */
 
diff --git a/source/blender/blenkernel/intern/derived_curve.cc b/source/blender/blenkernel/intern/derived_curve.cc
index 9364d68c929..bfc12b8c9cd 100644
--- a/source/blender/blenkernel/intern/derived_curve.cc
+++ b/source/blender/blenkernel/intern/derived_curve.cc
@@ -76,32 +76,42 @@ DCurve *dcurve_from_dna_curve(const Curve &dna_curve)
   curve->splines.reserve(BLI_listbase_count(nurbs));
 
   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];
-        point.position = bezt.vec[1];
-        point.handle_position_b = bezt.vec[2];
-        point.radius = bezt.radius;
-        point.tilt = bezt.tilt;
-        point.handle_type_a = handle_type_from_dna_bezt((eBezTriple_Handle)bezt.h1);
-        point.handle_type_b = handle_type_from_dna_bezt((eBezTriple_Handle)bezt.h2);
-        spline->control_points.append(std::move(point));
+    switch (nurb->type) {
+      case 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];
+          point.position = bezt.vec[1];
+          point.handle_position_b = bezt.vec[2];
+          point.radius = bezt.radius;
+          point.tilt = bezt.tilt;
+          point.handle_type_a = handle_type_from_dna_bezt((eBezTriple_Handle)bezt.h1);
+          point.handle_type_b = handle_type_from_dna_bezt((eBezTriple_Handle)bezt.h2);
+          spline->control_points.append(std::move(point));
+        }
+
+        curve->splines.append(spline);
+        break;
+      }
+      case CU_NURBS: {
+        break;
+      }
+      case CU_POLY: {
+        break;
+      }
+      default: {
+        BLI_assert_unreachable();
+        break;
       }
-
-      curve->splines.append(spline);
-    }
-    else if (nurb->type == CU_NURBS) {
-    }
-    else if (nurb->type == CU_POLY) {
     }
   }
 
+  /* TODO: Decide whether to store this in the spline or the curve. */
   const Spline::NormalCalculationMode normal_mode = normal_mode_from_dna_curve(
       dna_curve.twist_mode);
   for (Spline *spline : curve->splines) {
@@ -117,6 +127,13 @@ DCurve *dcurve_from_dna_curve(const Curve &dna_curve)
 /** \name Spline
  * \{ */
 
+int Spline::evaluated_edges_size() const
+{
+  const int points_len = this->evaluated_points_size();
+
+  return this->is_cyclic ? points_len : points_len - 1;
+}
+
 Span<float3> Spline::evaluated_positions() const
 {
   this->ensure_base_cache();
@@ -129,16 +146,25 @@ Span<PointMapping> Spline::evaluated_mappings() const
   return evaluated_mapping_cache_;
 }
 
-static void accumulate_lengths(Span<float3> positions, MutableSpan<float> r_lengths)
+static void accumulate_lengths(Span<float3> positions,
+                               const bool is_cyclic,
+                               MutableSpan<float> 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]);
+  for (const int i : IndexRange(positions.size() - 1)) {
+    length += float3::distance(positions[i], positions[i + 1]);
+    lengths[i] = length;
+  }
+  if (is_cyclic) {
+    lengths.last() = length + float3::distance(positions.last(), positions.first());
   }
 }
 
+/**
+ * Return non-owning access to the cache of accumulated lengths along the curve. Each item is the
+ * length of the subsequent segment, i.e. the first value is the length of the first segment rather
+ * than 0. This calculation only depends on the spline's evaluated positions.
+ */
 Span<float> Spline::evaluated_lengths() const
 {
   if (!this->length_cache_dirty_) {
@@ -150,11 +176,11 @@ Span<float> Spline::evaluated_lengths() const
     return evaluated_lengths_cache_;
   }
 
-  const int total = this->evaluated_points_size();
+  const int total = this->evaluated_edges_size();
   this->evaluated_lengths_cache_.resize(total);
 
   Span<float3> positions = this->evaluated_positions();
-  accumulate_lengths(positions, this->evaluated_lengths_cache_);
+  accumulate_lengths(positions, this->is_cyclic, this->evaluated_lengths_cache_);
 
   this->length_cache_dirty_ = false;
   return evaluated_lengths_cache_;
@@ -195,6 +221,9 @@ static void calculate_tangents(Span<float3> positions,
   }
 }
 
+/**
+ * Return non-owning access to the direction of the curve at each evaluated point.
+ */
 Span<float3> Spline::evaluated_tangents() const
 {
   if (!this->tangent_cache_dirty_) {
@@ -374,6 +403,10 @@ static void calculate_normals_z_up(Span<float3> tangents, MutableSpan<float3> no
   }
 }
 
+/**
+ * Return non-owning access to the direction vectors perpendicular to the tangents at every
+ * evaluated point. The method used to generate the normal vectors depends on Spline.normal_mode.
+ */
 Span<float3> Spline::evaluated_normals() const
 {
   if (!this->normal_cache_dirty_) {
@@ -405,6 +438,10 @@ Span<float3> Spline::evaluated_normals() const
   return evaluated_normals_cache_;
 }
 
+/**
+ * Mark all caches for recomputation. This must be called after any operation that would
+ * change the generated positions, tangents, normals, mapping, etc. of the evaluated points.
+ */
 void Spline::mark_cache_invalid()
 {
   base_cache_dirty_ = true;
@@ -429,6 +466,25 @@ float Spline::get_evaluated_point_radius(const int evaluated_index) const
   return interpf(next_radius, radius, factor);
 }
 
+void Spline::trim_lengths(const float start_length, const float end_length)
+{
+  Span<float> lengths = this->evaluated_lengths();
+
+  const float *lower = std::lower_bound(lengths.begin(), lengths.end(), start_length);
+  const float *upper = std::lower_bound(lengths.begin(), lengths.end(), end_length);
+
+  const int i_lower = lower - lengths.begin();
+  const int i_upper = upper - lengths.begin();
+
+  Span<PointMapping> mappings = this->evaluated_mappings();
+
+  const int i_control_lower = mappings[i_lower].control_point_index;
+  const int i_control_upper = mappings[i_upper].control_point_index;
+
+  // this->drop_front_control_points(i_control_upper);
+  // this->drop_back_control_points(this->size() - i_control_upper);
+}
+
 /** \} */
 
 /* -------------------------------------------------------------------- */
@@ -503,12 +559,14 @@ int BezierSpline::evaluated_points_size() const
   return total_len;
 }
 
+/**
+ * If the spline is not cyclic, the direction for the first and last points is just the
+ * direction formed by the corresponding handl

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list