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:
authorHans Goudey <h.goudey@me.com>2021-04-23 00:14:23 +0300
committerHans Goudey <h.goudey@me.com>2021-04-23 00:14:23 +0300
commitf2948faf97ae965e24f30d1175530d82d62b3a06 (patch)
tree59e4aa211ba07713fbba73ea9b48fc99381450a8 /source/blender
parentd7aa48123174c08a07366cfb7f5e3544b5c2fbb0 (diff)
Splines: Reorganize class inheritence, evaluation
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_spline.hh161
-rw-r--r--source/blender/blenkernel/intern/derived_curve.cc3
-rw-r--r--source/blender/blenkernel/intern/spline_base.cc28
-rw-r--r--source/blender/blenkernel/intern/spline_bezier.cc92
-rw-r--r--source/blender/blenkernel/intern/spline_nurbs.cc43
-rw-r--r--source/blender/blenkernel/intern/spline_poly.cc45
-rw-r--r--source/blender/functions/FN_generic_virtual_array.hh8
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc8
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc99
9 files changed, 265 insertions, 222 deletions
diff --git a/source/blender/blenkernel/BKE_spline.hh b/source/blender/blenkernel/BKE_spline.hh
index 8a707bda92c..0d84a032af4 100644
--- a/source/blender/blenkernel/BKE_spline.hh
+++ b/source/blender/blenkernel/BKE_spline.hh
@@ -49,6 +49,9 @@ struct PointMapping {
float factor;
};
+class Spline;
+using SplinePtr = std::unique_ptr<Spline>;
+
/**
* A spline is an abstraction of a curve section, its evaluation methods, and data.
* The spline data itself is just control points and a set of attributes.
@@ -58,14 +61,16 @@ struct PointMapping {
*/
class Spline {
public:
- using SplinePtr = std::unique_ptr<Spline>;
-
enum Type {
Bezier,
NURBS,
Poly,
};
- Type type;
+
+ private:
+ Type type_;
+
+ public:
bool is_cyclic = false;
enum NormalCalculationMode {
@@ -76,11 +81,6 @@ class Spline {
NormalCalculationMode normal_mode;
protected:
- mutable bool base_cache_dirty_ = true;
- mutable std::mutex base_cache_mutex_;
- mutable blender::Vector<blender::float3> evaluated_positions_cache_;
- mutable blender::Vector<PointMapping> evaluated_mapping_cache_;
-
mutable bool tangent_cache_dirty_ = true;
mutable std::mutex tangent_cache_mutex_;
mutable blender::Vector<blender::float3> evaluated_tangents_cache_;
@@ -95,15 +95,10 @@ class Spline {
public:
virtual ~Spline() = default;
- Spline() = default;
+ Spline(const Type type) : type_(type){};
Spline(Spline &other)
- : type(other.type), is_cyclic(other.is_cyclic), normal_mode(other.normal_mode)
+ : type_(other.type_), is_cyclic(other.is_cyclic), normal_mode(other.normal_mode)
{
- if (!other.base_cache_dirty_) {
- evaluated_positions_cache_ = other.evaluated_positions_cache_;
- evaluated_mapping_cache_ = other.evaluated_mapping_cache_;
- base_cache_dirty_ = false;
- }
if (!other.tangent_cache_dirty_) {
evaluated_tangents_cache_ = other.evaluated_tangents_cache_;
tangent_cache_dirty_ = false;
@@ -120,6 +115,8 @@ class Spline {
virtual SplinePtr copy() const = 0;
+ Spline::Type type() const;
+
virtual int size() const = 0;
int segments_size() const;
virtual int resolution() const = 0;
@@ -141,8 +138,7 @@ class Spline {
float length() const;
- blender::Span<blender::float3> evaluated_positions() const;
- blender::Span<PointMapping> evaluated_mappings() const;
+ virtual blender::Span<blender::float3> evaluated_positions() const = 0;
blender::Span<float> evaluated_lengths() const;
blender::Span<blender::float3> evaluated_tangents() const;
blender::Span<blender::float3> evaluated_normals() const;
@@ -161,47 +157,13 @@ class Spline {
LookupResult lookup_evaluated_factor(const float factor) const;
LookupResult lookup_evaluated_length(const float length) const;
- /**
- * Interpolate data from the original control points to the corresponding ealuated points.
- * \param source_data: Should have the same size as the number of control points.
- * \param result_data: ...
- */
- template<typename T>
- void interpolate_data_to_evaluated_points(blender::Span<T> source_data,
- blender::MutableSpan<T> result_data,
- const int offset = 0) const
- {
- /* TODO: Onstead of "offset", it may be better to split a function that returns a single value.
- * TODO: Check for null default mixer, possibly using std::enable_if? */
- const int control_points_len = this->size();
- blender::Span<PointMapping> mappings = this->evaluated_mappings();
-
- blender::attribute_math::DefaultMixer<T> mixer(result_data);
-
- for (const int i : result_data.index_range()) {
- const int evaluated_point_index = offset + i;
- const PointMapping &mapping = mappings[evaluated_point_index];
- const int index = mapping.control_point_index;
- const int next_index = (index + 1) % control_points_len;
- const float factor = mapping.factor;
-
- const T &value = source_data[index];
- const T &next_value = source_data[next_index];
-
- mixer.mix_in(i, value, 1.0f - factor);
- mixer.mix_in(i, next_value, factor);
- }
-
- mixer.finalize();
- }
+ virtual blender::fn::GVArrayPtr interpolate_to_evaluated_points(
+ const blender::fn::GVArray &source_data) const = 0;
protected:
virtual void correct_end_tangents() const = 0;
- virtual void ensure_base_cache() const = 0;
};
-using SplinePtr = std::unique_ptr<Spline>;
-
class BezierSpline final : public Spline {
public:
enum HandleType {
@@ -221,9 +183,14 @@ class BezierSpline final : public Spline {
blender::Vector<float> tilts_;
int resolution_u_;
+ mutable bool base_cache_dirty_ = true;
+ mutable std::mutex base_cache_mutex_;
+ mutable blender::Vector<blender::float3> evaluated_positions_cache_;
+ mutable blender::Vector<PointMapping> evaluated_mappings_cache_;
+
public:
virtual SplinePtr copy() const final;
- BezierSpline() = default;
+ BezierSpline() : Spline(Type::Bezier){};
BezierSpline(const BezierSpline &other)
: Spline((Spline &)other),
handle_types_start_(other.handle_types_start_),
@@ -235,12 +202,28 @@ class BezierSpline final : public Spline {
tilts_(other.tilts_),
resolution_u_(other.resolution_u_)
{
+ if (!other.base_cache_dirty_) {
+ evaluated_positions_cache_ = other.evaluated_positions_cache_;
+ evaluated_mappings_cache_ = other.evaluated_mappings_cache_;
+ base_cache_dirty_ = false;
+ }
}
int size() const final;
int resolution() const final;
void set_resolution(const int value) final;
+ void add_point(const blender::float3 position,
+ const HandleType handle_type_start,
+ const blender::float3 handle_position_start,
+ const HandleType handle_type_end,
+ const blender::float3 handle_position_end,
+ const float radius,
+ const float tilt);
+
+ void drop_front(const int count) final;
+ void drop_back(const int count) final;
+
blender::MutableSpan<blender::float3> positions() final;
blender::Span<blender::float3> positions() const final;
blender::MutableSpan<float> radii() final;
@@ -257,39 +240,32 @@ class BezierSpline final : public Spline {
blender::Span<blender::float3> handle_positions_end() const;
blender::MutableSpan<blender::float3> handle_positions_end();
- void add_point(const blender::float3 position,
- const HandleType handle_type_start,
- const blender::float3 handle_position_start,
- const HandleType handle_type_end,
- const blender::float3 handle_position_end,
- const float radius,
- const float tilt);
-
- void drop_front(const int count) final;
- void drop_back(const int count) final;
-
- int evaluated_points_size() const final;
-
bool point_is_sharp(const int index) const;
bool handle_start_is_automatic(const int index) const;
bool handle_end_is_automatic(const int index) const;
void move_control_point(const int index, const blender::float3 new_position);
+ int evaluated_points_size() const final;
+
+ blender::Span<PointMapping> evaluated_mappings() const;
+ blender::Span<blender::float3> evaluated_positions() const final;
+
+ virtual blender::fn::GVArrayPtr interpolate_to_evaluated_points(
+ const blender::fn::GVArray &source_data) const;
+
protected:
void correct_final_tangents() const;
private:
void correct_end_tangents() const final;
- void ensure_base_cache() const final;
bool segment_is_vector(const int start_index) const;
void evaluate_bezier_segment(const int index,
const int next_index,
int &offset,
blender::MutableSpan<blender::float3> positions,
blender::MutableSpan<PointMapping> mappings) const;
- void evaluate_bezier_position_and_mapping(blender::MutableSpan<blender::float3> positions,
- blender::MutableSpan<PointMapping> mappings) const;
+ void evaluate_bezier_position_and_mapping() const;
};
class NURBSpline final : public Spline {
@@ -318,13 +294,17 @@ class NURBSpline final : public Spline {
mutable std::mutex knots_mutex_;
mutable blender::Vector<float> knots_;
+ mutable bool position_cache_dirty_ = true;
+ mutable std::mutex position_cache_mutex_;
+ mutable blender::Vector<blender::float3> evaluated_positions_cache_;
+
mutable bool basis_cache_dirty_ = true;
mutable std::mutex basis_cache_mutex_;
- mutable blender::Vector<BasisCache> weight_cache_;
+ mutable blender::Vector<BasisCache> basis_cache_;
public:
SplinePtr copy() const final;
- NURBSpline() = default;
+ NURBSpline() : Spline(Type::NURBS){};
NURBSpline(const NURBSpline &other)
: Spline((Spline &)other),
positions_(other.positions_),
@@ -342,6 +322,14 @@ class NURBSpline final : public Spline {
uint8_t order() const;
void set_order(const uint8_t value);
+ void add_point(const blender::float3 position,
+ const float radius,
+ const float tilt,
+ const float weight);
+
+ void drop_front(const int count) final;
+ void drop_back(const int count) final;
+
bool check_valid_size_and_order() const;
int knots_size() const;
@@ -357,22 +345,15 @@ class NURBSpline final : public Spline {
blender::MutableSpan<float> weights();
blender::Span<float> weights() const;
- void add_point(const blender::float3 position,
- const float radius,
- const float tilt,
- const float weight);
-
- void drop_front(const int count) final;
- void drop_back(const int count) final;
-
int evaluated_points_size() const final;
+ blender::Span<blender::float3> evaluated_positions() const final;
+
blender::fn::GVArrayPtr interpolate_to_evaluated_points(
- const blender::fn::GVArray &source_data) const;
+ const blender::fn::GVArray &source_data) const final;
protected:
void correct_end_tangents() const final;
- void ensure_base_cache() const final;
void calculate_knots() const;
void calculate_basis_cache() const;
};
@@ -386,7 +367,7 @@ class PolySpline final : public Spline {
private:
public:
SplinePtr copy() const final;
- PolySpline() = default;
+ PolySpline() : Spline(Type::Bezier){};
PolySpline(const PolySpline &other)
: Spline((Spline &)other),
positions_(other.positions_),
@@ -399,6 +380,11 @@ class PolySpline final : public Spline {
int resolution() const final;
void set_resolution(const int value) final;
+ void add_point(const blender::float3 position, const float radius, const float tilt);
+
+ void drop_front(const int count) final;
+ void drop_back(const int count) final;
+
blender::MutableSpan<blender::float3> positions() final;
blender::Span<blender::float3> positions() const final;
blender::MutableSpan<float> radii() final;
@@ -406,16 +392,15 @@ class PolySpline final : public Spline {
blender::MutableSpan<float> tilts() final;
blender::Span<float> tilts() const final;
- void add_point(const blender::float3 position, const float radius, const float tilt);
+ int evaluated_points_size() const final;
- void drop_front(const int count) final;
- void drop_back(const int count) final;
+ blender::Span<blender::float3> evaluated_positions() const final;
- int evaluated_points_size() const final;
+ blender::fn::GVArrayPtr interpolate_to_evaluated_points(
+ const blender::fn::GVArray &source_data) const final;
protected:
void correct_end_tangents() const final;
- void ensure_base_cache() const final;
};
/* Proposed name to be different from DNA type. */
diff --git a/source/blender/blenkernel/intern/derived_curve.cc b/source/blender/blenkernel/intern/derived_curve.cc
index 9f5f9143641..7d2fc201742 100644
--- a/source/blender/blenkernel/intern/derived_curve.cc
+++ b/source/blender/blenkernel/intern/derived_curve.cc
@@ -150,7 +150,6 @@ DCurve *dcurve_from_dna_curve(const Curve &dna_curve)
case CU_BEZIER: {
std::unique_ptr<BezierSpline> spline = std::make_unique<BezierSpline>();
spline->set_resolution(nurb->resolu);
- spline->type = Spline::Type::Bezier;
spline->is_cyclic = nurb->flagu & CU_NURB_CYCLIC;
/* TODO: Optimize by reserving the correct size. */
@@ -170,7 +169,6 @@ DCurve *dcurve_from_dna_curve(const Curve &dna_curve)
case CU_NURBS: {
std::unique_ptr<NURBSpline> spline = std::make_unique<NURBSpline>();
spline->set_resolution(nurb->resolu);
- spline->type = Spline::Type::NURBS;
spline->is_cyclic = nurb->flagu & CU_NURB_CYCLIC;
spline->set_order(nurb->orderu);
spline->knots_mode = knots_mode_from_dna_nurb(nurb->flagu);
@@ -184,7 +182,6 @@ DCurve *dcurve_from_dna_curve(const Curve &dna_curve)
}
case CU_POLY: {
std::unique_ptr<PolySpline> spline = std::make_unique<PolySpline>();
- spline->type = Spline::Type::Poly;
spline->is_cyclic = nurb->flagu & CU_NURB_CYCLIC;
for (const BPoint &bp : Span(nurb->bp, nurb->pntsu)) {
diff --git a/source/blender/blenkernel/intern/spline_base.cc b/source/blender/blenkernel/intern/spline_base.cc
index 88ac8aa1a30..efc53442ec1 100644
--- a/source/blender/blenkernel/intern/spline_base.cc
+++ b/source/blender/blenkernel/intern/spline_base.cc
@@ -36,12 +36,16 @@ using blender::Vector;
*/
void Spline::mark_cache_invalid()
{
- base_cache_dirty_ = true;
tangent_cache_dirty_ = true;
normal_cache_dirty_ = true;
length_cache_dirty_ = true;
}
+Spline::Type Spline::type() const
+{
+ return this->type_;
+}
+
int Spline::evaluated_edges_size() const
{
const int points_len = this->evaluated_points_size();
@@ -54,12 +58,6 @@ float Spline::length() const
return this->evaluated_lengths().last();
}
-Span<float3> Spline::evaluated_positions() const
-{
- this->ensure_base_cache();
- return evaluated_positions_cache_;
-}
-
int Spline::segments_size() const
{
const int points_len = this->size();
@@ -67,22 +65,6 @@ int Spline::segments_size() const
return this->is_cyclic ? points_len : points_len - 1;
}
-/**
- * Returns non-owning access to the cache of mappings from the evaluated points to
- * the corresponing control points. Unless the spline is cyclic, the last control point
- * index will never be included as an index.
- */
-Span<PointMapping> Spline::evaluated_mappings() const
-{
- this->ensure_base_cache();
-#ifdef DEBUG
- if (evaluated_mapping_cache_.last().control_point_index == this->size() - 1) {
- BLI_assert(this->is_cyclic);
- }
-#endif
- return evaluated_mapping_cache_;
-}
-
static void accumulate_lengths(Span<float3> positions,
const bool is_cyclic,
MutableSpan<float> lengths)
diff --git a/source/blender/blenkernel/intern/spline_bezier.cc b/source/blender/blenkernel/intern/spline_bezier.cc
index b8f3717c464..ec86c81d7c3 100644
--- a/source/blender/blenkernel/intern/spline_bezier.cc
+++ b/source/blender/blenkernel/intern/spline_bezier.cc
@@ -331,9 +331,24 @@ void BezierSpline::evaluate_bezier_segment(const int index,
}
}
-void BezierSpline::evaluate_bezier_position_and_mapping(MutableSpan<float3> positions,
- MutableSpan<PointMapping> mappings) const
+void BezierSpline::evaluate_bezier_position_and_mapping() const
{
+ if (!this->base_cache_dirty_) {
+ return;
+ }
+
+ std::lock_guard lock{this->base_cache_mutex_};
+ if (!this->base_cache_dirty_) {
+ return;
+ }
+
+ const int total = this->evaluated_points_size();
+ this->evaluated_positions_cache_.resize(total);
+ this->evaluated_mappings_cache_.resize(total);
+
+ MutableSpan<float3> positions = this->evaluated_positions_cache_;
+ MutableSpan<PointMapping> mappings = this->evaluated_mappings_cache_;
+
/* TODO: It would also be possible to store an array of offsets to facilitate parallelism here,
* maybe it is worth it? */
int offset = 0;
@@ -354,25 +369,72 @@ void BezierSpline::evaluate_bezier_position_and_mapping(MutableSpan<float3> posi
}
BLI_assert(offset == positions.size());
+
+ this->base_cache_dirty_ = false;
}
-void BezierSpline::ensure_base_cache() const
+/**
+ * Returns non-owning access to the cache of mappings from the evaluated points to
+ * the corresponing control points. Unless the spline is cyclic, the last control point
+ * index will never be included as an index.
+ */
+Span<PointMapping> BezierSpline::evaluated_mappings() const
{
- if (!this->base_cache_dirty_) {
- return;
+ this->evaluate_bezier_position_and_mapping();
+#ifdef DEBUG
+ if (evaluated_mappings_cache_.last().control_point_index == this->size() - 1) {
+ BLI_assert(this->is_cyclic);
}
+#endif
+ return this->evaluated_mappings_cache_;
+}
- std::lock_guard lock{this->base_cache_mutex_};
- if (!this->base_cache_dirty_) {
- return;
+Span<float3> BezierSpline::evaluated_positions() const
+{
+ this->evaluate_bezier_position_and_mapping();
+
+ return this->evaluated_positions_cache_;
+}
+
+template<typename T>
+static void interpolate_to_evaluated_points_impl(Span<PointMapping> mappings,
+ const blender::VArray<T> &source_data,
+ MutableSpan<T> result_data)
+{
+ blender::attribute_math::DefaultMixer<T> mixer(result_data);
+
+ for (const int i : result_data.index_range()) {
+ const PointMapping &mapping = mappings[i];
+ const int index = mapping.control_point_index;
+ const int next_index = (index + 1) % source_data.size();
+ const float factor = mapping.factor;
+
+ const T &value = source_data[index];
+ const T &next_value = source_data[next_index];
+
+ mixer.mix_in(i, value, 1.0f - factor);
+ mixer.mix_in(i, next_value, factor);
}
- const int total = this->evaluated_points_size();
- this->evaluated_positions_cache_.resize(total);
- this->evaluated_mapping_cache_.resize(total);
+ mixer.finalize();
+}
- this->evaluate_bezier_position_and_mapping(this->evaluated_positions_cache_,
- this->evaluated_mapping_cache_);
+blender::fn::GVArrayPtr BezierSpline::interpolate_to_evaluated_points(
+ const blender::fn::GVArray &source_data) const
+{
+ BLI_assert(source_data.size() == this->size());
+ Span<PointMapping> mappings = this->evaluated_mappings();
- this->base_cache_dirty_ = false;
-} \ No newline at end of file
+ blender::fn::GVArrayPtr new_varray;
+ blender::attribute_math::convert_to_static_type(source_data.type(), [&](auto dummy) {
+ using T = decltype(dummy);
+ if constexpr (!std::is_void_v<blender::attribute_math::DefaultMixer<T>>) {
+ Array<T> values(this->evaluated_points_size());
+ interpolate_to_evaluated_points_impl<T>(mappings, source_data.typed<T>(), values);
+ new_varray = std::make_unique<blender::fn::GVArray_For_ArrayContainer<Array<T>>>(
+ std::move(values));
+ }
+ });
+
+ return new_varray;
+}
diff --git a/source/blender/blenkernel/intern/spline_nurbs.cc b/source/blender/blenkernel/intern/spline_nurbs.cc
index f81dec2d8f3..0176c36582f 100644
--- a/source/blender/blenkernel/intern/spline_nurbs.cc
+++ b/source/blender/blenkernel/intern/spline_nurbs.cc
@@ -250,7 +250,7 @@ Span<float> NURBSpline::knots() const
this->calculate_knots();
- this->base_cache_dirty_ = false;
+ this->knots_dirty_ = false;
return this->knots_;
}
@@ -327,13 +327,13 @@ void NURBSpline::calculate_basis_cache() const
const int points_len = this->size();
const int evaluated_len = this->evaluated_points_size();
- this->weight_cache_.resize(evaluated_len);
+ this->basis_cache_.resize(evaluated_len);
const int order = this->order();
Span<float> control_weights = this->weights();
Span<float> knots = this->knots();
- MutableSpan<BasisCache> basis_cache = this->weight_cache_;
+ MutableSpan<BasisCache> basis_cache(this->basis_cache_);
/* This buffer is reused by each basis calculation to store temporary values.
* Theoretically it could likely be optimized away in the future. */
@@ -366,20 +366,20 @@ void NURBSpline::calculate_basis_cache() const
template<typename T>
void interpolate_to_evaluated_points_impl(Span<NURBSpline::BasisCache> weights,
- const blender::VArray<T> &old_values,
- MutableSpan<T> r_values)
+ const blender::VArray<T> &source_data,
+ MutableSpan<T> result_data)
{
- const int points_len = old_values.size();
- BLI_assert(r_values.size() == weights.size());
- blender::attribute_math::DefaultMixer<T> mixer(r_values);
+ const int points_len = source_data.size();
+ BLI_assert(result_data.size() == weights.size());
+ blender::attribute_math::DefaultMixer<T> mixer(result_data);
- for (const int i : r_values.index_range()) {
+ for (const int i : result_data.index_range()) {
Span<float> point_weights = weights[i].weights;
const int start_index = weights[i].start_index;
for (const int j : point_weights.index_range()) {
const int point_index = (start_index + j) % points_len;
- mixer.mix_in(i, old_values[point_index], point_weights[j]);
+ mixer.mix_in(i, source_data[point_index], point_weights[j]);
}
}
@@ -389,8 +389,10 @@ void interpolate_to_evaluated_points_impl(Span<NURBSpline::BasisCache> weights,
blender::fn::GVArrayPtr NURBSpline::interpolate_to_evaluated_points(
const blender::fn::GVArray &source_data) const
{
+ BLI_assert(source_data.size() == this->size());
+
this->calculate_basis_cache();
- Span<BasisCache> weights = this->weight_cache_;
+ Span<BasisCache> weights(this->basis_cache_);
blender::fn::GVArrayPtr new_varray;
blender::attribute_math::convert_to_static_type(source_data.type(), [&](auto dummy) {
@@ -406,31 +408,32 @@ blender::fn::GVArrayPtr NURBSpline::interpolate_to_evaluated_points(
return new_varray;
}
-void NURBSpline::ensure_base_cache() const
+Span<float3> NURBSpline::evaluated_positions() const
{
- if (!this->base_cache_dirty_) {
- return;
+ if (!this->position_cache_dirty_) {
+ return this->evaluated_positions_cache_;
}
- std::lock_guard lock{this->base_cache_mutex_};
- if (!this->base_cache_dirty_) {
- return;
+ std::lock_guard lock{this->position_cache_mutex_};
+ if (!this->position_cache_dirty_) {
+ return this->evaluated_positions_cache_;
}
const int total = this->evaluated_points_size();
this->evaluated_positions_cache_.resize(total);
- this->evaluated_mapping_cache_.resize(total);
blender::fn::GVArray_For_Span<float3> positions_varray(this->positions_.as_span());
blender::fn::GVArrayPtr evaluated_positions_varray = this->interpolate_to_evaluated_points(
positions_varray);
+ /* TODO: Avoid copying. */
Span<float3> evaluated_positions =
evaluated_positions_varray->typed<float3>()->get_internal_span();
-
for (const int i : IndexRange(total)) {
this->evaluated_positions_cache_[i] = evaluated_positions[i];
}
- this->base_cache_dirty_ = false;
+ this->position_cache_dirty_ = false;
+
+ return this->evaluated_positions_cache_;
}
diff --git a/source/blender/blenkernel/intern/spline_poly.cc b/source/blender/blenkernel/intern/spline_poly.cc
index aa9935cb055..ebd4bb1ccb0 100644
--- a/source/blender/blenkernel/intern/spline_poly.cc
+++ b/source/blender/blenkernel/intern/spline_poly.cc
@@ -17,6 +17,7 @@
#include "BLI_array.hh"
#include "BLI_listbase.h"
#include "BLI_span.hh"
+#include "BLI_virtual_array.hh"
#include "BKE_curve.h"
#include "BKE_spline.hh"
@@ -114,30 +115,30 @@ void PolySpline::correct_end_tangents() const
{
}
-/* TODO: Consider refactoring to avoid copying and "mapping" for poly splines. */
-void PolySpline::ensure_base_cache() const
+Span<float3> PolySpline::evaluated_positions() const
{
- if (!this->base_cache_dirty_) {
- return;
- }
-
- std::lock_guard lock{this->base_cache_mutex_};
- if (!this->base_cache_dirty_) {
- return;
- }
+ return this->positions();
+}
- const int total = this->evaluated_points_size();
- this->evaluated_positions_cache_.resize(total);
- this->evaluated_mapping_cache_.resize(total);
+// static blender::fn::GVArrayPtr bad_hack_copy_varray(const blender::fn::GVArray &source_data)
+// {
+// }
- MutableSpan<float3> positions = this->evaluated_positions_cache_.as_mutable_span();
- MutableSpan<PointMapping> mappings = this->evaluated_mapping_cache_.as_mutable_span();
+/* TODO: This function is hacky.. how to deal with poly spline interpolation? */
+blender::fn::GVArrayPtr PolySpline::interpolate_to_evaluated_points(
+ const blender::fn::GVArray &source_data) const
+{
+ BLI_assert(source_data.size() == this->size());
- for (const int i : positions.index_range()) {
- positions[i] = this->positions_[i];
- mappings[i].control_point_index = i;
- mappings[i].factor = 0.0f;
+ if (source_data.is_span()) {
+ return std::make_unique<blender::fn::GVArray_For_GSpan>(source_data.get_internal_span());
}
-
- this->base_cache_dirty_ = false;
-}
+ // if (source_data.is_single()) {
+ // BUFFER_FOR_CPP_TYPE_VALUE(source_data.type(), value);
+ // source_data.get_internal_single(value);
+ // return std::make_unique<blender::fn::GVArray_For_SingleValue>(
+ // source_data.type(), source_data.size(), value);
+ // }
+
+ return {};
+} \ No newline at end of file
diff --git a/source/blender/functions/FN_generic_virtual_array.hh b/source/blender/functions/FN_generic_virtual_array.hh
index c1af00fd4cd..a7a13c02461 100644
--- a/source/blender/functions/FN_generic_virtual_array.hh
+++ b/source/blender/functions/FN_generic_virtual_array.hh
@@ -642,7 +642,7 @@ class GVArray_For_EmbeddedVArray : public GVArray_For_VArray<T> {
public:
template<typename... Args>
- GVArray_For_EmbeddedVArray(const int64_t size, Args &&... args)
+ GVArray_For_EmbeddedVArray(const int64_t size, Args &&...args)
: GVArray_For_VArray<T>(size), embedded_varray_(std::forward<Args>(args)...)
{
this->varray_ = &embedded_varray_;
@@ -657,7 +657,7 @@ class GVMutableArray_For_EmbeddedVMutableArray : public GVMutableArray_For_VMuta
public:
template<typename... Args>
- GVMutableArray_For_EmbeddedVMutableArray(const int64_t size, Args &&... args)
+ GVMutableArray_For_EmbeddedVMutableArray(const int64_t size, Args &&...args)
: GVMutableArray_For_VMutableArray<T>(size), embedded_varray_(std::forward<Args>(args)...)
{
this->varray_ = &embedded_varray_;
@@ -714,6 +714,10 @@ class GVArray_For_Span : public GVArray_For_EmbeddedVArray<T, VArray_For_Span<T>
: GVArray_For_EmbeddedVArray<T, VArray_For_Span<T>>(data.size(), data)
{
}
+ GVArray_For_Span(const MutableSpan<T> data)
+ : GVArray_For_EmbeddedVArray<T, VArray_For_Span<T>>(data.size(), data.as_span())
+ {
+ }
};
/* Same as VMutableArray_For_MutableSpan, but for a generic virtual array. */
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 619ee71e387..dad5c579a3b 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
@@ -183,8 +183,10 @@ static void spline_extrude_to_mesh_data(const Spline &spline,
Span<float3> tangents = spline.evaluated_tangents();
Span<float3> normals = spline.evaluated_normals();
Span<float3> profile_positions = profile_spline.evaluated_positions();
- Array<float> radii(spline_vert_len);
- spline.interpolate_data_to_evaluated_points<float>(spline.radii(), radii);
+
+ GVArrayPtr radii_varray = spline.interpolate_to_evaluated_points(
+ blender::fn::GVArray_For_Span(spline.radii()));
+ GVArray_Typed<float> radii = radii_varray->typed<float>();
for (const int i_ring : IndexRange(spline_vert_len)) {
float4x4 point_matrix = float4x4::from_normalized_axis_data(
positions[i_ring], tangents[i_ring], normals[i_ring]);
@@ -198,7 +200,7 @@ static void spline_extrude_to_mesh_data(const Spline &spline,
}
/* Mark edge loops from sharp vector control points sharp. */
- if (profile_spline.type == Spline::Bezier) {
+ if (profile_spline.type() == Spline::Bezier) {
const BezierSpline &bezier_spline = static_cast<const BezierSpline &>(profile_spline);
Span<PointMapping> mappings = bezier_spline.evaluated_mappings();
for (const int i_profile : mappings.index_range()) {
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc
index 60b0e648e01..5e13210663f 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc
@@ -67,65 +67,66 @@ static void geo_node_curve_trim_update(bNodeTree *UNUSED(ntree), bNode *node)
namespace blender::nodes {
-static void interpolate_control_point(Spline &spline,
+static void interpolate_control_point(BezierSpline &spline,
const bool adjust_next,
const Spline::LookupResult lookup)
{
- const int evaluated_index = lookup.evaluated_index;
+ using namespace ::blender::fn;
+
+ const int eval_index = lookup.evaluated_index;
Span<PointMapping> mappings = spline.evaluated_mappings();
- const PointMapping &mapping = mappings[evaluated_index];
+ const PointMapping &mapping = mappings[eval_index];
const int index = mapping.control_point_index + (adjust_next ? 1 : 0);
Span<float3> evaluated_positions = spline.evaluated_positions();
- spline.positions()[index] = float3::interpolate(evaluated_positions[evaluated_index],
- evaluated_positions[evaluated_index + 1],
- lookup.factor);
+ spline.positions()[index] = float3::interpolate(
+ evaluated_positions[eval_index], evaluated_positions[eval_index + 1], lookup.factor);
/* TODO: Do this interpolation with attributes instead. */
- MutableSpan<float> radii = spline.radii();
- Array<float, 2> neighboring_radii(2);
- spline.interpolate_data_to_evaluated_points(
- radii.as_span(), neighboring_radii.as_mutable_span(), evaluated_index);
- radii[index] = interpf(neighboring_radii[1], neighboring_radii[0], lookup.factor);
-
- MutableSpan<float> tilts = spline.tilts();
- Array<float, 2> neighboring_tilts(2);
- spline.interpolate_data_to_evaluated_points(
- tilts.as_span(), neighboring_tilts.as_mutable_span(), evaluated_index);
- tilts[index] = interpf(neighboring_tilts[1], neighboring_tilts[0], lookup.factor);
-
- /* Interpolate information specific to different spline types. */
- if (NURBSpline *poly_spline = dynamic_cast<NURBSpline *>(&spline)) {
- MutableSpan<float> weights = poly_spline->weights();
- Array<float, 2> neighboring_weights(2);
- spline.interpolate_data_to_evaluated_points(
- weights.as_span(), neighboring_weights.as_mutable_span(), evaluated_index);
- weights[index] = interpf(neighboring_weights[1], neighboring_weights[0], lookup.factor);
+ {
+ MutableSpan<float> radii = spline.radii();
+ GVArrayPtr radii_varray = spline.interpolate_to_evaluated_points(GVArray_For_Span(radii));
+ GVArray_Typed<float> radii_eval = radii_varray->typed<float>();
+
+ radii[index] = interpf(radii_eval[eval_index + 1], radii_eval[eval_index], lookup.factor);
}
- else if (BezierSpline *bezier_spline = dynamic_cast<BezierSpline *>(&spline)) {
- MutableSpan<float3> handle_positions_start = bezier_spline->handle_positions_start();
- Array<float3, 2> neighboring_handle_positions_start(2);
- spline.interpolate_data_to_evaluated_points(
- handle_positions_start.as_span(),
- neighboring_handle_positions_start.as_mutable_span(),
- evaluated_index);
- handle_positions_start[index] = float3::interpolate(neighboring_handle_positions_start[0],
- neighboring_handle_positions_start[1],
- lookup.factor);
-
- MutableSpan<float3> handle_positions_end = bezier_spline->handle_positions_end();
- Array<float3, 2> neighboring_handle_positions_end(2);
- spline.interpolate_data_to_evaluated_points(handle_positions_end.as_span(),
- neighboring_handle_positions_end.as_mutable_span(),
- evaluated_index);
- handle_positions_end[index] = float3::interpolate(
- neighboring_handle_positions_end[0], neighboring_handle_positions_end[1], lookup.factor);
+
+ {
+ MutableSpan<float> tilts = spline.radii();
+ GVArrayPtr tilt_varray = spline.interpolate_to_evaluated_points(GVArray_For_Span(tilts));
+ GVArray_Typed<float> tilts_eval = tilt_varray->typed<float>();
+
+ tilts[index] = interpf(tilts_eval[eval_index + 1], tilts_eval[eval_index], lookup.factor);
+ }
+
+ {
+ MutableSpan<float3> handle_positions_start = spline.handle_positions_start();
+ GVArrayPtr handle_positions_start_varray = spline.interpolate_to_evaluated_points(
+ GVArray_For_Span(handle_positions_start));
+ GVArray_Typed<float3> handle_positions_start_eval =
+ handle_positions_start_varray->typed<float3>();
+
+ handle_positions_start[index] = float3::interpolate(
+ handle_positions_start_eval[eval_index],
+ handle_positions_start_eval[eval_index + 1],
+ lookup.factor);
+ }
+
+ {
+ MutableSpan<float3> handle_positions_end = spline.handle_positions_end();
+ GVArrayPtr handle_positions_end_varray = spline.interpolate_to_evaluated_points(
+ GVArray_For_Span(handle_positions_end));
+ GVArray_Typed<float3> handle_positions_end_eval = handle_positions_end_varray->typed<float3>();
+
+ handle_positions_end[index] = float3::interpolate(handle_positions_end_eval[eval_index],
+ handle_positions_end_eval[eval_index + 1],
+ lookup.factor);
}
}
-static void trim_spline(Spline &spline,
+static void trim_spline(BezierSpline &spline,
const Spline::LookupResult start,
const Spline::LookupResult end)
{
@@ -170,10 +171,13 @@ static void geo_node_curve_trim_exec(GeoNodeExecParams params)
const float factor_start = params.extract_input<float>("Start");
const float factor_end = params.extract_input<float>("End");
for (SplinePtr &spline : curve.splines) {
+ if (spline->type() != Spline::Type::Bezier) {
+ continue;
+ }
if (spline->is_cyclic) {
continue;
}
- trim_spline(*spline,
+ trim_spline(static_cast<BezierSpline &>(*spline),
spline->lookup_evaluated_factor(std::min(factor_start, factor_end)),
spline->lookup_evaluated_factor(std::max(factor_start, factor_end)));
}
@@ -183,11 +187,14 @@ static void geo_node_curve_trim_exec(GeoNodeExecParams params)
const float length_start = params.extract_input<float>("Start_001");
const float length_from_end = params.extract_input<float>("End_001");
for (SplinePtr &spline : curve.splines) {
+ if (spline->type() != Spline::Type::Bezier) {
+ continue;
+ }
if (spline->is_cyclic) {
continue;
}
const float length_end = spline->length() - length_from_end;
- trim_spline(*spline,
+ trim_spline(static_cast<BezierSpline &>(*spline),
spline->lookup_evaluated_length(std::min(length_start, length_end)),
spline->lookup_evaluated_length(std::max(length_start, length_end)));
}