[Bf-blender-cvs] [a101f6d974e] temp-geometry-nodes-curve-sample: Some progress
Hans Goudey
noreply at git.blender.org
Tue Jul 13 01:43:14 CEST 2021
Commit: a101f6d974efc33ea97352b394e6aeb2cd7a86df
Author: Hans Goudey
Date: Sun Jul 4 21:08:16 2021 -0500
Branches: temp-geometry-nodes-curve-sample
https://developer.blender.org/rBa101f6d974efc33ea97352b394e6aeb2cd7a86df
Some progress
===================================================================
M source/blender/blenkernel/BKE_spline.hh
M source/blender/blenkernel/intern/spline_base.cc
M source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc
===================================================================
diff --git a/source/blender/blenkernel/BKE_spline.hh b/source/blender/blenkernel/BKE_spline.hh
index cd752bcb798..d7b2dd181b4 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_length_parameters_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,6 +172,8 @@ class Spline {
LookupResult lookup_evaluated_length(const float length) const;
blender::Array<float> sample_uniform_index_factors(const int samples_size) const;
+ void sample_length_parameters_to_index_factors(blender::MutableSpan<float> parameters) const;
+
LookupResult lookup_data_from_index_factor(const float index_factor) const;
void sample_with_index_factors(const blender::fn::GVArray &src,
diff --git a/source/blender/blenkernel/intern/spline_base.cc b/source/blender/blenkernel/intern/spline_base.cc
index aa0d95d4d61..0926e3befcd 100644
--- a/source/blender/blenkernel/intern/spline_base.cc
+++ b/source/blender/blenkernel/intern/spline_base.cc
@@ -463,6 +463,53 @@ 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.
+ */
+void Spline::sample_length_parameters_to_index_factors(MutableSpan<float> parameters) const
+{
+ const Span<float> lengths = this->evaluated_lengths();
+#ifdef DEBUG
+ assert_sorted_array_in_range(parameters, 0.0f, this->length());
+#endif
+
+ /* 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);
+ parameters[i_sample] = i_evaluated + factor;
+ }
+}
+
Spline::LookupResult Spline::lookup_data_from_index_factor(const float index_factor) const
{
const int eval_size = this->evaluated_points_size();
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc
index cf43e4b1c4e..89c46b58405 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc
@@ -76,16 +76,70 @@ static void geo_node_curve_resample_update(bNodeTree *UNUSED(ntree), bNode *node
namespace blender::nodes {
+static AttributeDomain get_result_domain(const GeometryComponent &component,
+ const StringRef parameter_name,
+ const StringRef result_name)
+{
+ std::optional<AttributeMetaData> result_info = component.attribute_get_meta_data(result_name);
+ if (result_info) {
+ return result_info->domain;
+ }
+ std::optional<AttributeMetaData> parameter_info = component.attribute_get_meta_data(
+ parameter_name);
+ if (parameter_info) {
+ return parameter_info->domain;
+ }
+ return ATTR_DOMAIN_POINT;
+}
+
+/**
+ * 1. Sort input parameters
+ * 2. For each spline in the curve, sample the values on it.
+ */
+static void curve_sample_attributes(const CurveEval &curve,
+ const StringRef name,
+ const Span<float> parameters,
+ GMutableSpan result)
+{
+ Array<int> original_indices(parameters.size());
+ for (const int i : original_indices.index_range()) {
+ original_indices[i] = i;
+ }
+
+ std::sort(original_indices.begin(), original_indices.end(), [parameters](int a, int b) {
+ return parameters[a] > parameters[b];
+ });
+
+ for (const int i : range) {
+ }
+}
+
static void execute_on_component(GeometryComponent &component,
const CurveComponent &curve_component,
const StringRef pararameter_name,
const StringRef attribute_name,
const StringRef result_name)
{
+ const AttributeDomain domain = get_result_domain(component, pararameter_name, result_name);
+
GVArray_Typed<float> parameters = component.attribute_get_for_read<float>(pararameter_name,
0.0f);
- ReadAttributeLookup attribute = curve_component.attribute_try_get_for_read(attribute_name,
- ATTR_DOMAIN_POINT);
+ VArray_Span<float> parameters_span{parameters};
+ std::optional<AttributeMetaData> curve_meta_data = curve_component.attribute_get_meta_data(
+ attribute_name);
+
+ OutputAttribute result = component.attribute_try_get_for_output_only(
+ result_name, domain, curve_meta_data->data_type);
+ GMutableSpan result_span = result.as_span();
+
+ const CurveEval &curve = *curve_component.get_for_read();
+
+ threading::parallel_for(IndexRange(result_span.size()), 1024, [&](IndexRange range) {
+ curve_sample_attributes(curve,
+ attribute_name,
+ parameters_span.slice(range.start(), range.size()),
+ result_span.slice(range.start(), range.size()));
+ });
}
static void geo_node_resample_exec(GeoNodeExecParams params)
More information about the Bf-blender-cvs
mailing list