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));
Low-level operations for curves.
#define GEO_NODE_INPUT_TANGENT
#define NOD_REGISTER_NODE(REGISTER_FUNC)
static VArray ForContainer(ContainerT container)
static VArray ForSpan(Span< T > values)
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
local_group_size(16, 16) .push_constant(Type b
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, int type, const char *name, short nclass)
unsigned __int64 uint64_t
NodeGeometryExecFunction geometry_node_execute
NodeDeclareFunction declare