[Bf-blender-cvs] [4cc8f098430] temp-geometry-nodes-curve-deform-node: Progress, theoretically working for attribute mode, needs debugging
Hans Goudey
noreply at git.blender.org
Fri May 28 18:40:51 CEST 2021
Commit: 4cc8f098430425d2a4a28087e335a5dbfdd0fa7f
Author: Hans Goudey
Date: Thu May 27 23:40:30 2021 -0400
Branches: temp-geometry-nodes-curve-deform-node
https://developer.blender.org/rB4cc8f098430425d2a4a28087e335a5dbfdd0fa7f
Progress, theoretically working for attribute mode, needs debugging
===================================================================
M source/blender/blenkernel/BKE_spline.hh
M source/blender/blenkernel/intern/spline_base.cc
M source/blender/nodes/geometry/nodes/node_geo_curve_deform.cc
M source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc
===================================================================
diff --git a/source/blender/blenkernel/BKE_spline.hh b/source/blender/blenkernel/BKE_spline.hh
index ef76c699cbb..17908973ea9 100644
--- a/source/blender/blenkernel/BKE_spline.hh
+++ b/source/blender/blenkernel/BKE_spline.hh
@@ -171,6 +171,19 @@ class Spline {
LookupResult lookup_evaluated_length(const float length) const;
blender::Array<float> sample_uniform_index_factors(const int samples_size) const;
+
+ struct Parameter {
+ float factor;
+ int data_index;
+
+ friend bool operator<(const Parameter &a, const Parameter &b)
+ {
+ return a.factor < b.factor;
+ }
+ };
+ void sample_parameters_to_index_factors(
+ blender::MutableSpan<Parameter> sample_index_factors) const;
+
LookupResult lookup_data_from_index_factor(const float index_factor) const;
/**
@@ -180,6 +193,11 @@ class Spline {
*/
virtual blender::fn::GVArrayPtr interpolate_to_evaluated_points(
const blender::fn::GVArray &source_data) const = 0;
+ template<typename T>
+ blender::fn::GVArrayPtr interpolate_to_evaluated_points(blender::Span<T> source_data) const
+ {
+ return this->interpolate_to_evaluated_points(blender::fn::GVArray_For_GSpan(source_data));
+ }
protected:
virtual void correct_end_tangents() const = 0;
diff --git a/source/blender/blenkernel/intern/spline_base.cc b/source/blender/blenkernel/intern/spline_base.cc
index 11620a30948..316ca04b438 100644
--- a/source/blender/blenkernel/intern/spline_base.cc
+++ b/source/blender/blenkernel/intern/spline_base.cc
@@ -313,6 +313,48 @@ Array<float> Spline::sample_uniform_index_factors(const int samples_size) const
return samples;
}
+static void verify_parameters_assert(Span<Spline::Parameter> parameters)
+{
+ float last = 0.0f;
+ for (const Spline::Parameter ¶meter : parameters) {
+ BLI_assert(parameter.factor >= last);
+ last = parameter.factor;
+ }
+ BLI_assert(last <= 1.0f);
+}
+
+void Spline::sample_parameters_to_index_factors(MutableSpan<Parameter> sample_index_factors) const
+{
+ const Span<float> lengths = this->evaluated_lengths();
+
+ verify_parameters_assert(sample_index_factors);
+
+ const int samples_size = sample_index_factors.size();
+ const float total_length = this->length();
+
+ /* Store the length at the previous evaluated point in a variable so it can
+ * start out at zero (the lengths array doesn't contain 0 for the first point). */
+ float prev_length = 0.0f;
+ int i_sample = 0;
+ for (const int i_evaluated : IndexRange(this->evaluated_edges_size())) {
+ const float length = lengths[i_evaluated];
+ const float sample_length = sample_index_factors[i_sample].factor * total_length;
+
+ /* Add every sample that fits in this evaluated edge. */
+ while ((sample_length * i_sample) < length && i_sample < samples_size) {
+ const float factor = (sample_length * i_sample - prev_length) / (length - prev_length);
+ sample_index_factors[i_sample].factor = i_evaluated + factor;
+ i_sample++;
+ }
+
+ if (i_sample >= samples_size) {
+ break;
+ }
+
+ prev_length = length;
+ }
+}
+
Spline::LookupResult Spline::lookup_data_from_index_factor(const float index_factor) const
{
const int points_len = this->evaluated_points_size();
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_deform.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_deform.cc
index 881c6876c6f..2b64d08ca04 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_deform.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_deform.cc
@@ -15,6 +15,7 @@
*/
#include "BLI_array.hh"
+#include "BLI_float4x4.hh"
#include "BLI_task.hh"
#include "BLI_timeit.hh"
@@ -27,14 +28,15 @@
#include "node_geometry_util.hh"
+using blender::float4x4;
using blender::bke::GeometryInstanceGroup;
static bNodeSocketTemplate geo_node_curve_deform_in[] = {
{SOCK_GEOMETRY, N_("Geometry")},
{SOCK_GEOMETRY, N_("Curve")},
- {SOCK_STRING, N_("Parameter")},
- {SOCK_FLOAT, N_("Parameter"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX},
- {SOCK_BOOLEAN, N_("Use Radius")},
+ {SOCK_STRING, N_("Factor")},
+ {SOCK_FLOAT, N_("Factor"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX},
+ // {SOCK_BOOLEAN, N_("Use Radius")},
{-1, ""},
};
@@ -57,7 +59,7 @@ static void geo_node_curve_deform_layout(uiLayout *layout, bContext *UNUSED(C),
else {
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
- uiItemR(layout, ptr, "attribute_input_type", 0, nullptr, ICON_NONE);
+ uiItemR(layout, ptr, "attribute_input_type", 0, IFACE_("Factor"), ICON_NONE);
}
}
@@ -84,45 +86,71 @@ static void geo_node_curve_deform_update(bNodeTree *UNUSED(ntree), bNode *node)
nodeSetSocketAvailability(attribute_socket, mode == GEO_NODE_CURVE_DEFORM_ATTRIBUTE);
update_attribute_input_socket_availabilities(
*node,
- "Parameter",
+ "Factor",
(GeometryNodeAttributeInputMode)node_storage.attribute_input_type,
mode == GEO_NODE_CURVE_DEFORM_ATTRIBUTE);
}
-namespace {
-struct Parameter {
- float parameter;
- int index;
-};
-} // namespace
-
-static void spline_deform(VArray<float3> &positions, Span<float> parameters, const Spline &spline)
+static void spline_deform(const Spline &spline,
+ MutableSpan<Spline::Parameter> parameters,
+ VMutableArray<float3> &positions)
{
-}
+ spline.sample_parameters_to_index_factors(parameters);
+ MutableSpan<Spline::Parameter> index_factors = std::move(parameters);
-struct CurveDeformInput {
- GeometryNodeAttributeInputMode mode;
- std::optional<GeometryNodeCurveDeformPositionAxis> position_axis;
- std::optional<std::string> attribute_name;
-};
+ Span<float3> spline_positions = spline.evaluated_positions();
+ Span<float3> spline_tangents = spline.evaluated_tangents();
+ Span<float3> spline_normals = spline.evaluated_normals();
+ GVArray_Typed<float> radii{spline.interpolate_to_evaluated_points(spline.radii())};
+
+ parallel_for(positions.index_range(), 1024, [&](IndexRange range) {
+ for (const int i : range) {
+ const Spline::LookupResult interp = spline.lookup_data_from_index_factor(
+ index_factors[i].factor);
+ const int index = interp.evaluated_index;
+ const int next_index = interp.next_evaluated_index;
+
+ float4x4 matrix = float4x4::from_normalized_axis_data(
+ spline_positions[index], spline_normals[index], spline_tangents[index]);
+ matrix.apply_scale(radii[index]);
+
+ float4x4 next_matrix = float4x4::from_normalized_axis_data(
+ spline_positions[next_index], spline_normals[next_index], spline_tangents[next_index]);
+ matrix.apply_scale(radii[next_index]);
-static void execute_on_component(GeometryComponent &component,
- const CurveDeformInput &input,
- const CurveEval &curve)
+ const float4x4 deform_matrix = float4x4::interpolate(matrix, next_matrix, interp.factor);
+
+ positions[parameters[i].data_index] = deform_matrix * positions[parameters[i].data_index];
+ }
+ });
+}
+
+static void execute_on_component(const GeoNodeExecParams ¶ms,
+ const CurveEval &curve,
+ GeometryComponent &component)
{
- GVArray_Typed<float3> positions = component.attribute_get_for_read<float3>(
+ const NodeGeometryCurveDeform &node_storage = *(NodeGeometryCurveDeform *)params.node().storage;
+ const GeometryNodeCurveDeformMode mode = (GeometryNodeCurveDeformMode)node_storage.input_mode;
+
+ if (curve.splines().size() == 0) {
+ params.error_message_add(NodeWarningType::Error, TIP_("Curve does not contain a spline"));
+ return;
+ }
+
+ const int size = component.attribute_domain_size(ATTR_DOMAIN_POINT);
+ OutputAttribute_Typed<float3> positions = component.attribute_try_get_for_output<float3>(
"position", ATTR_DOMAIN_POINT, {0, 0, 0});
- Array<Parameter> parameters(positions.size());
+ Array<Spline::Parameter> parameters(size);
- if (input.mode == GEO_NODE_CURVE_DEFORM_POSITION) {
- switch (*input.position_axis) {
+ if (mode == GEO_NODE_CURVE_DEFORM_POSITION) {
+ switch ((GeometryNodeCurveDeformPositionAxis)node_storage.position_axis) {
case GEO_NODE_CURVE_DEFORM_POSX:
- parallel_for(positions.index_range(), 4096, [&](IndexRange range) {
- for (const int i : range) {
- parameters[i] = { positions }
- }
- });
+ // parallel_for(positions.index_range(), 4096, [&](IndexRange range) {
+ // for (const int i : range) {
+ // parameters[i] = { positions }
+ // }
+ // });
break;
case GEO_NODE_CURVE_DEFORM_POSY:
break;
@@ -136,6 +164,26 @@ static void execute_on_component(GeometryComponent &component,
break;
}
}
+ else {
+ BLI_assert(mode == GEO_NODE_CURVE_DEFORM_ATTRIBUTE);
+ GVArrayPtr attribute = params.get_input_attribute(
+ "Factor", component, ATTR_DOMAIN_POINT, CD_PROP_FLOAT, nullptr);
+ if (!attribute) {
+ return;
+ }
+
+ /* Sanitize attribute input. */
+ GVArray_Typed<float> parameter_attribute{*attribute};
+ for (const int i : IndexRange(size)) {
+ parameters[i] = {std::clamp(parameter_attribute[i], 0.0f, 1.0f), i};
+ }
+ }
+
+ std::sort(parameters.begin(), parameters.end());
+
+ spline_deform(*curve.splines().first(), parameters, *positions);
+
+ positions.save();
}
static void geo_node_curve_deform_exec(GeoNodeExecParams params)
@@ -144,27 +192,30 @@ static void geo_node_curve_deform_exec(GeoNodeExecParams params)
GeometrySet curve_geometry_set = params.extract_input<GeometrySet>("Curve");
deform_geometry_set = bke::geometry_set_realize_instances(deform_geometry_set);
+
+ /* TODO: Theoretically this could be easily avoided. */
curve_geometry_set = bke::geometry_set_realize_instances(curve_geometry_set);
const CurveEval *curve = curve_geometry_set.get_curve_for_read();
if (curve == nullptr) {
- params.error_message_add(NodeWarningType::Error, TIP_("Curve input must contain curve data"));
+ params.set_output("Geometry
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list