32 for (const int i_curve : range) {
33 const IndexRange points = points_by_curve[i_curve];
34 const IndexRange evaluated_points = evaluated_points_by_curve[i_curve];
36 MutableSpan<float3> curve_tangents = results.as_mutable_span().slice(points);
38 switch (types[i_curve]) {
39 case CURVE_TYPE_CATMULL_ROM: {
40 Span<float3> tangents = evaluated_tangents.slice(evaluated_points);
41 const int resolution = resolutions[i_curve];
42 for (const int i : IndexRange(points.size())) {
43 curve_tangents[i] = tangents[resolution * i];
48 curve_tangents.copy_from(evaluated_tangents.slice(evaluated_points));
50 case CURVE_TYPE_BEZIER: {
51 Span<float3> tangents = evaluated_tangents.slice(evaluated_points);
52 curve_tangents.first() = tangents.first();
53 const Span<int> offsets = curves.bezier_evaluated_offsets_for_curve(i_curve);
54 for (const int i : IndexRange(points.size()).drop_front(1)) {
55 curve_tangents[i] = tangents[offsets[i]];
59 case CURVE_TYPE_NURBS: {
60 const Span<float3> curve_positions = positions.slice(points);
61 bke::curves::poly::calculate_tangents(curve_positions, cyclic[i_curve], curve_tangents);
81 if (domain == AttrDomain::Point) {
85 if (domain == AttrDomain::Curve) {
120 return AttrDomain::Point;
126 Field<float3> tangent_field{std::make_shared<TangentFieldInput>()};
127 params.set_output(
"Tangent", std::move(tangent_field));
135 ntype.
ui_name =
"Curve Tangent";
136 ntype.
ui_description =
"Retrieve the direction of curves at each control point";
Low-level operations for curves.
#define GEO_NODE_INPUT_TANGENT
#define NOD_REGISTER_NODE(REGISTER_FUNC)
unsigned long long int uint64_t
static VArray from_span(Span< T > values)
static VArray from_container(ContainerT container)
OffsetIndices< int > points_by_curve() const
IndexRange curves_range() const
Span< float3 > evaluated_tangents() const
VArray< int > resolution() const
Span< float3 > positions() const
OffsetIndices< int > evaluated_points_by_curve() const
GVArray adapt_domain(const GVArray &varray, AttrDomain from, AttrDomain to) const
bool is_single_type(CurveType type) const
VArray< int8_t > curve_types() const
VArray< bool > cyclic() const
void node_register_type(bNodeType &ntype)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
VecBase< float, 3 > float3
void geo_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
std::string ui_description
NodeGeometryExecFunction geometry_node_execute
const char * enum_name_legacy
NodeDeclareFunction declare