[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