[Bf-blender-cvs] [bb04d1c2c83] geometry-nodes-curve-support: Geometry Nodes Curves: Add structure for curve trim node
Hans Goudey
noreply at git.blender.org
Mon Apr 12 06:28:50 CEST 2021
Commit: bb04d1c2c83b3c31a8770108a9984409e2f94359
Author: Hans Goudey
Date: Sun Apr 11 23:28:40 2021 -0500
Branches: geometry-nodes-curve-support
https://developer.blender.org/rBbb04d1c2c83b3c31a8770108a9984409e2f94359
Geometry Nodes Curves: Add structure for curve trim node
The node doesn't do anything yet because the last level needs to
be implemented, but the majority of the necessary changes are done.
===================================================================
M release/scripts/startup/nodeitems_builtins.py
M source/blender/blenkernel/BKE_derived_curve.hh
M source/blender/blenkernel/BKE_node.h
M source/blender/blenkernel/intern/derived_curve.cc
M source/blender/blenkernel/intern/geometry_component_curve.cc
M source/blender/blenkernel/intern/node.cc
M source/blender/makesdna/DNA_node_types.h
M source/blender/makesrna/intern/rna_nodetree.c
M source/blender/nodes/CMakeLists.txt
M source/blender/nodes/NOD_geometry.h
M source/blender/nodes/NOD_static_types.h
M source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
M source/blender/nodes/geometry/nodes/node_geo_curve_transform_test.cc
A source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc
===================================================================
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index f76d9547ec1..4cb4929b98d 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -507,6 +507,7 @@ geometry_node_categories = [
GeometryNodeCategory("GEO_CURVE", "Curve", items=[
NodeItem("GeometryNodeCurveToMesh"),
NodeItem("GeometryNodeTransformTest"),
+ NodeItem("GeometryNodeCurveTrim"),
]),
GeometryNodeCategory("GEO_GEOMETRY", "Geometry", items=[
NodeItem("GeometryNodeBoundBox"),
diff --git a/source/blender/blenkernel/BKE_derived_curve.hh b/source/blender/blenkernel/BKE_derived_curve.hh
index 8512cfc022f..57054d8333c 100644
--- a/source/blender/blenkernel/BKE_derived_curve.hh
+++ b/source/blender/blenkernel/BKE_derived_curve.hh
@@ -36,6 +36,7 @@ struct PointMapping {
float factor;
};
+/* TODO: Think about storing each data type from each control point separately. */
struct BezierPoint {
enum HandleType {
Free,
@@ -65,7 +66,13 @@ struct BezierPoint {
}
};
-/* TODO: Think about storing each data type from each control point separately. */
+/**
+ * A spline is an abstraction of a curve section, its evaluation methods, and data.
+ * The spline data itself is just control points and a set of attributes.
+ *
+ * Common evaluated data is stored in caches on the spline itself. This way operations on splines
+ * don't need to worry about taking ownership of evaluated data when they don't need to.
+ */
class Spline {
public:
enum Type {
@@ -110,6 +117,7 @@ class Spline {
virtual void mark_cache_invalid();
virtual int evaluated_points_size() const = 0;
+ int evaluated_edges_size() const;
blender::Span<blender::float3> evaluated_positions() const;
blender::Span<PointMapping> evaluated_mappings() const;
@@ -117,10 +125,11 @@ class Spline {
blender::Span<blender::float3> evaluated_tangents() const;
blender::Span<blender::float3> evaluated_normals() const;
- /* TODO: I'm not sure this is the best abstraction here. Indeed, all of the `PointMapping`
- * stuff might be a bit suspect. */
+ /* TODO: I'm not sure this is the best abstraction here, maybe we want another cache. */
float get_evaluated_point_radius(const int index) const;
+ void trim_lengths(const float start_length, const float end_length);
+
protected:
virtual void correct_end_tangents() const = 0;
virtual void ensure_base_cache() const = 0;
@@ -188,12 +197,6 @@ class NURBSPline : public Spline {
struct DCurve {
blender::Vector<Spline *> splines;
- // enum TangentMethod {
- // ZUp,
- // Minimum,
- // Tangent,
- // };
-
// bool is_2d;
// DCurve *copy();
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 6c6f4c539e2..3cbf5147c88 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -1401,6 +1401,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
#define GEO_NODE_BOUNDING_BOX 1042
#define GEO_NODE_CURVE_TO_MESH 1043
#define GEO_NODE_CURVE_TRANSFORM_TEST 1044
+#define GEO_NODE_CURVE_TRIM 1045
/** \} */
diff --git a/source/blender/blenkernel/intern/derived_curve.cc b/source/blender/blenkernel/intern/derived_curve.cc
index 9364d68c929..bfc12b8c9cd 100644
--- a/source/blender/blenkernel/intern/derived_curve.cc
+++ b/source/blender/blenkernel/intern/derived_curve.cc
@@ -76,32 +76,42 @@ DCurve *dcurve_from_dna_curve(const Curve &dna_curve)
curve->splines.reserve(BLI_listbase_count(nurbs));
LISTBASE_FOREACH (const Nurb *, nurb, nurbs) {
- if (nurb->type == CU_BEZIER) {
- BezierSpline *spline = new BezierSpline();
- spline->set_resolution(nurb->resolu);
- spline->type = Spline::Type::Bezier;
- spline->is_cyclic = nurb->flagu & CU_NURB_CYCLIC;
-
- for (const BezTriple &bezt : Span(nurb->bezt, nurb->pntsu)) {
- BezierPoint point;
- point.handle_position_a = bezt.vec[0];
- point.position = bezt.vec[1];
- point.handle_position_b = bezt.vec[2];
- point.radius = bezt.radius;
- point.tilt = bezt.tilt;
- point.handle_type_a = handle_type_from_dna_bezt((eBezTriple_Handle)bezt.h1);
- point.handle_type_b = handle_type_from_dna_bezt((eBezTriple_Handle)bezt.h2);
- spline->control_points.append(std::move(point));
+ switch (nurb->type) {
+ case CU_BEZIER: {
+ BezierSpline *spline = new BezierSpline();
+ spline->set_resolution(nurb->resolu);
+ spline->type = Spline::Type::Bezier;
+ spline->is_cyclic = nurb->flagu & CU_NURB_CYCLIC;
+
+ for (const BezTriple &bezt : Span(nurb->bezt, nurb->pntsu)) {
+ BezierPoint point;
+ point.handle_position_a = bezt.vec[0];
+ point.position = bezt.vec[1];
+ point.handle_position_b = bezt.vec[2];
+ point.radius = bezt.radius;
+ point.tilt = bezt.tilt;
+ point.handle_type_a = handle_type_from_dna_bezt((eBezTriple_Handle)bezt.h1);
+ point.handle_type_b = handle_type_from_dna_bezt((eBezTriple_Handle)bezt.h2);
+ spline->control_points.append(std::move(point));
+ }
+
+ curve->splines.append(spline);
+ break;
+ }
+ case CU_NURBS: {
+ break;
+ }
+ case CU_POLY: {
+ break;
+ }
+ default: {
+ BLI_assert_unreachable();
+ break;
}
-
- curve->splines.append(spline);
- }
- else if (nurb->type == CU_NURBS) {
- }
- else if (nurb->type == CU_POLY) {
}
}
+ /* TODO: Decide whether to store this in the spline or the curve. */
const Spline::NormalCalculationMode normal_mode = normal_mode_from_dna_curve(
dna_curve.twist_mode);
for (Spline *spline : curve->splines) {
@@ -117,6 +127,13 @@ DCurve *dcurve_from_dna_curve(const Curve &dna_curve)
/** \name Spline
* \{ */
+int Spline::evaluated_edges_size() const
+{
+ const int points_len = this->evaluated_points_size();
+
+ return this->is_cyclic ? points_len : points_len - 1;
+}
+
Span<float3> Spline::evaluated_positions() const
{
this->ensure_base_cache();
@@ -129,16 +146,25 @@ Span<PointMapping> Spline::evaluated_mappings() const
return evaluated_mapping_cache_;
}
-static void accumulate_lengths(Span<float3> positions, MutableSpan<float> r_lengths)
+static void accumulate_lengths(Span<float3> positions,
+ const bool is_cyclic,
+ MutableSpan<float> lengths)
{
float length = 0.0f;
- r_lengths[0] = length;
- for (const int i : IndexRange(1, positions.size() - 1)) {
- r_lengths[i] = length;
- length += float3::distance(positions[i - 1], positions[i]);
+ for (const int i : IndexRange(positions.size() - 1)) {
+ length += float3::distance(positions[i], positions[i + 1]);
+ lengths[i] = length;
+ }
+ if (is_cyclic) {
+ lengths.last() = length + float3::distance(positions.last(), positions.first());
}
}
+/**
+ * Return non-owning access to the cache of accumulated lengths along the curve. Each item is the
+ * length of the subsequent segment, i.e. the first value is the length of the first segment rather
+ * than 0. This calculation only depends on the spline's evaluated positions.
+ */
Span<float> Spline::evaluated_lengths() const
{
if (!this->length_cache_dirty_) {
@@ -150,11 +176,11 @@ Span<float> Spline::evaluated_lengths() const
return evaluated_lengths_cache_;
}
- const int total = this->evaluated_points_size();
+ const int total = this->evaluated_edges_size();
this->evaluated_lengths_cache_.resize(total);
Span<float3> positions = this->evaluated_positions();
- accumulate_lengths(positions, this->evaluated_lengths_cache_);
+ accumulate_lengths(positions, this->is_cyclic, this->evaluated_lengths_cache_);
this->length_cache_dirty_ = false;
return evaluated_lengths_cache_;
@@ -195,6 +221,9 @@ static void calculate_tangents(Span<float3> positions,
}
}
+/**
+ * Return non-owning access to the direction of the curve at each evaluated point.
+ */
Span<float3> Spline::evaluated_tangents() const
{
if (!this->tangent_cache_dirty_) {
@@ -374,6 +403,10 @@ static void calculate_normals_z_up(Span<float3> tangents, MutableSpan<float3> no
}
}
+/**
+ * Return non-owning access to the direction vectors perpendicular to the tangents at every
+ * evaluated point. The method used to generate the normal vectors depends on Spline.normal_mode.
+ */
Span<float3> Spline::evaluated_normals() const
{
if (!this->normal_cache_dirty_) {
@@ -405,6 +438,10 @@ Span<float3> Spline::evaluated_normals() const
return evaluated_normals_cache_;
}
+/**
+ * Mark all caches for recomputation. This must be called after any operation that would
+ * change the generated positions, tangents, normals, mapping, etc. of the evaluated points.
+ */
void Spline::mark_cache_invalid()
{
base_cache_dirty_ = true;
@@ -429,6 +466,25 @@ float Spline::get_evaluated_point_radius(const int evaluated_index) const
return interpf(next_radius, radius, factor);
}
+void Spline::trim_lengths(const float start_length, const float end_length)
+{
+ Span<float> lengths = this->evaluated_lengths();
+
+ const float *lower = std::lower_bound(lengths.begin(), lengths.end(), start_length);
+ const float *upper = std::lower_bound(lengths.begin(), lengths.end(), end_length);
+
+ const int i_lower = lower - lengths.begin();
+ const int i_upper = upper - lengths.begin();
+
+ Span<PointMapping> mappings = this->evaluated_mappings();
+
+ const int i_control_lower = mappings[i_lower].control_point_index;
+ const int i_control_upper = mappings[i_upper].control_point_index;
+
+ // this->drop_front_control_points(i_control_upper);
+ // this->drop_back_control_points(this->size() - i_control_upper);
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -503,12 +559,14 @@ int BezierSpline::evaluated_points_size() const
return total_len;
}
+/**
+ * If the spline is not cyclic, the direction for the first and last points is just the
+ * direction formed by the corresponding handl
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list