[Bf-blender-cvs] [a80edb8865e] geometry-nodes-curve-support: Geometry nodes curves: Mostly working version of a curve trim node
Hans Goudey
noreply at git.blender.org
Sun Apr 18 20:20:28 CEST 2021
Commit: a80edb8865ecf46d00ef18e062e7b0a2c7848e4d
Author: Hans Goudey
Date: Sun Apr 18 13:20:21 2021 -0500
Branches: geometry-nodes-curve-support
https://developer.blender.org/rBa80edb8865ecf46d00ef18e062e7b0a2c7848e4d
Geometry nodes curves: Mostly working version of a curve trim node
This still needs some more fixes, but the basics are there now.
===================================================================
M source/blender/blenkernel/BKE_derived_curve.hh
M source/blender/blenkernel/intern/derived_curve.cc
M source/blender/blenkernel/intern/geometry_component_curve.cc
M source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc
===================================================================
diff --git a/source/blender/blenkernel/BKE_derived_curve.hh b/source/blender/blenkernel/BKE_derived_curve.hh
index 90af9f6a848..646fa08e455 100644
--- a/source/blender/blenkernel/BKE_derived_curve.hh
+++ b/source/blender/blenkernel/BKE_derived_curve.hh
@@ -27,14 +27,23 @@
#include "BLI_vector.hh"
#include "BKE_attribute_math.hh"
-#include "BKE_curve.h"
struct Curve;
+/**
+ * Contains the information necessary to interpolate values from the original control points to
+ * evaluated points.
+ */
struct PointMapping {
+ /**
+ * The index of the control point preceding the evaluated point at this index.
+ * For resolutions higher than 1, many evaluated points can share the same value.
+ */
int control_point_index;
- /* Linear interpolation factor starting at this control point with the index in
- * `control_point_index`, and ending with the next control point. */
+ /**
+ * This evaluated point's portion of the total length between the `control_point_index` value
+ * and the next.
+ */
float factor;
};
@@ -127,23 +136,47 @@ class Spline {
virtual int evaluated_points_size() const = 0;
int evaluated_edges_size() const;
+ float length() const;
+
blender::Span<blender::float3> evaluated_positions() const;
blender::Span<PointMapping> evaluated_mappings() const;
blender::Span<float> evaluated_lengths() const;
blender::Span<blender::float3> evaluated_tangents() const;
blender::Span<blender::float3> evaluated_normals() const;
- /* TODO: Check for null default mixer. Use std::enable_if? */
+ struct LookupResult {
+ /*
+ * The index of the evaluated point before the result location.
+ * In other words, the index of the edge that the result lies on.
+ */
+ int evaluated_index;
+ /**
+ * The portion of the way from the evaluated point at #index to the next point.
+ */
+ float factor;
+ };
+ LookupResult lookup_evaluated_factor(const float factor) const;
+ LookupResult lookup_evaluated_length(const float length) const;
+
+ /**
+ * Interpolate data from the original control points to the corresponding ealuated points.
+ * \param source_data: Should have the same size as the number of control points.
+ * \param result_data: ...
+ */
template<typename T>
void interpolate_data_to_evaluated_points(blender::Span<T> source_data,
- blender::MutableSpan<T> result_data) const
+ blender::MutableSpan<T> result_data,
+ const int offset = 0) const
{
+ /* TODO: Onstead of "offset", it may be better to split a function that returns a single value.
+ * TODO: Check for null default mixer, possibly using std::enable_if? */
const int control_points_len = this->size();
blender::Span<PointMapping> mappings = this->evaluated_mappings();
blender::attribute_math::DefaultMixer<T> mixer(result_data);
- for (const int evaluated_point_index : mappings.index_range()) {
+ for (const int i : result_data.index_range()) {
+ const int evaluated_point_index = offset + i;
const PointMapping &mapping = mappings[evaluated_point_index];
const int index = mapping.control_point_index;
const int next_index = (index + 1) % control_points_len;
@@ -152,8 +185,8 @@ class Spline {
const T &value = source_data[index];
const T &next_value = source_data[next_index];
- mixer.mix_in(evaluated_point_index, value, 1.0f - factor);
- mixer.mix_in(evaluated_point_index, next_value, factor);
+ mixer.mix_in(i, value, 1.0f - factor);
+ mixer.mix_in(i, next_value, factor);
}
mixer.finalize();
@@ -234,11 +267,11 @@ class BezierSpline final : public Spline {
int evaluated_points_size() const final;
- bool point_is_sharp(const int index) const
- {
- return ELEM(handle_types_start_[index], HandleType::Vector, HandleType::Free) ||
- ELEM(handle_types_end_[index], HandleType::Vector, HandleType::Free);
- }
+ bool point_is_sharp(const int index) const;
+ bool handle_start_is_automatic(const int index) const;
+ bool handle_end_is_automatic(const int index) const;
+
+ void move_control_point(const int index, const blender::float3 new_position);
protected:
void correct_final_tangents() const;
@@ -247,7 +280,7 @@ class BezierSpline final : public Spline {
void correct_end_tangents() const final;
void ensure_base_cache() const final;
bool segment_is_vector(const int start_index) const;
- void evaluate_bezier_segment(const int first_index,
+ void evaluate_bezier_segment(const int index,
const int next_index,
int &offset,
blender::MutableSpan<blender::float3> positions,
@@ -363,7 +396,7 @@ class DCurve {
// DCurve *copy();
void translate(const blender::float3 translation);
- void transform(const blender::float4x4 &transform);
+ void transform(const blender::float4x4 &matrix);
};
DCurve *dcurve_from_dna_curve(const Curve &curve);
\ No newline at end of file
diff --git a/source/blender/blenkernel/intern/derived_curve.cc b/source/blender/blenkernel/intern/derived_curve.cc
index d13cc9954c6..6cea835d0d9 100644
--- a/source/blender/blenkernel/intern/derived_curve.cc
+++ b/source/blender/blenkernel/intern/derived_curve.cc
@@ -35,13 +35,6 @@ using blender::Vector;
/** \name Utilities
* \{ */
-/* TODO: This only works for trivial types? */
-template<typename T> static void vector_drop_front(Vector<T> vector, const int count)
-{
- memcpy(vector.begin(), vector.begin() + count, sizeof(T) * count);
- vector.resize(vector.size() - count);
-}
-
/** \} */
/* -------------------------------------------------------------------- */
@@ -207,6 +200,18 @@ DCurve *dcurve_from_dna_curve(const Curve &dna_curve)
/** \name Spline
* \{ */
+/**
+ * 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;
+ tangent_cache_dirty_ = true;
+ normal_cache_dirty_ = true;
+ length_cache_dirty_ = true;
+}
+
int Spline::evaluated_edges_size() const
{
const int points_len = this->evaluated_points_size();
@@ -214,15 +219,30 @@ int Spline::evaluated_edges_size() const
return this->is_cyclic ? points_len : points_len - 1;
}
+float Spline::length() const
+{
+ return this->evaluated_lengths().last();
+}
+
Span<float3> Spline::evaluated_positions() const
{
this->ensure_base_cache();
return evaluated_positions_cache_;
}
+/**
+ * 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
+ * index will never be included as an index.
+ */
Span<PointMapping> Spline::evaluated_mappings() const
{
this->ensure_base_cache();
+#ifdef DEBUG
+ if (evaluated_mapping_cache_.last().control_point_index == this->size() - 1) {
+ BLI_assert(this->is_cyclic);
+ }
+#endif
return evaluated_mapping_cache_;
}
@@ -241,9 +261,10 @@ static void accumulate_lengths(Span<float3> positions,
}
/**
- * Return non-owning access to the cache of accumulated lengths along the curve. Each item is the
+ * Return non-owning access to the cache of accumulated lengths along the spline. 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.
+ * than 0. This calculation is rather trivial, and only depends on the evaluated positions.
+ * However, the results are used often, so it makes sense to cache it.
*/
Span<float> Spline::evaluated_lengths() const
{
@@ -479,16 +500,26 @@ 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()
+Spline::LookupResult Spline::lookup_evaluated_factor(const float factor) const
{
- base_cache_dirty_ = true;
- tangent_cache_dirty_ = true;
- normal_cache_dirty_ = true;
- length_cache_dirty_ = true;
+ return this->lookup_evaluated_length(this->length() * factor);
+}
+
+/* TODO: Support extrapolation somehow. */
+Spline::LookupResult Spline::lookup_evaluated_length(const float length) const
+{
+ BLI_assert(length >= 0.0f && length <= this->length());
+
+ Span<float> lengths = this->evaluated_lengths();
+
+ const float *offset = std::lower_bound(lengths.begin(), lengths.end(), length);
+ const int index = offset - lengths.begin();
+
+ const float segment_length = lengths[index];
+ const float previous_length = (index == 0) ? 0.0f : lengths[index - 1];
+ const float factor = (length - previous_length) / (segment_length - previous_length);
+
+ return LookupResult{index, factor};
}
/** \} */
@@ -603,19 +634,21 @@ void BezierSpline::add_point(const float3 position,
void BezierSpline::drop_front(const int count)
{
+ std::cout << __func__ << ": " << count << "\n";
BLI_assert(this->size() - count > 0);
- vector_drop_front(this->handle_types_start_, count);
- vector_drop_front(this->handle_positions_start_, count);
- vector_drop_front(this->positions_, count);
- vector_drop_front(this->handle_types_end_, count);
- vector_drop_front(this->handle_positions_end_, count);
- vector_drop_front(this->radii_, count);
- vector_drop_front(this->tilts_, count);
+ this->handle_types_start_.remove(0, count);
+ this->handle_positions_start_.remove(0, count);
+ this->positions_.remove(0, count);
+ this->handle_types_end_.remove(0, count);
+ this->handle_positions_end_.remove(0, count);
+ this->radii_.remove(0, count);
+ this->tilts_.remove(0, count);
this->mark_cache_invalid();
}
void BezierSpline::drop_back(const int count)
{
+ std::cout << __func__ << ": " << count << "\n";
const int new_size = this->size() -
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list