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:
-rw-r--r--source/blender/blenkernel/BKE_spline.hh26
-rw-r--r--source/blender/blenkernel/intern/spline_base.cc41
-rw-r--r--source/blender/blenkernel/intern/spline_nurbs.cc8
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc77
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc3
5 files changed, 94 insertions, 61 deletions
diff --git a/source/blender/blenkernel/BKE_spline.hh b/source/blender/blenkernel/BKE_spline.hh
index fc1292e3620..dfbe82f31fd 100644
--- a/source/blender/blenkernel/BKE_spline.hh
+++ b/source/blender/blenkernel/BKE_spline.hh
@@ -172,6 +172,25 @@ class Spline {
blender::Array<float> sample_uniform_index_factors(const int samples_size) const;
LookupResult lookup_data_from_index_factor(const float index_factor) const;
+ void sample_based_on_index_factors(const blender::fn::GVArray &src,
+ blender::Span<float> index_factors,
+ blender::fn::GMutableSpan dst) const;
+ template<typename T>
+ void sample_based_on_index_factors(const blender::VArray<T> &src,
+ blender::Span<float> index_factors,
+ blender::MutableSpan<T> dst) const
+ {
+ this->sample_based_on_index_factors(
+ blender::fn::GVArray_For_VArray(src), index_factors, blender::fn::GMutableSpan(dst));
+ }
+ template<typename T>
+ void sample_based_on_index_factors(blender::Span<T> src,
+ blender::Span<float> index_factors,
+ blender::MutableSpan<T> dst) const
+ {
+ this->sample_based_on_index_factors(blender::VArray_For_Span(src), index_factors, dst);
+ }
+
/**
* Interpolate a virtual array of data with the size of the number of control points to the
* evaluated points. For poly splines, the lifetime of the returned virtual array must not
@@ -179,6 +198,13 @@ class Spline {
*/
virtual blender::fn::GVArrayPtr interpolate_to_evaluated_points(
const blender::fn::GVArray &source_data) const = 0;
+ blender::fn::GVArrayPtr interpolate_to_evaluated_points(blender::fn::GSpan data) const;
+ template<typename T>
+ blender::fn::GVArray_Typed<T> interpolate_to_evaluated_points(blender::Span<T> data) const
+ {
+ return blender::fn::GVArray_Typed<T>(
+ this->interpolate_to_evaluated_points(blender::fn::GSpan(data)));
+ }
protected:
virtual void correct_end_tangents() const = 0;
diff --git a/source/blender/blenkernel/intern/spline_base.cc b/source/blender/blenkernel/intern/spline_base.cc
index 11620a30948..9f8c215b31f 100644
--- a/source/blender/blenkernel/intern/spline_base.cc
+++ b/source/blender/blenkernel/intern/spline_base.cc
@@ -16,6 +16,7 @@
#include "BLI_array.hh"
#include "BLI_span.hh"
+#include "BLI_task.hh"
#include "BLI_timeit.hh"
#include "BKE_spline.hh"
@@ -27,6 +28,12 @@ using blender::float3;
using blender::IndexRange;
using blender::MutableSpan;
using blender::Span;
+using blender::fn::GMutableSpan;
+using blender::fn::GSpan;
+using blender::fn::GVArray;
+using blender::fn::GVArray_For_GSpan;
+using blender::fn::GVArray_Typed;
+using blender::fn::GVArrayPtr;
Spline::Type Spline::type() const
{
@@ -234,8 +241,7 @@ Span<float3> Spline::evaluated_normals() const
calculate_normals_z_up(tangents, normals);
/* Rotate the generated normals with the interpolated tilt data. */
- blender::fn::GVArray_Typed<float> tilts{
- this->interpolate_to_evaluated_points(blender::fn::GVArray_For_Span(this->tilts()))};
+ GVArray_Typed<float> tilts = this->interpolate_to_evaluated_points(this->tilts());
for (const int i : normals.index_range()) {
normals[i] = rotate_direction_around_axis(normals[i], tangents[i], tilts[i]);
}
@@ -341,3 +347,34 @@ void Spline::bounds_min_max(float3 &min, float3 &max, const bool use_evaluated)
minmax_v3v3_v3(min, max, position);
}
}
+
+GVArrayPtr Spline::interpolate_to_evaluated_points(GSpan data) const
+{
+ return this->interpolate_to_evaluated_points(GVArray_For_GSpan(data));
+}
+
+/**
+ * Sample any input data with a value for each evaluated point (already interpolated to evaluated
+ * points) to arbitrary parameters in betwen the evaluated points. The interpolation is quite
+ * simple, but this handles the cyclic and end point special cases.
+ */
+void Spline::sample_based_on_index_factors(const GVArray &src,
+ Span<float> index_factors,
+ GMutableSpan dst) const
+{
+ BLI_assert(src.size() == this->evaluated_points_size());
+
+ blender::attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
+ using T = decltype(dummy);
+ const GVArray_Typed<T> src_typed = src.typed<T>();
+ MutableSpan<T> dst_typed = dst.typed<T>();
+ blender::parallel_for(dst_typed.index_range(), 1024, [&](IndexRange range) {
+ for (const int i : range) {
+ const LookupResult interp = this->lookup_data_from_index_factor(index_factors[i]);
+ dst_typed[i] = blender::attribute_math::mix2(interp.factor,
+ src_typed[interp.evaluated_index],
+ src_typed[interp.next_evaluated_index]);
+ }
+ });
+ });
+}
diff --git a/source/blender/blenkernel/intern/spline_nurbs.cc b/source/blender/blenkernel/intern/spline_nurbs.cc
index cae206341a0..bfb0d652b1a 100644
--- a/source/blender/blenkernel/intern/spline_nurbs.cc
+++ b/source/blender/blenkernel/intern/spline_nurbs.cc
@@ -26,6 +26,7 @@ using blender::float3;
using blender::IndexRange;
using blender::MutableSpan;
using blender::Span;
+using blender::fn::GVArray_Typed;
SplinePtr NURBSpline::copy() const
{
@@ -434,10 +435,9 @@ Span<float3> NURBSpline::evaluated_positions() const
const int eval_size = this->evaluated_points_size();
evaluated_position_cache_.resize(eval_size);
- blender::fn::GVArray_Typed<float3> evaluated_positions{
- this->interpolate_to_evaluated_points(blender::fn::GVArray_For_Span<float3>(positions_))};
-
- evaluated_positions->materialize(evaluated_position_cache_);
+ /* TODO: Avoid copying the evaluated data from the temporary array. */
+ GVArray_Typed<float3> evaluated = Spline::interpolate_to_evaluated_points(positions_.as_span());
+ evaluated->materialize(evaluated_position_cache_);
position_cache_dirty_ = false;
return evaluated_position_cache_;
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc
index 684f7d6c702..9d0820eb0b0 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc
@@ -76,34 +76,17 @@ struct SampleModeParam {
std::optional<int> count;
};
-template<typename T>
-static void sample_span_to_output_spline(const Spline &input_spline,
- Span<float> index_factors,
- const VArray<T> &input_data,
- MutableSpan<T> output_data)
-{
- BLI_assert(input_data.size() == input_spline.evaluated_points_size());
-
- parallel_for(output_data.index_range(), 1024, [&](IndexRange range) {
- for (const int i : range) {
- const Spline::LookupResult interp = input_spline.lookup_data_from_index_factor(
- index_factors[i]);
- output_data[i] = blender::attribute_math::mix2(interp.factor,
- input_data[interp.evaluated_index],
- input_data[interp.next_evaluated_index]);
- }
- });
-}
-
static SplinePtr resample_spline(const Spline &input_spline, const int count)
{
std::unique_ptr<PolySpline> output_spline = std::make_unique<PolySpline>();
output_spline->set_cyclic(input_spline.is_cyclic());
output_spline->normal_mode = input_spline.normal_mode;
- if (input_spline.evaluated_edges_size() < 1) {
- output_spline->resize(1);
- output_spline->positions().first() = input_spline.positions().first();
+ if (input_spline.evaluated_edges_size() < 1 || count == 1) {
+ output_spline->add_point(input_spline.positions().first(),
+ input_spline.tilts().first(),
+ input_spline.radii().first());
+ output_spline->attributes.reallocate(1);
return output_spline;
}
@@ -111,26 +94,18 @@ static SplinePtr resample_spline(const Spline &input_spline, const int count)
Array<float> uniform_samples = input_spline.sample_uniform_index_factors(count);
- {
- GVArray_For_Span positions(input_spline.evaluated_positions());
- GVArray_Typed<float3> positions_typed(positions);
- sample_span_to_output_spline<float3>(
- input_spline, uniform_samples, positions_typed, output_spline->positions());
- }
- {
- GVArrayPtr interpolated_data = input_spline.interpolate_to_evaluated_points(
- GVArray_For_Span(input_spline.radii()));
- GVArray_Typed<float> interpolated_data_typed{*interpolated_data};
- sample_span_to_output_spline<float>(
- input_spline, uniform_samples, interpolated_data_typed, output_spline->radii());
- }
- {
- GVArrayPtr interpolated_data = input_spline.interpolate_to_evaluated_points(
- GVArray_For_Span(input_spline.tilts()));
- GVArray_Typed<float> interpolated_data_typed{*interpolated_data};
- sample_span_to_output_spline<float>(
- input_spline, uniform_samples, interpolated_data_typed, output_spline->tilts());
- }
+ input_spline.sample_based_on_index_factors<float3>(
+ input_spline.evaluated_positions(), uniform_samples, output_spline->positions());
+
+ input_spline.sample_based_on_index_factors<float>(
+ input_spline.interpolate_to_evaluated_points(input_spline.radii()),
+ uniform_samples,
+ output_spline->radii());
+
+ input_spline.sample_based_on_index_factors<float>(
+ input_spline.interpolate_to_evaluated_points(input_spline.tilts()),
+ uniform_samples,
+ output_spline->tilts());
output_spline->attributes.reallocate(count);
input_spline.attributes.foreach_attribute(
@@ -147,16 +122,12 @@ static SplinePtr resample_spline(const Spline &input_spline, const int count)
BLI_assert_unreachable();
return false;
}
- GVArrayPtr interpolated_attribute = input_spline.interpolate_to_evaluated_points(
- GVArray_For_GSpan(*input_attribute));
- attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) {
- using T = decltype(dummy);
- GVArray_Typed<T> interpolated_attribute_typed{*interpolated_attribute};
- sample_span_to_output_spline<T>(input_spline,
- uniform_samples,
- interpolated_attribute_typed,
- (*output_attribute).typed<T>());
- });
+
+ input_spline.sample_based_on_index_factors(
+ *input_spline.interpolate_to_evaluated_points(*input_attribute),
+ uniform_samples,
+ *output_attribute);
+
return true;
},
ATTR_DOMAIN_POINT);
@@ -177,7 +148,7 @@ static std::unique_ptr<CurveEval> resample_curve(const CurveEval &input_curve,
else if (mode_param.mode == GEO_NODE_CURVE_SAMPLE_LENGTH) {
BLI_assert(mode_param.length);
const float length = spline->length();
- const int count = length / *mode_param.length;
+ const int count = std::max(int(length / *mode_param.length), 1);
output_curve->add_spline(resample_spline(*spline, count));
}
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
index fe1b23bf6d7..b6f04352929 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
@@ -181,8 +181,7 @@ static void spline_extrude_to_mesh_data(const Spline &spline,
Span<float3> normals = spline.evaluated_normals();
Span<float3> profile_positions = profile_spline.evaluated_positions();
- GVArray_Typed<float> radii{
- spline.interpolate_to_evaluated_points(blender::fn::GVArray_For_Span(spline.radii()))};
+ GVArray_Typed<float> radii = spline.interpolate_to_evaluated_points(spline.radii());
for (const int i_ring : IndexRange(spline_vert_len)) {
float4x4 point_matrix = float4x4::from_normalized_axis_data(
positions[i_ring], normals[i_ring], tangents[i_ring]);