[Bf-blender-cvs] [2c73e16d1cc] geometry-nodes-curve-support: Geometry Nodes Curves: Sample positions from NURBS curves
Hans Goudey
noreply at git.blender.org
Tue Apr 20 21:38:56 CEST 2021
Commit: 2c73e16d1ccdcb2faf6862472385be39af2ed44a
Author: Hans Goudey
Date: Tue Apr 20 14:38:46 2021 -0500
Branches: geometry-nodes-curve-support
https://developer.blender.org/rB2c73e16d1ccdcb2faf6862472385be39af2ed44a
Geometry Nodes Curves: Sample positions from NURBS curves
===================================================================
M source/blender/blenkernel/BKE_derived_curve.hh
M source/blender/blenkernel/intern/derived_curve.cc
M source/blender/blenkernel/intern/derived_curve_spline_base.cc
M source/blender/blenkernel/intern/derived_curve_spline_bezier.cc
M source/blender/blenkernel/intern/derived_curve_spline_nurbs.cc
===================================================================
diff --git a/source/blender/blenkernel/BKE_derived_curve.hh b/source/blender/blenkernel/BKE_derived_curve.hh
index 646fa08e455..f662f53e7c1 100644
--- a/source/blender/blenkernel/BKE_derived_curve.hh
+++ b/source/blender/blenkernel/BKE_derived_curve.hh
@@ -119,6 +119,7 @@ class Spline {
virtual SplinePtr copy() const = 0;
virtual int size() const = 0;
+ int segments_size() const;
virtual int resolution() const = 0;
virtual void set_resolution(const int value) = 0;
@@ -290,6 +291,14 @@ class BezierSpline final : public Spline {
};
class NURBSpline final : public Spline {
+ public:
+ enum KnotsMode {
+ Normal,
+ EndPoint,
+ Bezier,
+ };
+ KnotsMode knots_mode;
+
private:
blender::Vector<blender::float3> positions_;
blender::Vector<float> radii_;
@@ -298,6 +307,10 @@ class NURBSpline final : public Spline {
int resolution_u_;
uint8_t order_;
+ mutable bool knots_dirty_ = true;
+ mutable std::mutex knots_mutex_;
+ mutable blender::Vector<float> knots_;
+
public:
SplinePtr copy() const final;
NURBSpline() = default;
@@ -318,6 +331,9 @@ class NURBSpline final : public Spline {
uint8_t order() const;
void set_order(const uint8_t value);
+ bool check_valid_size_and_order() const;
+ int knots_size() const;
+
blender::MutableSpan<blender::float3> positions() final;
blender::Span<blender::float3> positions() const final;
blender::MutableSpan<float> radii() final;
@@ -325,6 +341,8 @@ class NURBSpline final : public Spline {
blender::MutableSpan<float> tilts() final;
blender::Span<float> tilts() const final;
+ blender::Span<float> knots() const;
+
blender::MutableSpan<float> weights();
blender::Span<float> weights() const;
@@ -341,6 +359,9 @@ class NURBSpline final : public Spline {
protected:
void correct_end_tangents() const final;
void ensure_base_cache() const final;
+ void evaluate_position_and_mapping(blender::MutableSpan<blender::float3> positions,
+ blender::MutableSpan<PointMapping> mappings) const;
+ void calculate_knots() const;
};
class PolySpline final : public Spline {
diff --git a/source/blender/blenkernel/intern/derived_curve.cc b/source/blender/blenkernel/intern/derived_curve.cc
index ae217892ae8..36b3dd2aff6 100644
--- a/source/blender/blenkernel/intern/derived_curve.cc
+++ b/source/blender/blenkernel/intern/derived_curve.cc
@@ -122,6 +122,21 @@ static Spline::NormalCalculationMode normal_mode_from_dna_curve(const int twist_
return Spline::NormalCalculationMode::Minimum;
}
+static NURBSpline::KnotsMode knots_mode_from_dna_nurb(const short flag)
+{
+ switch (flag & (CU_NURB_ENDPOINT | CU_NURB_BEZIER)) {
+ case CU_NURB_ENDPOINT:
+ return NURBSpline::KnotsMode::EndPoint;
+ case CU_NURB_BEZIER:
+ return NURBSpline::KnotsMode::Bezier;
+ default:
+ return NURBSpline::KnotsMode::Normal;
+ }
+
+ BLI_assert_unreachable();
+ return NURBSpline::KnotsMode::Normal;
+}
+
DCurve *dcurve_from_dna_curve(const Curve &dna_curve)
{
DCurve *curve = new DCurve();
@@ -153,6 +168,18 @@ DCurve *dcurve_from_dna_curve(const Curve &dna_curve)
break;
}
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);
+
+ for (const BPoint &bp : Span(nurb->bp, nurb->pntsu)) {
+ spline->add_point(bp.vec, bp.radius, bp.tilt, bp.vec[3]);
+ }
+
+ curve->splines.append(std::move(spline));
break;
}
case CU_POLY: {
diff --git a/source/blender/blenkernel/intern/derived_curve_spline_base.cc b/source/blender/blenkernel/intern/derived_curve_spline_base.cc
index e2b754660f2..3140a5d55ca 100644
--- a/source/blender/blenkernel/intern/derived_curve_spline_base.cc
+++ b/source/blender/blenkernel/intern/derived_curve_spline_base.cc
@@ -20,7 +20,6 @@
#include "DNA_curve_types.h"
-#include "BKE_curve.h"
#include "BKE_derived_curve.hh"
using blender::Array;
@@ -61,6 +60,13 @@ Span<float3> Spline::evaluated_positions() const
return evaluated_positions_cache_;
}
+int Spline::segments_size() const
+{
+ const int points_len = this->size();
+
+ 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
diff --git a/source/blender/blenkernel/intern/derived_curve_spline_bezier.cc b/source/blender/blenkernel/intern/derived_curve_spline_bezier.cc
index c84d23b8c89..b0ff18116d1 100644
--- a/source/blender/blenkernel/intern/derived_curve_spline_bezier.cc
+++ b/source/blender/blenkernel/intern/derived_curve_spline_bezier.cc
@@ -18,7 +18,6 @@
#include "BLI_listbase.h"
#include "BLI_span.hh"
-#include "BKE_curve.h"
#include "BKE_derived_curve.hh"
using blender::Array;
diff --git a/source/blender/blenkernel/intern/derived_curve_spline_nurbs.cc b/source/blender/blenkernel/intern/derived_curve_spline_nurbs.cc
index 9d591b3d6b6..6e0bf81c13f 100644
--- a/source/blender/blenkernel/intern/derived_curve_spline_nurbs.cc
+++ b/source/blender/blenkernel/intern/derived_curve_spline_nurbs.cc
@@ -18,7 +18,6 @@
#include "BLI_listbase.h"
#include "BLI_span.hh"
-#include "BKE_curve.h"
#include "BKE_derived_curve.hh"
using blender::Array;
@@ -56,6 +55,18 @@ void NURBSpline::set_resolution(const int value)
this->mark_cache_invalid();
}
+uint8_t NURBSpline::order() const
+{
+ return this->order_;
+}
+
+void NURBSpline::set_order(const uint8_t value)
+{
+ /* TODO: Check the spline length. */
+ BLI_assert(value >= 2 && value <= 6);
+ this->order_ = value;
+}
+
void NURBSpline::add_point(const float3 position,
const float radius,
const float tilt,
@@ -65,6 +76,7 @@ void NURBSpline::add_point(const float3 position,
this->radii_.append(radius);
this->tilts_.append(tilt);
this->weights_.append(weight);
+ this->knots_dirty_ = true;
}
void NURBSpline::drop_front(const int count)
@@ -123,13 +135,252 @@ Span<float> NURBSpline::weights() const
int NURBSpline::evaluated_points_size() const
{
- return 0;
+ return this->resolution_u_ * this->segments_size();
}
void NURBSpline::correct_end_tangents() const
{
}
+bool NURBSpline::check_valid_size_and_order() const
+{
+ if (this->size() < this->order_) {
+ return false;
+ }
+
+ if (!this->is_cyclic && this->knots_mode == KnotsMode::Bezier) {
+ if (this->order_ == 4) {
+ if (this->size() < 5) {
+ return false;
+ }
+ }
+ else if (this->order_ != 3) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+int NURBSpline::knots_size() const
+{
+ const int size = this->size() + this->order_;
+ return this->is_cyclic ? size + this->order_ - 1 : size;
+}
+
+void NURBSpline::calculate_knots() const
+{
+ const KnotsMode mode = this->knots_mode;
+ const int length = this->size();
+ const int order = this->order_;
+
+ this->knots_.resize(this->knots_size());
+
+ MutableSpan<float> knots = this->knots_;
+
+ if (mode == NURBSpline::KnotsMode::Normal || this->is_cyclic) {
+ for (const int i : knots.index_range()) {
+ knots[i] = static_cast<float>(i);
+ }
+ }
+ else if (mode == NURBSpline::KnotsMode::EndPoint) {
+ float k = 0.0f;
+ for (const int i : IndexRange(1, knots.size())) {
+ knots[i - 1] = k;
+ if (i >= order && i <= length) {
+ k += 1.0f;
+ }
+ }
+ }
+ else if (mode == NURBSpline::KnotsMode::Bezier) {
+ BLI_assert(ELEM(order, 3, 4));
+ if (order == 3) {
+ float k = 0.6f;
+ for (const int i : knots.index_range()) {
+ if (i >= order && i <= length) {
+ k += 0.5f;
+ }
+ knots[i] = std::floor(k);
+ }
+ }
+ else {
+ float k = 0.34f;
+ for (const int i : knots.index_range()) {
+ knots[i] = std::floor(k);
+ k += 1.0f / 3.0f;
+ }
+ }
+ }
+
+ if (this->is_cyclic) {
+ const int b = length + order - 1;
+ if (order > 2) {
+ for (const int i : IndexRange(1, order - 2)) {
+ if (knots[b] != knots[b - i]) {
+ if (i == order - 1) {
+ knots[length + order - 2] += 1.0f;
+ break;
+ }
+ }
+ }
+ }
+
+ int c = order;
+ for (int i = b; i < this->knots_size(); i++) {
+ knots[i] = knots[i - 1] + (knots[c] - knots[c - 1]);
+ c--;
+ }
+ }
+}
+
+Span<float> NURBSpline::knots() const
+{
+ if (!this->knots_dirty_) {
+ BLI_assert(this->knots_.size() == this->size() + this->order_);
+ return this->knots_;
+ }
+
+ std::lock_guard lock{this->knots_mutex_};
+ if (!this->knots_dirty_) {
+ BLI_assert(this->knots_.size() == this->size() + this->order_);
+ return this->knots_;
+ }
+
+ this->calculate_knots();
+
+ this->base_cache_dirty_ = false;
+
+ return this->knots_;
+}
+
+/* TODO: Better variables names, simplify logic once it works. */
+static void nurb_basis(const float parameter,
+ const int points_len,
+ const int order,
+ Span<float> knots,
+ MutableSpan<float> basis,
+ int &start,
+ int &end)
+{
+ /* Clamp parameter due to floating point inaccuracy. TODO: Look into using doubles. */
+ const float t = std::clamp(parameter, knots[0], knots[points_len + order - 1]);
+
+ int i1 = 0;
+ int i2 = 0;
+ for (int i = 0; i < points_len + order - 1; i++) {
+ if ((knots[i] != knots[i + 1]) && (t >= knots[i]) && (t <= knots[i + 1])) {
+ basis[i] = 1.0f;
+ i1 = std::max(i - order - 1, 0);
+ i2 = i;
+ i++;
+ while (i < points_len + order - 1) {
+ basis[i] = 0.0f;
+ i++;
+ }
+ break;
+ }
+ basis[i] = 0.0f;
+ }
+ basis[points_len + order - 1] = 0.0f;
+
+ for (int i_order = 2; i_order <= order; i_order++) {
+ if (i2 +
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list