[Bf-blender-cvs] [11f6c65e61a] blender-v3.4-release: Geometry Nodes: Trim curve node selection input and corrections

Mattias Fredriksson noreply at git.blender.org
Wed Nov 9 17:54:48 CET 2022


Commit: 11f6c65e61a22ea9423962d6165f54ec29e221a8
Author: Mattias Fredriksson
Date:   Wed Nov 9 10:50:51 2022 -0600
Branches: blender-v3.4-release
https://developer.blender.org/rB11f6c65e61a22ea9423962d6165f54ec29e221a8

Geometry Nodes: Trim curve node selection input and corrections

Correct trim for cyclical curves mentioned in T101379, splitting the
curves if the start/endpoint is at the 'loop point'.

Correct implementation based on comments in D14481, request was made to
use 'foreach_curve_by_type' to computing the point lookups.

Included corrections from D16066 as it may not be a adopted solution.

Exposed selection input by adding it as input to the node.
Note: This is disabled for 3.4 to avoid making UI changes in Bcon3.

Differential Revision: https://developer.blender.org/D16161

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

M	source/blender/blenkernel/BKE_curves_utils.hh
M	source/blender/blenkernel/intern/curves_utils.cc
M	source/blender/geometry/GEO_trim_curves.hh
M	source/blender/geometry/intern/trim_curves.cc
M	source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc

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

diff --git a/source/blender/blenkernel/BKE_curves_utils.hh b/source/blender/blenkernel/BKE_curves_utils.hh
index f9155023db7..670b25bf80f 100644
--- a/source/blender/blenkernel/BKE_curves_utils.hh
+++ b/source/blender/blenkernel/BKE_curves_utils.hh
@@ -67,86 +67,228 @@ struct CurvePoint : public CurveSegment {
 };
 
 /**
- * Cyclical index range. Iterates the interval [start, end).
+ * Cyclical index range. Allows iteration over a plain 'IndexRange' interval on form [start, end)
+ * while also supporting treating the underlying array as a cyclic array where the last index is
+ * followed by the first nidex in the 'cyclical' range. The cyclical index range can then be
+ * considered a combination of the intervals separated by the last index of the underlying array,
+ * namely [start, range_size) and [0, end) where start/end is the indices iterated between and
+ * range_size is the size of the underlying array. To cycle the underlying array the interval
+ * [0, range_size) can be iterated over an arbitrary amount of times inbetween.
  */
 class IndexRangeCyclic {
   /* Index to the start and end of the iterated range.
    */
-  int64_t start_ = 0;
-  int64_t end_ = 0;
-  /* Index for the start and end of the entire iterable range which contains the iterated range
-   * (e.g. the point range for an individual spline/curve within the entire Curves point domain).
+  int start_ = 0;
+  int end_ = 0;
+  /* Size of the underlying iterable range.
    */
-  int64_t range_start_ = 0;
-  int64_t range_end_ = 0;
+  int range_size_ = 0;
   /* Number of times the range end is passed when the range is iterated.
    */
-  int64_t cycles_ = 0;
-
-  constexpr IndexRangeCyclic(int64_t begin,
-                             int64_t end,
-                             int64_t iterable_range_start,
-                             int64_t iterable_range_end,
-                             int64_t cycles)
-      : start_(begin),
-        end_(end),
-        range_start_(iterable_range_start),
-        range_end_(iterable_range_end),
-        cycles_(cycles)
-  {
-  }
+  int cycles_ = 0;
 
  public:
   constexpr IndexRangeCyclic() = default;
   ~IndexRangeCyclic() = default;
 
-  constexpr IndexRangeCyclic(int64_t start, int64_t end, IndexRange iterable_range, int64_t cycles)
-      : start_(start),
-        end_(end),
-        range_start_(iterable_range.first()),
-        range_end_(iterable_range.one_after_last()),
-        cycles_(cycles)
+  constexpr IndexRangeCyclic(const int start,
+                             const int end,
+                             const int iterable_range_size,
+                             const int cycles)
+      : start_(start), end_(end), range_size_(iterable_range_size), cycles_(cycles)
   {
   }
 
   /**
    * Create an iterator over the cyclical interval [start_index, end_index).
    */
-  constexpr IndexRangeCyclic(int64_t start, int64_t end, IndexRange iterable_range)
+  constexpr IndexRangeCyclic(const int start, const int end, const int iterable_range_size)
       : start_(start),
-        end_(end == iterable_range.one_after_last() ? iterable_range.first() : end),
-        range_start_(iterable_range.first()),
-        range_end_(iterable_range.one_after_last()),
+        end_(end == iterable_range_size ? 0 : end),
+        range_size_(iterable_range_size),
         cycles_(end < start)
   {
   }
 
   /**
-   * Increment the range by adding the given number of indices to the beginning of the range.
+   * Create a cyclical iterator of the specified size.
+   *
+   * \param start_point: Point on the curve that define the starting point of the interval.
+   * \param iterator_size: Number of elements to iterate (size of the iterated cyclical range).
+   * \param iterable_range_size: Size of the underlying range (superset to the cyclical range).
+   */
+  static IndexRangeCyclic get_range_from_size(const int start_index,
+                                              const int iterator_size,
+                                              const int iterable_range_size)
+  {
+    BLI_assert(start_index >= 0);
+    BLI_assert(iterator_size >= 0);
+    BLI_assert(iterable_range_size > 0);
+    const int num_until_loop = iterable_range_size - start_index;
+    if (iterator_size < num_until_loop) {
+      return IndexRangeCyclic(start_index, start_index + iterator_size, iterable_range_size, 0);
+    }
+
+    const int num_remaining = iterator_size - num_until_loop;
+    const int num_full_cycles = num_remaining /
+                                iterable_range_size; /* Integer division (rounded down). */
+    const int end_index = num_remaining - num_full_cycles * iterable_range_size;
+    return IndexRangeCyclic(start_index, end_index, iterable_range_size, num_full_cycles + 1);
+  }
+
+  /**
+   * Create a cyclical iterator for all control points within the interval [start_point, end_point]
+   * including any control point at the start or end point.
+   *
+   * \param start_point: Point on the curve that define the starting point of the interval.
+   * \param end_point: Point on the curve that define the end point of the interval (included).
+   * \param iterable_range_size: Size of the underlying range (superset to the cyclical range).
+   */
+  static IndexRangeCyclic get_range_between_endpoints(const CurvePoint start_point,
+                                                      const CurvePoint end_point,
+                                                      const int iterable_range_size)
+  {
+    BLI_assert(iterable_range_size > 0);
+    const int start_index = start_point.parameter == 0.0 ? start_point.index :
+                                                           start_point.next_index;
+    int end_index = end_point.parameter == 0.0 ? end_point.index : end_point.next_index;
+    int cycles;
+
+    if (end_point.is_controlpoint()) {
+      BLI_assert(end_index < iterable_range_size);
+      ++end_index;
+      if (end_index == iterable_range_size) {
+        end_index = 0;
+      }
+      /* end_point < start_point but parameter is irrelevant (end_point is controlpoint), and loop
+       * when equal due to increment. */
+      cycles = end_index <= start_index;
+    }
+    else {
+      cycles = end_point < start_point || end_index < start_index;
+    }
+    return IndexRangeCyclic(start_index, end_index, iterable_range_size, cycles);
+  }
+
+  /**
+   * Next index within the iterable range.
+   */
+  template<typename IndexT> constexpr IndexT next_index(const IndexT index, const bool cyclic)
+  {
+    static_assert((is_same_any_v<IndexT, int, int>), "Expected signed integer type.");
+    const IndexT next_index = index + 1;
+    if (next_index == this->size_range()) {
+      return cyclic ? 0 : index;
+    }
+    return next_index;
+  }
+
+  /**
+   * Previous index within the iterable range.
+   */
+  template<typename IndexT> constexpr IndexT previous_index(const IndexT index, const bool cyclic)
+  {
+    static_assert((is_same_any_v<IndexT, int, int64_t>), "Expected signed integer type.");
+    const IndexT prev_index = index - 1;
+    if (prev_index < 0) {
+      return cyclic ? this->size_range() - 1 : 0;
+    }
+    return prev_index;
+  }
+
+  /**
+   * Increment the range by adding `n` loops to the range. This invokes undefined behavior when n
+   * is negative.
    */
-  constexpr IndexRangeCyclic push_forward(int n)
+  constexpr IndexRangeCyclic push_loop(const int n = 1) const
+  {
+    return {this->start_, this->end_, this->range_size_, this->cycles_ + n};
+  }
+
+  /**
+   * Increment the range by adding the given number of indices to the beginning of the iterated
+   * range. This invokes undefined behavior when n is negative.
+   */
+  constexpr IndexRangeCyclic push_front(const int n = 1) const
   {
     BLI_assert(n >= 0);
-    int64_t nstart = start_ - n;
-    int64_t cycles = cycles_;
-    if (nstart < range_start_) {
+    int new_start = this->start_ - n;
+    int num_cycles = this->cycles_;
+    if (new_start < 0) {
+      const int new_cycles = n / this->size_range(); /* Integer division (floor) */
+      const int remainder = new_start + this->size_range() * new_cycles;
+      const bool underflow = remainder < 0;
+      new_start = remainder + (underflow ? this->size_range() : 0);
+      num_cycles += new_cycles + int(underflow);
+    }
+    BLI_assert(num_cycles >= 0);
+    BLI_assert(num_cycles > 0 ||
+               (new_start <= this->end_ || (this->end_ == 0 && new_start < this->size_range())));
+    return {new_start, this->end_, this->range_size_, num_cycles};
+  }
 
-      cycles += (int64_t)(n / (range_end_ - range_start_)) + (end_ < nstart) - (end_ < start_);
+  /**
+   * Increment the range by adding the given number of indices to the end of the iterated range.
+   * This invokes undefined behavior when n is negative.
+   */
+  constexpr IndexRangeCyclic push_back(const int n = 1) const
+  {
+    BLI_assert(n >= 0);
+    int new_end = this->end_ + n;
+    int num_cycles = this->cycles_;
+    if (this->size_range() <= new_end) {
+      const int new_cycles = n / this->size_range(); /* Integer division (floor) */
+      const int remainder = new_end - this->size_range() * new_cycles;
+      const bool overflow = remainder >= this->size_range();
+      new_end = remainder - (overflow ? this->size_range() : 0);
+      num_cycles += new_cycles + int(overflow);
     }
-    return {nstart, end_, range_start_, range_end_, cycles};
+    BLI_assert(num_cycles >= 0);
+    BLI_assert(num_cycles > 0 || (this->start_ <= new_end || new_end == 0));
+    return {this->start_, new_end, this->range_size_, num_cycles};
   }
+
   /**
-   * Increment the range by adding the given number of indices to the end of the range.
+   * Returns a new range with n indices removed from the beginning of the range.
+   * This invokes undefined behavior.
    */
-  constexpr IndexRangeCyclic push_backward(int n)
+  constexpr IndexRangeCyclic drop_front(const int n = 1) const
   {
     BLI_assert(n >= 0);
-    int64_t new_end = end_ + n;
-    int64_t cycles = cycles_;
-    if (range_end_ <= new_end) {
-      cycles += (int64_t)(n / (range_end_ - range_start_)) + (new_end < start_) - (end_ < start_);
+    int new_start = this->st

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list