Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_node.h1
-rw-r--r--source/blender/blenkernel/BKE_spline.hh7
-rw-r--r--source/blender/blenkernel/intern/node.cc1
-rw-r--r--source/blender/blenkernel/intern/spline_base.cc61
4 files changed, 70 insertions, 0 deletions
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 9b8eca77e6b..39024445808 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -1465,6 +1465,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
#define GEO_NODE_CURVE_ENDPOINTS 1069
#define GEO_NODE_CURVE_PRIMITIVE_QUADRILATERAL 1070
#define GEO_NODE_CURVE_TRIM 1071
+#define GEO_NODE_CURVE_SAMPLE 1072
/** \} */
diff --git a/source/blender/blenkernel/BKE_spline.hh b/source/blender/blenkernel/BKE_spline.hh
index f85e62768f7..176e44b3245 100644
--- a/source/blender/blenkernel/BKE_spline.hh
+++ b/source/blender/blenkernel/BKE_spline.hh
@@ -56,6 +56,8 @@ using SplinePtr = std::unique_ptr<Spline>;
* along the length of a curve.
* 3. #sample_uniform_index_factors returns an array that stores uniform-length samples
* along the spline which can be used to interpolate data from method 1.
+ * 4. #sample_lengths_to_index_factors does the same, but uses arbitrary parameter
+ * inputs, instead of sampling uniformly.
*
* Commonly used evaluated data is stored in caches on the spline itself so that operations on
* splines don't need to worry about taking ownership of evaluated data when they don't need to.
@@ -170,11 +172,16 @@ class Spline {
LookupResult lookup_evaluated_length(const float length) const;
blender::Array<float> sample_uniform_index_factors(const int samples_size) const;
+ blender::Array<float> sample_lengths_to_index_factors(blender::Span<float> parameters) const;
+
LookupResult lookup_data_from_index_factor(const float index_factor) const;
void sample_with_index_factors(const blender::fn::GVArray &src,
blender::Span<float> index_factors,
blender::fn::GMutableSpan dst) const;
+ void sample_with_index_factors(blender::fn::GSpan src,
+ blender::Span<float> index_factors,
+ blender::fn::GMutableSpan dst) const;
template<typename T>
void sample_with_index_factors(const blender::VArray<T> &src,
blender::Span<float> index_factors,
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index 3d5973b1d5e..dbea83ae0ca 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -5115,6 +5115,7 @@ static void registerGeometryNodes()
register_node_type_geo_curve_primitive_quadrilateral();
register_node_type_geo_curve_primitive_spiral();
register_node_type_geo_curve_primitive_star();
+ register_node_type_geo_curve_sample();
register_node_type_geo_curve_resample();
register_node_type_geo_curve_reverse();
register_node_type_geo_curve_subdivide();
diff --git a/source/blender/blenkernel/intern/spline_base.cc b/source/blender/blenkernel/intern/spline_base.cc
index a7caae967f6..9652622d4a1 100644
--- a/source/blender/blenkernel/intern/spline_base.cc
+++ b/source/blender/blenkernel/intern/spline_base.cc
@@ -463,6 +463,60 @@ Array<float> Spline::sample_uniform_index_factors(const int samples_size) const
return samples;
}
+#ifdef DEBUG
+static void assert_sorted_array_in_range(Span<float> data, const float min, const float max)
+{
+ BLI_assert(data.first() >= min);
+ for (const int i : IndexRange(1, data.size() - 1)) {
+ BLI_assert(data[i] >= data[i - 1]);
+ }
+ BLI_assert(data.last() <= max);
+}
+#endif
+
+/**
+ * Transform an array of sorted length parameters into index factors. The result is indices
+ * and factors to the next index, encoded in floats. The logic for converting from the float
+ * values to interpolation data is in #lookup_data_from_index_factor.
+ *
+ * \param parameters: Lengths along the spline to be transformed into index factors
+ * (to save another allocation). Must be between zero and the total length of the spline.
+ *
+ * \note The implementation is similar to #sample_uniform_index_factors(), though
+ * the two loops are inverted, and obviously custom parameters are provided.
+ *
+ * \note This could have a result data argument instead of returning a span in the future.
+ */
+Array<float> Spline::sample_lengths_to_index_factors(const Span<float> parameters) const
+{
+ const Span<float> lengths = this->evaluated_lengths();
+ const float total_length = this->length();
+#ifdef DEBUG
+ // assert_sorted_array_in_range(parameters, 0.0f, this->length());
+#endif
+
+ Array<float> index_factors(parameters.size());
+
+ /* Store the length at the previous evaluated point in a variable so it can
+ * start out at zero (the lengths array doesn't contain 0 for the first point). */
+ float prev_length = 0.0f;
+ int i_evaluated = 0;
+ for (const int i_sample : parameters.index_range()) {
+ const float sample_length = parameters[i_sample];
+
+ /* Skip over every evaluated point that fits before this sample. */
+ while (lengths[i_evaluated] < sample_length) {
+ prev_length = lengths[i_evaluated];
+ i_evaluated++;
+ }
+
+ const float factor = (sample_length - prev_length) / (lengths[i_evaluated] - prev_length);
+ index_factors[i_sample] = i_evaluated + factor;
+ }
+
+ return index_factors;
+}
+
Spline::LookupResult Spline::lookup_data_from_index_factor(const float index_factor) const
{
const int eval_size = this->evaluated_points_size();
@@ -497,6 +551,13 @@ GVArrayPtr Spline::interpolate_to_evaluated(GSpan data) const
return this->interpolate_to_evaluated(GVArray_For_GSpan(data));
}
+void Spline::sample_with_index_factors(GSpan src,
+ Span<float> index_factors,
+ GMutableSpan dst) const
+{
+ return this->sample_with_index_factors(GVArray_For_GSpan(src), index_factors, dst);
+}
+
/**
* Sample any input data with a value for each evaluated point (already interpolated to evaluated
* points) to arbitrary parameters in between the evaluated points. The interpolation is quite