[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