[Bf-blender-cvs] [51f6fa351d4] temp-geometry-nodes-curve-sample: Working sampling, only sampling builtin curve attributes doesn't work

Hans Goudey noreply at git.blender.org
Mon Jul 19 03:54:28 CEST 2021


Commit: 51f6fa351d417aff102b6f819e1998a09b00b338
Author: Hans Goudey
Date:   Sun Jul 18 21:54:20 2021 -0400
Branches: temp-geometry-nodes-curve-sample
https://developer.blender.org/rB51f6fa351d417aff102b6f819e1998a09b00b338

Working sampling, only sampling builtin curve attributes doesn't work

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

M	source/blender/blenkernel/intern/spline_base.cc
M	source/blender/makesdna/DNA_node_types.h
M	source/blender/makesrna/intern/rna_nodetree.c
M	source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc

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

diff --git a/source/blender/blenkernel/intern/spline_base.cc b/source/blender/blenkernel/intern/spline_base.cc
index 9652622d4a1..d07e0dfdf4a 100644
--- a/source/blender/blenkernel/intern/spline_base.cc
+++ b/source/blender/blenkernel/intern/spline_base.cc
@@ -463,17 +463,6 @@ 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
@@ -486,15 +475,22 @@ static void assert_sorted_array_in_range(Span<float> data, const float min, cons
  * 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.
+ *
+ * \todo Investigate running the single threaded loop over evaluated points in chunks.
  */
 Array<float> Spline::sample_lengths_to_index_factors(const Span<float> parameters) const
 {
+  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];
+  });
+
   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
@@ -502,7 +498,7 @@ Array<float> Spline::sample_lengths_to_index_factors(const Span<float> parameter
   float prev_length = 0.0f;
   int i_evaluated = 0;
   for (const int i_sample : parameters.index_range()) {
-    const float sample_length = parameters[i_sample];
+    const float sample_length = std::clamp(parameters[i_sample], 0.0f, total_length);
 
     /* Skip over every evaluated point that fits before this sample. */
     while (lengths[i_evaluated] < sample_length) {
@@ -511,7 +507,7 @@ Array<float> Spline::sample_lengths_to_index_factors(const Span<float> parameter
     }
 
     const float factor = (sample_length - prev_length) / (lengths[i_evaluated] - prev_length);
-    index_factors[i_sample] = i_evaluated + factor;
+    index_factors[original_indices[i_sample]] = i_evaluated + factor;
   }
 
   return index_factors;
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index e325a22a74d..17efc5fc965 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -1381,7 +1381,7 @@ typedef struct NodeGeometryCurveResample {
 } NodeGeometryCurveResample;
 
 typedef struct NodeGeometryCurveSample {
-  /* GeometryNodeCurveSampleMode. */
+  /* GeometryNodeCurveInterpolateMode. */
   uint8_t mode;
 } NodeGeometryCurveSample;
 
@@ -1954,11 +1954,6 @@ typedef enum GeometryNodeCurveResampleMode {
   GEO_NODE_CURVE_RESAMPLE_EVALUATED = 2,
 } GeometryNodeCurveResampleMode;
 
-typedef enum GeometryNodeCurveSampleMode {
-  GEO_NODE_CURVE_SAMPLE_FACTOR = 0,
-  GEO_NODE_CURVE_SAMPLE_LENGTH = 1,
-} GeometryNodeCurveSampleMode;
-
 typedef enum GeometryNodeCurveInterpolateMode {
   GEO_NODE_CURVE_INTERPOLATE_FACTOR = 0,
   GEO_NODE_CURVE_INTERPOLATE_LENGTH = 1,
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index ce2c777b782..8f6318c9d46 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -10000,16 +10000,16 @@ static void def_geo_curve_sample(StructRNA *srna)
   PropertyRNA *prop;
 
   static EnumPropertyItem mode_items[] = {
-      {GEO_NODE_CURVE_SAMPLE_FACTOR,
-       "COUNT",
+      {GEO_NODE_CURVE_INTERPOLATE_FACTOR,
+       "FACTOR",
        0,
-       "Count",
+       "Factor",
        "Choose sample points on the curve based on the portion of the total length"},
-      {GEO_NODE_CURVE_SAMPLE_LENGTH,
+      {GEO_NODE_CURVE_INTERPOLATE_LENGTH,
        "LENGTH",
        0,
        "Length",
-       "Choose sample points on the curve based on the assumulated length at that point"},
+       "Choose sample points on the curve based on the accumulated length at that point"},
       {0, NULL, 0, NULL, NULL},
   };
 
@@ -10017,7 +10017,7 @@ static void def_geo_curve_sample(StructRNA *srna)
 
   prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
   RNA_def_property_enum_items(prop, mode_items);
-  RNA_def_property_ui_text(prop, "Mode", "How to specify the amount of samples");
+  RNA_def_property_ui_text(prop, "Mode", "How to specify the sample positions on the curve");
   RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
 }
 
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 734d17ac459..9ab89c4f428 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc
@@ -57,22 +57,23 @@ static void geo_node_curve_sample_init(bNodeTree *UNUSED(tree), bNode *node)
   NodeGeometryCurveSample *data = (NodeGeometryCurveSample *)MEM_callocN(
       sizeof(NodeGeometryCurveSample), __func__);
 
-  data->mode = GEO_NODE_CURVE_SAMPLE_FACTOR;
+  data->mode = GEO_NODE_CURVE_INTERPOLATE_FACTOR;
   node->storage = data;
 }
 
 static void geo_node_curve_sample_update(bNodeTree *UNUSED(ntree), bNode *node)
 {
   const NodeGeometryCurveSample &node_storage = *(NodeGeometryCurveSample *)node->storage;
-  const GeometryNodeCurveSampleMode mode = (GeometryNodeCurveSampleMode)node_storage.mode;
+  const GeometryNodeCurveInterpolateMode mode = (GeometryNodeCurveInterpolateMode)
+                                                    node_storage.mode;
 
   bNodeSocket *parameter_socket = ((bNodeSocket *)node->inputs.first)->next;
 
-  if (mode == GEO_NODE_CURVE_SAMPLE_FACTOR) {
+  if (mode == GEO_NODE_CURVE_INTERPOLATE_FACTOR) {
     node_sock_label(parameter_socket, "Factor");
   }
   else {
-    BLI_assert(mode == GEO_NODE_CURVE_SAMPLE_LENGTH);
+    BLI_assert(mode == GEO_NODE_CURVE_INTERPOLATE_LENGTH);
     node_sock_label(parameter_socket, "Length");
   }
 }
@@ -103,39 +104,31 @@ static CustomDataType get_result_type(const CurveComponent &curve_component,
   return curve_meta_data->data_type;
 }
 
-using SamplePair = std::pair<GSpan, GMutableSpan>;
+struct SamplePair {
+  GSpan src;
+  GMutableSpan dst;
+};
 
-/** TODO: Investigate chunkifying the first part,
- * since #sample_lengths_to_index_factors is single threaded. */
-static void spline_sample_attributes(const Spline &spline,
-                                     Span<float> lengths,
-                                     Span<SamplePair> samples_extrapolated,
-                                     Span<SamplePair> samples)
+static void sample_with_lookups(const SamplePair &sample, Span<Spline::LookupResult> lookups)
 {
-  Array<int> original_indices(lengths.size());
-  for (const int i : original_indices.index_range()) {
-    original_indices[i] = i;
-  }
-
-  std::sort(original_indices.begin(), original_indices.end(), [lengths](int a, int b) {
-    return lengths[a] > lengths[b];
+  blender::attribute_math::convert_to_static_type(sample.src.type(), [&](auto dummy) {
+    using T = decltype(dummy);
+    Span<T> src = sample.src.typed<T>();
+    MutableSpan<T> dst = sample.dst.typed<T>();
+
+    threading::parallel_for(lookups.index_range(), 1024, [&](IndexRange range) {
+      for (const int i : range) {
+        dst[i] = attribute_math::mix2<T>(lookups[i].factor,
+                                         src[lookups[i].evaluated_index],
+                                         src[lookups[i].next_evaluated_index]);
+      }
+    });
   });
-
-  const Array<float> index_factors = spline.sample_lengths_to_index_factors(lengths);
-
-  for (const SamplePair &sample : samples_extrapolated) {
-    spline.sample_with_index_factors(sample.first, index_factors, sample.second);
-  }
-
-  /* TODO: Clamp index factors. */
-
-  for (const SamplePair &sample : samples) {
-    spline.sample_with_index_factors(sample.first, index_factors, sample.second);
-  }
 }
 
 static void execute_on_component(GeometryComponent &component,
                                  const CurveComponent &curve_component,
+                                 const GeometryNodeCurveInterpolateMode mode,
                                  const StringRef pararameter_name,
                                  const StringRef position_name,
                                  const StringRef tangent_name,
@@ -145,58 +138,73 @@ static void execute_on_component(GeometryComponent &component,
 {
   const CurveEval &curve = *curve_component.get_for_read();
   const Spline &spline = *curve.splines().first();
+  const float length = spline.length();
 
   const AttributeDomain domain = get_result_domain(component, pararameter_name, result_name);
 
   GVArray_Typed<float> parameters = component.attribute_get_for_read<float>(
       pararameter_name, domain, 0.0f);
-  VArray_Span<float> parameters_span{parameters};
-  /* TODO: Multiply by length if in factor mode. */
 
-  Vector<OutputAttribute> output_attributes;
-  Vector<GVArrayPtr> owned_curve_attributes;
-  Vector<SamplePair> sample_data;
-  Vector<SamplePair> sample_data_extrapolated;
+  Array<Spline::LookupResult> lookups(parameters.size());
+  if (mode == GEO_NODE_CURVE_INTERPOLATE_LENGTH) {
+    threading::parallel_for(lookups.index_range(), 1024, [&](IndexRange range) {
+      for (const int i : range) {
+        lookups[i] = spline.lookup_evaluated_length(std::clamp(parameters[i], 0.0f, length));
+      }
+    });
+  }
+  else {
+    threading::parallel_for(lookups.index_range(), 1024, [&](Index

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list