[Bf-blender-cvs] [073bf63a9db] geometry-nodes-curve-support: Geometry Nodes Curves: Cleanup, progres on evaluation for bezier splines
Hans Goudey
noreply at git.blender.org
Mon Apr 5 06:09:26 CEST 2021
Commit: 073bf63a9dbe69a3f2a6c8899832ade978d7cfc5
Author: Hans Goudey
Date: Sun Apr 4 23:09:20 2021 -0500
Branches: geometry-nodes-curve-support
https://developer.blender.org/rB073bf63a9dbe69a3f2a6c8899832ade978d7cfc5
Geometry Nodes Curves: Cleanup, progres on evaluation for bezier splines
===================================================================
M source/blender/blenkernel/BKE_derived_curve.hh
M source/blender/blenkernel/intern/derived_curve.cc
M source/blender/blenlib/BLI_float3.hh
M source/blender/blenlib/BLI_span.hh
M source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
M source/blender/nodes/geometry/nodes/node_geo_transform.cc
===================================================================
diff --git a/source/blender/blenkernel/BKE_derived_curve.hh b/source/blender/blenkernel/BKE_derived_curve.hh
index bbe06eb6a0e..0f0b228b7ac 100644
--- a/source/blender/blenkernel/BKE_derived_curve.hh
+++ b/source/blender/blenkernel/BKE_derived_curve.hh
@@ -29,33 +29,23 @@
struct Curve;
-enum class BezierHandleType {
- Free,
- Auto,
- Vector,
- Align,
-};
-
-struct ControlPoint {
+struct BezierPoint {
+ enum HandleType {
+ Free,
+ Auto,
+ Vector,
+ Align,
+ };
+ blender::float3 handle_position_a;
blender::float3 position;
+ blender::float3 handle_position_b;
+ HandleType handle_type_a;
+ HandleType handle_type_b;
float radius;
/* User defined tilt in radians, added on top of the auto-calculated tilt. */
float tilt;
};
-struct ControlPointBezier : ControlPoint {
- blender::float3 handle_position_a;
- blender::float3 handle_position_b;
- BezierHandleType handle_type_a;
- BezierHandleType handle_type_b;
-};
-
-struct ControlPointNURBS : ControlPoint {
- blender::float3 position;
- float radius;
- float weight;
-};
-
class Spline {
public:
enum Type {
@@ -73,23 +63,26 @@ class Spline {
virtual int evaluated_points_size() const = 0;
virtual void ensure_evaluation_cache() const = 0;
virtual blender::Span<blender::float3> evaluated_positions() const = 0;
+ virtual blender::Span<blender::float3> evaluated_tangents() const = 0;
+ virtual blender::Span<blender::float3> evaluated_normals() const = 0;
};
class BezierSpline : public Spline {
public:
/* TODO: Figure out if I want to store this as a few separate vectors directly in the spline. */
- blender::Vector<ControlPointBezier> control_points;
+ blender::Vector<BezierPoint> control_points;
int resolution_u;
static constexpr inline Type static_type = Spline::Type::Bezier;
private:
- bool cache_dirty = true;
-
- int32_t flag; /* Cyclic, smooth. */
+ bool is_cyclic = false;
- std::mutex cache_mutex;
- blender::Vector<blender::float3> evaluated_spline_cache;
+ mutable std::mutex cache_mutex;
+ mutable bool cache_dirty = true;
+ mutable blender::Vector<blender::float3> evaluated_positions_cache;
+ mutable blender::Vector<blender::float3> evaluated_tangents_cache;
+ mutable blender::Vector<blender::float3> evaluated_normals_cache;
public:
int size() const final
@@ -117,15 +110,36 @@ class BezierSpline : public Spline {
blender::Span<blender::float3> evaluated_positions() const final
{
this->ensure_evaluation_cache();
- return evaluated_spline_cache;
+ return evaluated_positions_cache;
+ }
+
+ blender::Span<blender::float3> evaluated_tangents() const final
+ {
+ this->ensure_evaluation_cache();
+ return evaluated_tangents_cache;
+ }
+
+ blender::Span<blender::float3> evaluated_normals() const final
+ {
+ this->ensure_evaluation_cache();
+ return evaluated_normals_cache;
}
~BezierSpline() = default;
};
+struct NURBSPoint {
+ blender::float3 position;
+ float radius;
+ float weight;
+
+ /* User defined tilt in radians, added on top of the auto-calculated tilt. */
+ float tilt;
+};
+
class SplineNURBS : public Spline {
public:
- blender::Vector<ControlPointNURBS> control_points;
+ blender::Vector<NURBSPoint> control_points;
int32_t flag; /* Cyclic, smooth. */
int resolution_u;
uint8_t order;
@@ -156,6 +170,16 @@ class SplineNURBS : public Spline {
{
return {};
}
+
+ blender::Span<blender::float3> evaluated_tangents() const final
+ {
+ return {};
+ }
+
+ blender::Span<blender::float3> evaluated_normals() const final
+ {
+ return {};
+ }
};
/* 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 e4efff12308..bcebd07ebff 100644
--- a/source/blender/blenkernel/intern/derived_curve.cc
+++ b/source/blender/blenkernel/intern/derived_curve.cc
@@ -29,24 +29,30 @@ using blender::IndexRange;
using blender::MutableSpan;
using blender::Span;
-static BezierHandleType handle_type_from_dna_bezt(const eBezTriple_Handle dna_handle_type)
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name General Curve Functions
+ * \{ */
+
+static BezierPoint::HandleType handle_type_from_dna_bezt(const eBezTriple_Handle dna_handle_type)
{
switch (dna_handle_type) {
case HD_FREE:
- return BezierHandleType::Free;
+ return BezierPoint::Free;
case HD_AUTO:
- return BezierHandleType::Auto;
+ return BezierPoint::Auto;
case HD_VECT:
- return BezierHandleType::Vector;
+ return BezierPoint::Vector;
case HD_ALIGN:
- return BezierHandleType::Align;
+ return BezierPoint::Align;
case HD_AUTO_ANIM:
- return BezierHandleType::Auto;
+ return BezierPoint::Auto;
case HD_ALIGN_DOUBLESIDE:
- return BezierHandleType::Align;
+ return BezierPoint::Align;
}
BLI_assert_unreachable();
- return BezierHandleType::Free;
+ return BezierPoint::Free;
}
DCurve *dcurve_from_dna_curve(const Curve &dna_curve)
@@ -61,7 +67,7 @@ DCurve *dcurve_from_dna_curve(const Curve &dna_curve)
if (nurb->type == CU_BEZIER) {
BezierSpline *spline = new BezierSpline();
for (const BezTriple &bezt : Span(nurb->bezt, nurb->pntsu)) {
- ControlPointBezier point;
+ BezierPoint point;
point.handle_position_a = bezt.vec[0];
point.position = bezt.vec[1];
point.handle_position_b = bezt.vec[2];
@@ -87,12 +93,46 @@ DCurve *dcurve_from_dna_curve(const Curve &dna_curve)
return curve;
}
-static void evaluate_bezier_part_3d(const float3 point_0,
- const float3 point_1,
- const float3 point_2,
- const float3 point_3,
+/* -------------------------------------------------------------------- */
+/** \name Bezier Spline
+ * \{ */
+
+static bool segment_is_vector(const BezierPoint &point_a, const BezierPoint &point_b)
+{
+ return point_a.handle_type_b == BezierPoint::HandleType::Vector &&
+ point_b.handle_type_a == BezierPoint::HandleType::Vector;
+}
+
+int BezierSpline::evaluated_points_size() const
+{
+ BLI_assert(control_points.size() > 0);
+
+ int total_len = 1;
+ for (const int i : IndexRange(1, this->control_points.size() - 1)) {
+ const BezierPoint &point_prev = this->control_points[i - 1];
+ const BezierPoint &point = this->control_points[i];
+ if (segment_is_vector(point_prev, point)) {
+ total_len += 1;
+ }
+ else {
+ total_len += this->resolution_u;
+ }
+ }
+
+ if (!this->is_cyclic) {
+ total_len++;
+ }
+
+ return total_len;
+}
+
+static void evaluate_bezier_part_3d(const float3 &point_0,
+ const float3 &point_1,
+ const float3 &point_2,
+ const float3 &point_3,
MutableSpan<float3> result)
{
+ /* TODO: This can probably be vectorized... no one has done this already? */
float *data = (float *)result.data();
for (const int axis : {0, 1, 2}) {
BKE_curve_forward_diff_bezier(point_0[axis],
@@ -105,61 +145,161 @@ static void evaluate_bezier_part_3d(const float3 point_0,
}
}
-int BezierSpline::evaluated_points_size() const
+static void evaluate_segment_positions(const BezierPoint &point,
+ const BezierPoint &next,
+ const int resolution,
+ int &offset,
+ MutableSpan<float3> positions)
{
- BLI_assert(control_points.size() > 0);
+ if (segment_is_vector(point, next)) {
+ positions[offset] = point.position;
+ offset++;
+ }
+ else {
+ evaluate_bezier_part_3d(point.position,
+ point.handle_position_b,
+ next.handle_position_a,
+ next.position,
+ positions.slice(offset, resolution));
+ offset += resolution;
+ }
+}
- int total_len = 1;
- for (const int i : IndexRange(1, this->control_points.size() - 1)) {
- const ControlPointBezier &point_prev = this->control_points[i - 1];
- const ControlPointBezier &point = this->control_points[i];
- if (point_prev.handle_type_b == BezierHandleType::Vector &&
- point.handle_type_a == BezierHandleType::Vector) {
- total_len += 1;
+static void evaluate_positions(Span<BezierPoint> control_points,
+ const int resolution,
+ const bool is_cyclic,
+ MutableSpan<float3> positions)
+{
+ int offset = 0;
+ for (const int i : IndexRange(1, control_points.size() - 1)) {
+ const BezierPoint &point_prev = control_points[i - 1];
+ const BezierPoint &point = control_points[i];
+ evaluate_segment_positions(point_prev, point, resolution, offset, positions);
+ }
+
+ if (is_cyclic) {
+ const BezierPoint &last_point = control_points.last();
+ const BezierPoint &first_point = control_points.first();
+ evaluate_segment_positions(last_point, first_point, resolution, offset, positions);
+ }
+ else {
+ /* Since evaulating the bezier doesn't add the final point's position,
+ * it must be added manually in the non-cyclic case. */
+ positions[offset] = control_points.last().position;
+ offset++;
+ }
+
+ BLI_assert(offset == positions.size());
+}
+
+static float3 direction_bisect(const float3 &prev, const float3 &middle, const float3 &next)
+{
+ const float3 dir_prev = (middle - prev).normalized();
+ const float3 dir_next = (next - middle).normalized();
+
+ return (dir_prev + dir_next).normalized();
+}
+
+static void calculate_tangents(Span<BezierPoint> control_points,
+ Span<float3> positions,
+ const bool is_cyclic,
+ MutableSpan<float3> tangents)
+{
+ for (const int i : IndexRange(1, positions.size() - 2)) {
+ tangents[i] = direction_bisect(positions[i - 1], posi
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list