26 static auto max_one_fn = mf::build::SI1_SO<int, int>(
28 [](
int value) {
return std::max(1, value); },
29 mf::build::exec_presets::AllSpanOrSingle());
35 static auto get_count_fn = mf::build::SI2_SO<float, float, int>(
36 "Length Input to Count",
37 [](
const float curve_length,
const float sample_length) {
40 if (
UNLIKELY(sample_length == 0.0f)) {
43 const int count =
int(curve_length / sample_length) + 1;
44 return std::max(1,
count);
46 mf::build::exec_presets::AllSpanOrSingle());
50 {
fn::Field<float>(std::make_shared<bke::CurveLengthFieldInput>()), length_field});
60 const std::array<int, CURVE_TYPES_NUM> &type_counts)
65 if (
ELEM(attribute_id,
"handle_type_left",
"handle_type_right",
"handle_left",
"handle_right")) {
68 if (
ELEM(attribute_id,
"nurbs_weight")) {
86 return !no_interpolation.
contains(attribute_id);
111 dst_attributes.
append(std::move(dst_attribute));
152 ids.add_new(iter.name);
155 ids_no_interpolation.add_new(iter.name);
164 ids, src_curves, dst_curves, result.src, result.dst, result.dst_attributes);
171 result.src_no_interpolation,
172 result.dst_no_interpolation,
173 result.dst_attributes);
181 result.dst_attributes.append(std::move(dst_attribute));
188 result.dst_attributes.append(std::move(dst_attribute));
205 for (
const int i : attributes.src.index_range()) {
212 for (
const int i : attributes.src_no_interpolation.index_range()) {
216 attributes.src_no_interpolation[i],
217 attributes.dst_no_interpolation[i]);
220 if (!attributes.dst_tangents.is_empty()) {
222 dst_points_by_curve, unselected_curves,
float3(0), attributes.dst_tangents);
224 if (!attributes.dst_normals.is_empty()) {
226 dst_points_by_curve, unselected_curves,
float3(0), attributes.dst_normals);
232 for (
const int i : data.index_range()) {
241 for (
const int i_curve : curve_selection) {
259 const int64_t size_in_bytes =
sizeof(
T) * size;
263 this->heap_allocated.
resize(size_in_bytes);
310 for (
const int i_curve : selection_segment) {
311 const bool cyclic = curves_cyclic[i_curve];
312 const IndexRange dst_points = dst_points_by_curve[i_curve];
314 if (lengths.is_empty()) {
321 !curves_cyclic[i_curve],
329 for (
const int i_attribute : attributes.dst.index_range()) {
330 const CPPType &type = attributes.src[i_attribute].type();
332 using T =
decltype(dummy);
333 Span<T> src = attributes.src[i_attribute].typed<T>();
336 for (
const int i_curve : selection_segment) {
337 const IndexRange src_points = src_points_by_curve[i_curve];
338 const IndexRange dst_points = dst_points_by_curve[i_curve];
342 sample_indices.
as_span().slice(dst_points),
343 sample_factors.
as_span().slice(dst_points),
344 dst.slice(dst_points));
348 evaluated_points_by_curve[i_curve].
size());
352 sample_indices.
as_span().slice(dst_points),
353 sample_factors.
as_span().slice(dst_points),
354 dst.slice(dst_points));
361 for (
const int i_curve : selection_segment) {
362 const IndexRange src_points = evaluated_points_by_curve[i_curve];
363 const IndexRange dst_points = dst_points_by_curve[i_curve];
365 sample_indices.
as_span().slice(dst_points),
366 sample_factors.
as_span().slice(dst_points),
367 dst.slice(dst_points));
372 interpolate_evaluated_data(evaluated_positions, dst_positions);
374 if (!attributes.dst_tangents.is_empty()) {
375 interpolate_evaluated_data(attributes.src_evaluated_tangents, attributes.dst_tangents);
378 if (!attributes.dst_normals.is_empty()) {
379 interpolate_evaluated_data(attributes.src_evaluated_normals, attributes.dst_normals);
384 for (
GMutableSpan dst : attributes.dst_no_interpolation) {
385 for (
const int i_curve : selection_segment) {
386 const IndexRange dst_points = dst_points_by_curve[i_curve];
387 dst.type().value_initialize_n(dst.slice(dst_points).data(), dst_points.
size());
416 evaluator.set_selection(selection_field);
417 evaluator.add_with_destination(count_field, dst_offsets.
drop_back(1));
418 evaluator.evaluate();
419 const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
458 [&](
const int count) { return count > 0; }));
495 selection.foreach_index(
GrainSize(1024), [&](
const int curve_i) {
497 curves_cyclic[curve_i]);
498 dst_offsets[curve_i] =
int(curve_length / sample_lengths[curve_i]) + 1;
559 for (
const int i_attribute : attributes.dst.index_range()) {
560 for (
const int i_curve : selection_segment) {
561 const IndexRange src_points = src_points_by_curve[i_curve];
562 const IndexRange dst_points = dst_points_by_curve[i_curve];
564 attributes.src[i_attribute].slice(src_points),
565 attributes.dst[i_attribute].slice(dst_points));
570 for (
const int i_curve : selection_segment) {
571 const IndexRange src_points = src_evaluated_points_by_curve[i_curve];
572 const IndexRange dst_points = dst_points_by_curve[i_curve];
573 dst.
slice(dst_points).copy_from(src.
slice(src_points));
578 copy_evaluated_data(evaluated_positions, dst_positions);
580 if (!attributes.dst_tangents.is_empty()) {
581 copy_evaluated_data(attributes.src_evaluated_tangents, attributes.dst_tangents);
584 if (!attributes.dst_normals.is_empty()) {
585 copy_evaluated_data(attributes.src_evaluated_normals, attributes.dst_normals);
590 for (
GMutableSpan dst : attributes.dst_no_interpolation) {
591 for (
const int i_curve : selection_segment) {
592 const IndexRange dst_points = dst_points_by_curve[i_curve];
593 dst.type().value_initialize_n(dst.slice(dst_points).data(), dst_points.
size());
616 evaluator.set_selection(selection_field);
617 evaluator.evaluate();
619 src_curves, evaluator.get_evaluated_selection_as_mask(), output_ids);
Low-level operations for curves.
Low-level operations for curves.
Span< T > as_span() const
MutableSpan< T > as_mutable_span()
MutableSpan< T > typed() const
const CPPType & type() const
static constexpr size_t min_alignment
constexpr int64_t size() const
constexpr bool is_empty() const
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
constexpr MutableSpan< NewT > cast() const
constexpr MutableSpan drop_back(const int64_t n) const
constexpr T * end() const
constexpr T * begin() const
constexpr T & last(const int64_t n=0) const
bool contains(const Key &key) const
constexpr Span slice(int64_t start, int64_t size) const
constexpr IndexRange index_range() const
void remove_contained(const Key &key)
void append(const T &value)
void resize(const int64_t new_size)
MutableSpan< T > as_mutable_span()
void foreach_attribute(const FunctionRef< void(const AttributeIter &)> fn) const
GAttributeReader lookup(const StringRef attribute_id) const
eCustomDataType data_type
MutableSpan< float3 > positions_for_write()
OffsetIndices< int > points_by_curve() const
void ensure_can_interpolate_to_evaluated() const
IndexRange curves_range() const
const std::array< int, CURVE_TYPES_NUM > & curve_type_counts() const
MutableAttributeAccessor attributes_for_write()
Span< float > evaluated_lengths_for_curve(int curve_index, bool cyclic) const
Span< float3 > evaluated_tangents() const
void interpolate_to_evaluated(int curve_index, GSpan src, GMutableSpan dst) const
Span< float3 > evaluated_normals() const
Span< float3 > positions() const
OffsetIndices< int > evaluated_points_by_curve() const
void resize(int points_num, int curves_num)
void fill_curve_types(CurveType type)
AttributeAccessor attributes() const
float evaluated_length_total_for_curve(int curve_index, bool cyclic) const
MutableSpan< int > offsets_for_write()
void ensure_evaluated_lengths() const
Span< float3 > evaluated_positions() const
VArray< int8_t > curve_types() const
VArray< bool > cyclic() const
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type)
static std::shared_ptr< FieldOperation > Create(std::shared_ptr< const mf::MultiFunction > function, Vector< GField > inputs={})
IndexMask complement(const IndexMask &universe, IndexMaskMemory &memory) const
OffsetIndices slice(const IndexRange range) const
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
void copy(const GVArray &src, GMutableSpan dst, int64_t grain_size=4096)
void copy_group_to_group(OffsetIndices< int > src_offsets, OffsetIndices< int > dst_offsets, const IndexMask &selection, GSpan src, GMutableSpan dst)
void convert_to_static_type(const CPPType &cpp_type, const Func &func)
bke::CurvesGeometry copy_only_curve_domain(const bke::CurvesGeometry &src_curves)
void fill_points(OffsetIndices< int > points_by_curve, const IndexMask &curve_selection, GPointer value, GMutableSpan dst)
bool attribute_name_is_anonymous(const StringRef name)
eCustomDataType cpp_type_to_custom_data_type(const CPPType &type)
static fn::Field< int > get_count_input_max_one(const fn::Field< int > &count_field)
static AttributesForInterpolation retrieve_attribute_spans(const Span< StringRef > ids, const CurvesGeometry &src_from_curves, const CurvesGeometry &src_to_curves, const bke::AttrDomain domain, CurvesGeometry &dst_curves)
static void normalize_span(MutableSpan< float3 > data)
static void copy_or_defaults_for_unselected_curves(const CurvesGeometry &src_curves, const IndexMask &unselected_curves, const AttributesForResample &attributes, CurvesGeometry &dst_curves)
CurvesGeometry resample_to_count(const CurvesGeometry &src_curves, const IndexMask &selection, const VArray< int > &counts, const ResampleCurvesOutputAttributeIDs &output_ids={})
static bool interpolate_attribute_to_poly_curve(const StringRef attribute_id)
CurvesGeometry resample_to_evaluated(const CurvesGeometry &src_curves, const IndexMask &selection, const ResampleCurvesOutputAttributeIDs &output_ids={})
static void resample_to_uniform(const CurvesGeometry &src_curves, const IndexMask &selection, const ResampleCurvesOutputAttributeIDs &output_ids, CurvesGeometry &dst_curves)
static bool interpolate_attribute_to_curves(const StringRef attribute_id, const std::array< int, CURVE_TYPES_NUM > &type_counts)
static fn::Field< int > get_count_input_from_length(const fn::Field< float > &length_field)
static AttributesForInterpolation gather_point_attributes_to_interpolate(const CurvesGeometry &from_curves, const CurvesGeometry &to_curves, CurvesGeometry &dst_curves)
static void normalize_curve_point_data(const IndexMaskSegment curve_selection, const OffsetIndices< int > points_by_curve, MutableSpan< float3 > data)
CurvesGeometry resample_to_length(const CurvesGeometry &src_curves, const IndexMask &selection, const VArray< float > &sample_lengths, const ResampleCurvesOutputAttributeIDs &output_ids={})
void interpolate(const Span< T > src, const Span< int > indices, const Span< float > factors, MutableSpan< T > dst)
void sample_uniform(Span< float > accumulated_segment_lengths, bool include_last_point, MutableSpan< int > r_segment_indices, MutableSpan< float > r_factors)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
void copy_group_sizes(OffsetIndices< int > offsets, const IndexMask &mask, MutableSpan< int > sizes)
OffsetIndices< int > accumulate_counts_to_offsets(MutableSpan< int > counts_to_offsets, int start_offset=0)
std::optional< OffsetIndices< int > > accumulate_counts_to_offsets_with_overflow_check(MutableSpan< int > counts_to_offsets, int start_offset=0)
VecBase< float, 3 > float3
Span< float3 > src_evaluated_tangents
MutableSpan< float3 > dst_normals
Vector< bke::GSpanAttributeWriter > dst_attributes
Vector< GMutableSpan > dst_no_interpolation
Vector< GVArraySpan > src
Vector< GVArraySpan > src_no_interpolation
MutableSpan< float3 > dst_tangents
Span< float3 > src_evaluated_normals
Vector< GMutableSpan > dst
MutableSpan< T > resize(const int64_t size)
std::array< std::byte, 1024 > inline_buffer
Vector< std::byte, 0, AllocatorType > heap_allocated
std::optional< std::string > tangent_id
std::optional< std::string > normal_id