Splines: Add a method for reversing a Spline
This moved the spline reversing logic out of the Curve Reverse geometry node and into the spline class. This allows a spline to reverse itself with a call to `my_spline.reverse()` The base class will reverse position, radii & tilt, while specialized versions are created for Bezier and Nurbs splines to reverse the additional data that these classes encapsulate. Differential Revision: https://developer.blender.org/D12501
This commit is contained in:
@@ -130,6 +130,11 @@ class Spline {
|
||||
virtual void translate(const blender::float3 &translation);
|
||||
virtual void transform(const blender::float4x4 &matrix);
|
||||
|
||||
/**
|
||||
* Change the direction of the spline (switch the start and end) without changing its shape.
|
||||
*/
|
||||
void reverse();
|
||||
|
||||
/**
|
||||
* Mark all caches for re-computation. This must be called after any operation that would
|
||||
* change the generated positions, tangents, normals, mapping, etc. of the evaluated points.
|
||||
@@ -210,6 +215,7 @@ class Spline {
|
||||
virtual void correct_end_tangents() const = 0;
|
||||
virtual void copy_settings(Spline &dst) const = 0;
|
||||
virtual void copy_data(Spline &dst) const = 0;
|
||||
virtual void reverse_impl() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -353,6 +359,9 @@ class BezierSpline final : public Spline {
|
||||
void correct_end_tangents() const final;
|
||||
void copy_settings(Spline &dst) const final;
|
||||
void copy_data(Spline &dst) const final;
|
||||
|
||||
protected:
|
||||
void reverse_impl() override;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -469,6 +478,7 @@ class NURBSpline final : public Spline {
|
||||
void correct_end_tangents() const final;
|
||||
void copy_settings(Spline &dst) const final;
|
||||
void copy_data(Spline &dst) const final;
|
||||
void reverse_impl() override;
|
||||
|
||||
void calculate_knots() const;
|
||||
blender::Span<BasisCache> calculate_basis_cache() const;
|
||||
@@ -519,6 +529,7 @@ class PolySpline final : public Spline {
|
||||
void correct_end_tangents() const final;
|
||||
void copy_settings(Spline &dst) const final;
|
||||
void copy_data(Spline &dst) const final;
|
||||
void reverse_impl() override;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
#include "BLI_task.hh"
|
||||
#include "BLI_timeit.hh"
|
||||
|
||||
#include "BKE_attribute_access.hh"
|
||||
#include "BKE_attribute_math.hh"
|
||||
#include "BKE_spline.hh"
|
||||
|
||||
#include "FN_generic_virtual_array.hh"
|
||||
@@ -28,6 +30,8 @@ using blender::float3;
|
||||
using blender::IndexRange;
|
||||
using blender::MutableSpan;
|
||||
using blender::Span;
|
||||
using blender::attribute_math::convert_to_static_type;
|
||||
using blender::bke::AttributeIDRef;
|
||||
using blender::fn::GMutableSpan;
|
||||
using blender::fn::GSpan;
|
||||
using blender::fn::GVArray;
|
||||
@@ -110,6 +114,31 @@ void Spline::transform(const blender::float4x4 &matrix)
|
||||
this->mark_cache_invalid();
|
||||
}
|
||||
|
||||
void Spline::reverse()
|
||||
{
|
||||
this->positions().reverse();
|
||||
this->radii().reverse();
|
||||
this->tilts().reverse();
|
||||
|
||||
this->attributes.foreach_attribute(
|
||||
[&](const AttributeIDRef &id, const AttributeMetaData &meta_data) {
|
||||
std::optional<blender::fn::GMutableSpan> attribute = this->attributes.get_for_write(id);
|
||||
if (!attribute) {
|
||||
BLI_assert_unreachable();
|
||||
return false;
|
||||
}
|
||||
convert_to_static_type(meta_data.data_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
attribute->typed<T>().reverse();
|
||||
});
|
||||
return true;
|
||||
},
|
||||
ATTR_DOMAIN_POINT);
|
||||
|
||||
this->reverse_impl();
|
||||
this->mark_cache_invalid();
|
||||
}
|
||||
|
||||
int Spline::evaluated_edges_size() const
|
||||
{
|
||||
const int eval_size = this->evaluated_points_size();
|
||||
|
||||
@@ -166,6 +166,17 @@ MutableSpan<float3> BezierSpline::handle_positions_right()
|
||||
return handle_positions_right_;
|
||||
}
|
||||
|
||||
void BezierSpline::reverse_impl()
|
||||
{
|
||||
this->handle_positions_left().reverse();
|
||||
this->handle_positions_right().reverse();
|
||||
std::swap(this->handle_positions_left_, this->handle_positions_right_);
|
||||
|
||||
this->handle_types_left().reverse();
|
||||
this->handle_types_right().reverse();
|
||||
std::swap(this->handle_types_left_, this->handle_types_right_);
|
||||
}
|
||||
|
||||
static float3 previous_position(Span<float3> positions, const bool cyclic, const int i)
|
||||
{
|
||||
if (i == 0) {
|
||||
|
||||
@@ -142,6 +142,11 @@ Span<float> NURBSpline::weights() const
|
||||
return weights_;
|
||||
}
|
||||
|
||||
void NURBSpline::reverse_impl()
|
||||
{
|
||||
this->weights().reverse();
|
||||
}
|
||||
|
||||
void NURBSpline::mark_cache_invalid()
|
||||
{
|
||||
basis_cache_dirty_ = true;
|
||||
|
||||
@@ -91,6 +91,10 @@ Span<float> PolySpline::tilts() const
|
||||
return tilts_;
|
||||
}
|
||||
|
||||
void PolySpline::reverse_impl()
|
||||
{
|
||||
}
|
||||
|
||||
void PolySpline::mark_cache_invalid()
|
||||
{
|
||||
tangent_cache_dirty_ = true;
|
||||
|
||||
Reference in New Issue
Block a user