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:
parent
a866a32ff2
commit
231948f33f
|
@ -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;
|
||||
|
|
|
@ -49,47 +49,9 @@ static void geo_node_curve_reverse_exec(GeoNodeExecParams params)
|
|||
|
||||
threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) {
|
||||
for (const int i : range) {
|
||||
if (!selection[i]) {
|
||||
continue;
|
||||
if (selection[i]) {
|
||||
splines[i]->reverse();
|
||||
}
|
||||
|
||||
splines[i]->positions().reverse();
|
||||
splines[i]->radii().reverse();
|
||||
splines[i]->tilts().reverse();
|
||||
|
||||
splines[i]->attributes.foreach_attribute(
|
||||
[&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) {
|
||||
std::optional<blender::fn::GMutableSpan> output_attribute =
|
||||
splines[i]->attributes.get_for_write(attribute_id);
|
||||
if (!output_attribute) {
|
||||
BLI_assert_unreachable();
|
||||
return false;
|
||||
}
|
||||
attribute_math::convert_to_static_type(meta_data.data_type, [&](auto dummy) {
|
||||
using T = decltype(dummy);
|
||||
output_attribute->typed<T>().reverse();
|
||||
});
|
||||
return true;
|
||||
},
|
||||
ATTR_DOMAIN_POINT);
|
||||
|
||||
/* Deal with extra info on derived types. */
|
||||
if (BezierSpline *spline = dynamic_cast<BezierSpline *>(splines[i].get())) {
|
||||
spline->handle_types_left().reverse();
|
||||
spline->handle_types_right().reverse();
|
||||
|
||||
spline->handle_positions_left().reverse();
|
||||
spline->handle_positions_right().reverse();
|
||||
for (int i : spline->handle_positions_left().index_range()) {
|
||||
std::swap(spline->handle_positions_left()[i], spline->handle_positions_right()[i]);
|
||||
}
|
||||
}
|
||||
else if (NURBSpline *spline = dynamic_cast<NURBSpline *>(splines[i].get())) {
|
||||
spline->weights().reverse();
|
||||
}
|
||||
/* Nothing to do for poly splines. */
|
||||
|
||||
splines[i]->mark_cache_invalid();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue