diff options
author | Hans Goudey <h.goudey@me.com> | 2022-04-09 20:46:30 +0300 |
---|---|---|
committer | Hans Goudey <h.goudey@me.com> | 2022-04-09 20:46:30 +0300 |
commit | ceed37fc5cbb466a04b4b4f7afba5dcd561fdd6a (patch) | |
tree | 83f515a54846d868d57a10f14854df69cf4c82fd /source/blender/nodes | |
parent | 69a4d113e8dd3f2f267536b2b93af2540f3a0978 (diff) |
Curves: Port tangent and normal calculation to the new data-block
Port the "Normal" and "Curve Tangent" nodes to the new curves data-block
to avoid the conversion to `CurveEval`. This should make them faster by
avoiding all that copying, but otherwise nothing else has changed.
This also includes a fix to move the normal mode as a built-in curve
attribute when converting to and from `CurveEval`. The attribute is
needed because the option is used implicitly in many nodes currently.
Differential Revision: https://developer.blender.org/D14609
Diffstat (limited to 'source/blender/nodes')
-rw-r--r-- | source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc | 99 |
1 files changed, 47 insertions, 52 deletions
diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc b/source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc index 435dd969c03..039d6b69585 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc @@ -2,7 +2,7 @@ #include "BLI_task.hh" -#include "BKE_spline.hh" +#include "BKE_curves.hh" #include "node_geometry_util.hh" @@ -13,65 +13,54 @@ static void node_declare(NodeDeclarationBuilder &b) b.add_output<decl::Vector>(N_("Tangent")).field_source(); } -static void calculate_bezier_tangents(const BezierSpline &spline, MutableSpan<float3> tangents) +static Array<float3> curve_tangent_point_domain(const bke::CurvesGeometry &curves) { - Span<int> offsets = spline.control_point_offsets(); - Span<float3> evaluated_tangents = spline.evaluated_tangents(); - for (const int i : IndexRange(spline.size())) { - tangents[i] = evaluated_tangents[offsets[i]]; - } -} + const VArray<int8_t> types = curves.curve_types(); + const VArray<int> resolutions = curves.resolution(); + const VArray<bool> cyclic = curves.cyclic(); + const Span<float3> positions = curves.positions(); -static void calculate_poly_tangents(const PolySpline &spline, MutableSpan<float3> tangents) -{ - tangents.copy_from(spline.evaluated_tangents()); -} + const Span<float3> evaluated_tangents = curves.evaluated_tangents(); -/** - * Because NURBS control points are not necessarily on the path, the tangent at the control points - * is not well defined, so create a temporary poly spline to find the tangents. This requires extra - * copying currently, but may be more efficient in the future if attributes have some form of CoW. - */ -static void calculate_nurbs_tangents(const NURBSpline &spline, MutableSpan<float3> tangents) -{ - PolySpline poly_spline; - poly_spline.resize(spline.size()); - poly_spline.positions().copy_from(spline.positions()); - tangents.copy_from(poly_spline.evaluated_tangents()); -} + Array<float3> results(curves.points_num()); -static Array<float3> curve_tangent_point_domain(const CurveEval &curve) -{ - Span<SplinePtr> splines = curve.splines(); - Array<int> offsets = curve.control_point_offsets(); - const int total_size = offsets.last(); - Array<float3> tangents(total_size); - - threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) { - for (const int i : range) { - const Spline &spline = *splines[i]; - MutableSpan spline_tangents{tangents.as_mutable_span().slice(offsets[i], spline.size())}; - switch (splines[i]->type()) { - case CURVE_TYPE_BEZIER: { - calculate_bezier_tangents(static_cast<const BezierSpline &>(spline), spline_tangents); + threading::parallel_for(curves.curves_range(), 128, [&](IndexRange range) { + for (const int i_curve : range) { + const IndexRange points = curves.points_for_curve(i_curve); + const IndexRange evaluated_points = curves.evaluated_points_for_curve(i_curve); + + MutableSpan<float3> curve_tangents = results.as_mutable_span().slice(points); + + switch (types[i_curve]) { + case CURVE_TYPE_CATMULL_ROM: { + Span<float3> tangents = evaluated_tangents.slice(evaluated_points); + const int resolution = resolutions[i_curve]; + for (const int i : IndexRange(points.size())) { + curve_tangents[i] = tangents[resolution * i]; + } break; } - case CURVE_TYPE_POLY: { - calculate_poly_tangents(static_cast<const PolySpline &>(spline), spline_tangents); + case CURVE_TYPE_POLY: + curve_tangents.copy_from(evaluated_tangents.slice(evaluated_points)); break; - } - case CURVE_TYPE_NURBS: { - calculate_nurbs_tangents(static_cast<const NURBSpline &>(spline), spline_tangents); + case CURVE_TYPE_BEZIER: { + Span<float3> tangents = evaluated_tangents.slice(evaluated_points); + curve_tangents.first() = tangents.first(); + const Span<int> offsets = curves.bezier_evaluated_offsets_for_curve(i_curve); + for (const int i : IndexRange(points.size()).drop_front(1)) { + curve_tangents[i] = tangents[offsets[i - 1]]; + } break; } - case CURVE_TYPE_CATMULL_ROM: { - BLI_assert_unreachable(); + case CURVE_TYPE_NURBS: { + const Span<float3> curve_positions = positions.slice(points); + bke::curves::poly::calculate_tangents(curve_positions, cyclic[i_curve], curve_tangents); break; } } } }); - return tangents; + return results; } static VArray<float3> construct_curve_tangent_gvarray(const CurveComponent &component, @@ -80,19 +69,25 @@ static VArray<float3> construct_curve_tangent_gvarray(const CurveComponent &comp if (!component.has_curves()) { return {}; } - const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*component.get_for_read()); + + const Curves &curves_id = *component.get_for_read(); + const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry); + + const VArray<int8_t> types = curves.curve_types(); + if (curves.is_single_type(CURVE_TYPE_POLY)) { + return component.attribute_try_adapt_domain<float3>( + VArray<float3>::ForSpan(curves.evaluated_tangents()), ATTR_DOMAIN_POINT, domain); + } + + Array<float3> tangents = curve_tangent_point_domain(curves); if (domain == ATTR_DOMAIN_POINT) { - Array<float3> tangents = curve_tangent_point_domain(*curve); return VArray<float3>::ForContainer(std::move(tangents)); } if (domain == ATTR_DOMAIN_CURVE) { - Array<float3> point_tangents = curve_tangent_point_domain(*curve); return component.attribute_try_adapt_domain<float3>( - VArray<float3>::ForContainer(std::move(point_tangents)), - ATTR_DOMAIN_POINT, - ATTR_DOMAIN_CURVE); + VArray<float3>::ForContainer(std::move(tangents)), ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE); } return nullptr; |