[Bf-blender-cvs] [399aed9a81d] geometry-nodes-curve-support: Splines: Fix interpolation for bezier splines
Hans Goudey
noreply at git.blender.org
Mon Apr 26 21:17:31 CEST 2021
Commit: 399aed9a81d17960a0a0cbec7f145bf0bcb1868b
Author: Hans Goudey
Date: Mon Apr 26 14:17:25 2021 -0500
Branches: geometry-nodes-curve-support
https://developer.blender.org/rB399aed9a81d17960a0a0cbec7f145bf0bcb1868b
Splines: Fix interpolation for bezier splines
Also parallelize some of the calculations, since I was reworking
how the mapping was calculated anyway. I still haven't tuned the
grain size.
===================================================================
M source/blender/blenkernel/BKE_spline.hh
M source/blender/blenkernel/intern/spline_bezier.cc
M source/blender/blenkernel/intern/spline_nurbs.cc
===================================================================
diff --git a/source/blender/blenkernel/BKE_spline.hh b/source/blender/blenkernel/BKE_spline.hh
index 4e4b6eed156..c06273db828 100644
--- a/source/blender/blenkernel/BKE_spline.hh
+++ b/source/blender/blenkernel/BKE_spline.hh
@@ -90,18 +90,6 @@ class Spline {
Spline(Spline &other)
: type_(other.type_), is_cyclic(other.is_cyclic), normal_mode(other.normal_mode)
{
- if (!other.tangent_cache_dirty_) {
- evaluated_tangents_cache_ = other.evaluated_tangents_cache_;
- tangent_cache_dirty_ = false;
- }
- if (!other.normal_cache_dirty_) {
- evaluated_normals_cache_ = other.evaluated_normals_cache_;
- normal_cache_dirty_ = false;
- }
- if (!other.length_cache_dirty_) {
- evaluated_lengths_cache_ = other.evaluated_lengths_cache_;
- length_cache_dirty_ = false;
- }
}
virtual SplinePtr copy() const = 0;
@@ -188,12 +176,19 @@ class BezierSpline final : public Spline {
blender::Vector<blender::float3> handle_positions_end_;
blender::Vector<float> radii_;
blender::Vector<float> tilts_;
- int resolution_u_;
+ int resolution_;
- mutable bool base_cache_dirty_ = true;
- mutable std::mutex base_cache_mutex_;
- mutable blender::Vector<blender::float3> evaluated_positions_cache_;
- mutable blender::Vector<float> evaluated_mappings_cache_;
+ mutable bool offset_cache_dirty_ = true;
+ mutable std::mutex offset_cache_mutex_;
+ mutable blender::Vector<int> offset_cache_;
+
+ mutable bool position_cache_dirty_ = true;
+ mutable std::mutex position_cache_mutex_;
+ mutable blender::Vector<blender::float3> evaluated_position_cache_;
+
+ mutable bool mapping_cache_dirty_ = true;
+ mutable std::mutex mapping_cache_mutex_;
+ mutable blender::Vector<float> evaluated_mapping_cache_;
public:
virtual SplinePtr copy() const final;
@@ -207,13 +202,8 @@ class BezierSpline final : public Spline {
handle_positions_end_(other.handle_positions_end_),
radii_(other.radii_),
tilts_(other.tilts_),
- resolution_u_(other.resolution_u_)
+ resolution_(other.resolution_)
{
- 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;
@@ -256,6 +246,7 @@ class BezierSpline final : public Spline {
void mark_cache_invalid() final;
int evaluated_points_size() const final;
+ blender::Span<int> control_point_offsets() const;
blender::Span<float> evaluated_mappings() const;
blender::Span<blender::float3> evaluated_positions() const final;
struct InterpolationData {
@@ -268,18 +259,13 @@ class BezierSpline final : public Spline {
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;
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<float> mappings) const;
- void evaluate_bezier_position_and_mapping() const;
+ blender::MutableSpan<blender::float3> positions) const;
+ blender::Array<int> evaluated_point_offsets() const;
};
/**
@@ -307,7 +293,7 @@ class NURBSpline final : public Spline {
blender::Vector<float> radii_;
blender::Vector<float> tilts_;
blender::Vector<float> weights_;
- int resolution_u_;
+ int resolution_;
uint8_t order_;
mutable bool knots_dirty_ = true;
@@ -316,7 +302,7 @@ class NURBSpline final : public Spline {
mutable bool position_cache_dirty_ = true;
mutable std::mutex position_cache_mutex_;
- mutable blender::Vector<blender::float3> evaluated_positions_cache_;
+ mutable blender::Vector<blender::float3> evaluated_position_cache_;
mutable bool basis_cache_dirty_ = true;
mutable std::mutex basis_cache_mutex_;
@@ -331,7 +317,7 @@ class NURBSpline final : public Spline {
radii_(other.radii_),
tilts_(other.tilts_),
weights_(other.weights_),
- resolution_u_(other.resolution_u_),
+ resolution_(other.resolution_),
order_(other.order_)
{
}
diff --git a/source/blender/blenkernel/intern/spline_bezier.cc b/source/blender/blenkernel/intern/spline_bezier.cc
index dea91b2c0fd..4a3f5cdbf19 100644
--- a/source/blender/blenkernel/intern/spline_bezier.cc
+++ b/source/blender/blenkernel/intern/spline_bezier.cc
@@ -16,6 +16,7 @@
#include "BLI_array.hh"
#include "BLI_span.hh"
+#include "BLI_task.hh"
#include "BKE_spline.hh"
@@ -46,12 +47,12 @@ int BezierSpline::size() const
int BezierSpline::resolution() const
{
- return this->resolution_u_;
+ return this->resolution_;
}
void BezierSpline::set_resolution(const int value)
{
- this->resolution_u_ = value;
+ this->resolution_ = value;
this->mark_cache_invalid();
}
@@ -197,7 +198,9 @@ bool BezierSpline::segment_is_vector(const int index) const
void BezierSpline::mark_cache_invalid()
{
- this->base_cache_dirty_ = true;
+ this->offset_cache_dirty_ = true;
+ this->position_cache_dirty_ = true;
+ this->mapping_cache_dirty_ = true;
this->tangent_cache_dirty_ = true;
this->normal_cache_dirty_ = true;
this->length_cache_dirty_ = true;
@@ -205,45 +208,15 @@ void BezierSpline::mark_cache_invalid()
int BezierSpline::evaluated_points_size() const
{
- BLI_assert(this->size() > 0);
-#ifndef DEBUG
- if (!this->base_cache_dirty_) {
- /* In a non-debug build, assume that the cache size has not changed, and that any operation
- * that would cause the cache to change its length would also mark the cache dirty. This
- * assumption is checked at the end of this function in a debug build. */
- return this->evaluated_positions_cache_.size();
- }
-#endif
-
- int total_len = 0;
- for (const int i : IndexRange(this->size() - 1)) {
- if (this->segment_is_vector(i)) {
- total_len += 1;
- }
- else {
- total_len += this->resolution_u_;
- }
- }
+ const int points_len = this->size();
+ BLI_assert(points_len > 0);
+ const int last_offset = this->control_point_offsets().last();
if (this->is_cyclic) {
- if (segment_is_vector(this->size() - 1)) {
- total_len++;
- }
- else {
- total_len += this->resolution_u_;
- }
- }
- else {
- /* Since evaulating the bezier doesn't add the final point's position,
- * it must be added manually in the non-cyclic case. */
- total_len++;
+ return last_offset + (this->segment_is_vector(points_len - 1) ? 0 : this->resolution_);
}
- if (!this->base_cache_dirty_) {
- BLI_assert(this->evaluated_positions_cache_.size() == total_len);
- }
-
- return total_len;
+ return last_offset + 1;
}
/**
@@ -291,95 +264,52 @@ static void bezier_forward_difference_3d(const float3 &point_0,
}
}
-static void evaluate_segment_mapping(Span<float3> evaluated_positions,
- MutableSpan<float> mappings,
- const int index)
-{
- float length = 0.0f;
- mappings[0] = index;
- for (const int i : IndexRange(1, mappings.size() - 1)) {
- length += float3::distance(evaluated_positions[i - 1], evaluated_positions[i]);
- mappings[i] = length;
- }
-
- /* To get the factors instead of the accumulated lengths, divide the mapping factors by the
- * accumulated length. */
- if (length != 0.0f) {
- for (float &mapping : mappings) {
- mapping = mapping / length + index;
- }
- }
-}
-
void BezierSpline::evaluate_bezier_segment(const int index,
const int next_index,
- int &offset,
- MutableSpan<float3> positions,
- MutableSpan<float> mappings) const
+ MutableSpan<float3> positions) const
{
if (this->segment_is_vector(index)) {
- positions[offset] = positions_[index];
- mappings[offset] = index;
- offset++;
+ positions.first() = this->positions_[index];
}
else {
bezier_forward_difference_3d(this->positions_[index],
this->handle_positions_end_[index],
this->handle_positions_start_[next_index],
this->positions_[next_index],
- positions.slice(offset, this->resolution_u_));
- evaluate_segment_mapping(positions.slice(offset, this->resolution_u_),
- mappings.slice(offset, this->resolution_u_),
- index);
- offset += this->resolution_u_;
+ positions);
}
}
-void BezierSpline::evaluate_bezier_position_and_mapping() const
+/**
+ * Returns access to a cache of offsets into the evaluated point array for each control point.
+ * This is important because while most control point edges generate the number of edges specified
+ * by the resolution, vector segments only generate one edge.
+ */
+Span<int> BezierSpline::control_point_offsets() const
{
- if (!this->base_cache_dirty_) {
- return;
+ if (!this->offset_cache_dirty_) {
+ return this->offset_cache_;
}
- std::lock_guard lock{this->base_cache_mutex_};
- if (!this->base_cache_dirty_) {
- return;
+ std::lock_guard lock{this->offset_cache_mutex_};
+ if (!this->offset_cache_dirty_) {
+ return this->offset_cache_;
}
- const int total = this->evaluated_points_size();
- this->evaluated_positions_cache_.resize(total);
- this->evaluated_mappings_cache_.resize(total);
+ const int points_len = this->size();
+ this->offset_cache_.resize(points_len);
- MutableSpan<float3> positions = this->evaluated_positions_cache_;
- MutableSpan<float> mappings = this->evaluated_mappings_cache_;
+ MutableSpan<int> offsets
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list