38 const float sample_length,
41 const int num_curve_points)
44 const int last_index = num_curve_points - 1;
45 if (sample_length <= 0.0f) {
46 return {{0, 1}, 0.0f};
48 if (sample_length >= lengths.
last()) {
56 const int index = eval_index / resolution;
57 const int next_index = (index == last_index) ? 0 : index + 1;
58 const float parameter = (eval_factor + eval_index) / resolution - index;
67 const float sample_length,
69 const int evaluated_size)
71 const int last_index = evaluated_size - 1;
72 if (sample_length <= 0.0f) {
73 return {{0, 1}, 0.0f};
75 if (sample_length >= lengths.
last()) {
84 const int next_eval_index = (eval_index == last_index) ? 0 : eval_index + 1;
93 const float sample_length,
95 const int num_curve_points)
97 const int last_index = num_curve_points - 1;
98 if (sample_length <= 0.0f) {
99 return {{0, 1}, 0.0f};
101 if (sample_length >= lengths.
last()) {
110 const int *offset = std::upper_bound(bezier_offsets.
begin(), bezier_offsets.
end(), eval_index);
111 const int left = offset - bezier_offsets.
begin() - 1;
112 const int right =
left == last_index ? 0 :
left + 1;
114 const int prev_offset = bezier_offsets[
left];
115 const float offset_in_segment = eval_factor + (eval_index - prev_offset);
116 const int segment_resolution = bezier_offsets[
left + 1] - prev_offset;
117 const float parameter = std::clamp(offset_in_segment / segment_resolution, 0.0f, 1.0f);
119 return {{
left, right}, parameter};
127 const float sample_length,
129 const int resolution,
130 const int num_curve_points)
133 num_curve_points, evaluated_points_by_curve[curve_index].
size(), cyclic, resolution))
137 bezier_offsets, accumulated_lengths, sample_length, cyclic, num_curve_points);
140 accumulated_lengths, sample_length, cyclic, resolution, num_curve_points);
149 const float sample_length,
151 const int resolution,
152 const int num_curve_points)
154 if (num_curve_points == 1) {
155 return {{0, 0}, 0.0f};
160 accumulated_lengths, sample_length, cyclic, resolution, num_curve_points);
164 evaluated_points_by_curve,
178 accumulated_lengths, sample_length, cyclic, evaluated_points_by_curve[curve_index].
size());
199 const IndexRange points = dst_points_by_curve[curve_i];
202 handle_positions_left.
slice(points).
fill({0.0f, 0.0f, 0.0f});
203 handle_positions_right.
slice(points).
fill({0.0f, 0.0f, 0.0f});
225 dst_index += increment;
228 dst_data.
slice(dst_index, increment)
230 dst_index += increment;
235 dst_index += increment;
249 const bool src_cyclic)
253 if (insertion_point.
index == 0) {
254 i0 = src_cyclic ? src_data.
size() - 1 : insertion_point.
index;
257 i0 = insertion_point.
index - 1;
260 if (i3 == src_data.
size()) {
261 i3 = src_cyclic ? 0 : insertion_point.
next_index;
264 src_data[insertion_point.
index],
280 handles_right[insertion_point.
index],
305template<
typename T,
bool include_start_po
int = true>
317 if constexpr (!include_start_point) {
322 else if constexpr (!include_start_point) {
333 if (dst_range.
size() == 1) {
359 const bool src_cyclic)
372 if (dst_range.
size() == 1) {
390template<
bool include_start_po
int = true>
409 bool start_point_trimmed =
false;
412 if constexpr (!include_start_point) {
416 else if constexpr (!include_start_point) {
422 src_positions, src_handles_l, src_handles_r, start_point);
423 dst_positions[dst_range.
first()] = start_point_insert.
position;
426 dst_types_l[dst_range.
first()] = src_types_l[start_point.
index];
427 dst_types_r[dst_range.
first()] = src_types_r[start_point.
index];
429 start_point_trimmed =
true;
437 const IndexRange dst_range_to_end(dst_index, increment);
444 dst_index += increment;
446 if (dst_range.
size() == 1) {
452 if (src_range.
cycles() && increment > 0) {
453 const IndexRange dst_range_looped(dst_index, increment);
460 dst_index += increment;
463 if (start_point_trimmed) {
476 dst_handles_l[dst_range.
first()] = dst_positions[dst_range.
first()];
477 dst_handles_r[dst_range.
last()] = dst_positions[dst_range.
first()];
479 else if (start_point.
parameter == 1.0f) {
496 dst_handles_l[dst_range.
first()] = dst_positions[dst_range.
first()];
497 dst_handles_r[dst_range.
last()] = dst_positions[dst_range.
first()];
499 else if (start_point.
parameter == 1.0f) {
540 dst_handles_r[dst_index - 1],
549 src_positions, src_handles_l, src_handles_r, end_point);
560 dst_handles_r[dst_index - 1] = end_point_insert.
handle_prev;
561 dst_types_r[dst_index - 1] = src_types_l[end_point.
index];
563 dst_handles_l[dst_index] = end_point_insert.
left_handle;
564 dst_handles_r[dst_index] = end_point_insert.
right_handle;
565 dst_positions[dst_index] = end_point_insert.
position;
566 dst_types_l[dst_index] = src_types_l[end_point.
next_index];
567 dst_types_r[dst_index] = src_types_r[end_point.
next_index];
593 using T = decltype(dummy);
595 selection.foreach_index(GrainSize(512), [&](const int curve_i) {
596 const IndexRange src_points = src_points_by_curve[curve_i];
597 sample_interval_linear<T>(attribute.src.template typed<T>().slice(src_points),
598 attribute.dst.span.typed<T>(),
600 dst_points_by_curve[curve_i],
601 start_points[curve_i],
602 end_points[curve_i]);
622 const IndexRange src_points = src_points_by_curve[curve_i];
623 const IndexRange dst_points = dst_points_by_curve[curve_i];
629 start_points[curve_i],
630 end_points[curve_i]);
640 transfer_attributes);
658 const IndexRange src_points = src_points_by_curve[curve_i];
659 const IndexRange dst_points = dst_points_by_curve[curve_i];
665 start_points[curve_i],
667 src_cyclic[curve_i]);
674 using T = decltype(dummy);
676 selection.foreach_index(GrainSize(512), [&](const int curve_i) {
677 const IndexRange src_points = src_points_by_curve[curve_i];
678 const IndexRange dst_points = dst_points_by_curve[curve_i];
680 sample_interval_catmull_rom<T>(attribute.src.template typed<T>().slice(src_points),
681 attribute.dst.span.typed<T>(),
684 start_points[curve_i],
686 src_cyclic[curve_i]);
715 const IndexRange src_points = src_points_by_curve[curve_i];
716 const IndexRange dst_points = dst_points_by_curve[curve_i];
719 src_handles_l.
slice(src_points),
720 src_handles_r.
slice(src_points),
721 src_types_l.
slice(src_points),
722 src_types_r.
slice(src_points),
730 start_points[curve_i],
731 end_points[curve_i]);
740 transfer_attributes);
758 const IndexRange src_evaluated_points = src_evaluated_points_by_curve[curve_i];
759 const IndexRange dst_points = dst_points_by_curve[curve_i];
764 start_points[curve_i],
765 end_points[curve_i]);
772 using T = decltype(dummy);
774 selection.foreach_segment(GrainSize(512), [&](const IndexMaskSegment segment) {
775 Vector<std::byte> evaluated_buffer;
776 for (const int64_t curve_i : segment) {
777 const IndexRange src_points = src_points_by_curve[curve_i];
780 evaluated_buffer.reinitialize(sizeof(T) * src_evaluated_points_by_curve[curve_i].size());
781 MutableSpan<T> evaluated = evaluated_buffer.as_mutable_span().cast<T>();
782 src_curves.interpolate_to_evaluated(curve_i, attribute.src.slice(src_points), evaluated);
783 sample_interval_linear<T>(evaluated,
784 attribute.dst.span.typed<T>(),
786 dst_points_by_curve[curve_i],
787 start_points[curve_i],
788 end_points[curve_i]);
800 const float sample_length,
804 sample_length * accumulated_lengths.
last() :
806 return std::clamp(
length, 0.0f, accumulated_lengths.
last());
835 point_count = evaluated_points_by_curve[curve_i].
size();
838 point_count = points_by_curve[curve_i].
size();
840 if (point_count == 1) {
842 dst_curve_size[curve_i] = 1;
844 start_points[curve_i] = {{0, 0}, 0.0f};
845 end_points[curve_i] = {{0, 0}, 0.0f};
849 const bool cyclic = src_cyclic[curve_i];
856 bool equal_sample_point;
859 const float cyclic_start = start_length == lengths.
last() ? 0.0f : start_length;
860 const float cyclic_end = end_length == lengths.
last() ? 0.0f : end_length;
861 equal_sample_point = cyclic_start == cyclic_end;
864 end_length = ends[curve_i] <= starts[curve_i] ?
867 equal_sample_point = start_length == end_length;
871 evaluated_points_by_curve,
879 if (equal_sample_point) {
880 end_points[curve_i] = start_points[curve_i];
881 if (end_length <= start_length) {
883 dst_curve_size[curve_i] = 1;
884 if (start_points[curve_i].is_controlpoint()) {
886 const int single_point_index = start_points[curve_i].parameter == 1.0f ?
887 start_points[curve_i].next_index :
888 start_points[curve_i].index;
890 single_point_index, 1, point_count);
897 start_points[curve_i], end_points[curve_i], point_count)
899 const int count = 1 + !start_points[curve_i].is_controlpoint() + point_count;
901 dst_curve_size[curve_i] =
count;
907 evaluated_points_by_curve,
917 start_points[curve_i], end_points[curve_i], point_count);
918 const int count = src_ranges[curve_i].
size() + !start_points[curve_i].is_controlpoint() +
919 !end_points[curve_i].is_controlpoint();
921 dst_curve_size[curve_i] =
count;
968 Set<std::string> transfer_curve_skip = {
"cyclic",
"curve_type",
"nurbs_order",
"knots_mode"};
971 transfer_curve_skip.
remove(
"nurbs_order");
972 transfer_curve_skip.
remove(
"knots_mode");
995 transfer_attributes);
1004 transfer_attributes);
1013 transfer_attributes);
1025 transfer_attributes);
1058 copy_point_skip.
add(
"nurbs_weight");
1066 src_points_by_curve,
1067 dst_points_by_curve,
Low-level operations for curves.
Low-level operations for curves.
GeometryNodeCurveSampleMode
@ GEO_NODE_CURVE_SAMPLE_FACTOR
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its and value channels Color Retrieve a color attribute
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
SIMD_FORCE_INLINE btScalar length(const btQuaternion &q)
Return the length of a quaternion.
constexpr const T & last(const int64_t n=0) const
constexpr int64_t first() const
constexpr int64_t one_after_last() const
constexpr int64_t last(const int64_t n=0) const
constexpr int64_t size() const
constexpr int64_t size() const
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
constexpr void fill(const T &value) const
constexpr void copy_from(Span< T > values) const
bool remove(const Key &key)
constexpr Span slice(int64_t start, int64_t size) const
constexpr int64_t size() const
constexpr const T & last(const int64_t n=0) const
constexpr const T * end() const
constexpr const T * begin() const
VArray< int8_t > handle_types_left() const
void remove_attributes_based_on_types()
MutableSpan< float3 > positions_for_write()
OffsetIndices< int > points_by_curve() const
MutableSpan< int8_t > handle_types_right_for_write()
VArray< int8_t > handle_types_right() const
void ensure_can_interpolate_to_evaluated() const
IndexRange curves_range() const
const std::array< int, CURVE_TYPES_NUM > & curve_type_counts() const
MutableSpan< float3 > handle_positions_left_for_write()
MutableAttributeAccessor attributes_for_write()
MutableSpan< float3 > handle_positions_right_for_write()
Span< float > evaluated_lengths_for_curve(int curve_index, bool cyclic) const
Span< float3 > handle_positions_left() const
VArray< int > resolution() const
Span< int > bezier_evaluated_offsets_for_curve(int curve_index) const
Span< int > offsets() const
Span< float3 > positions() const
OffsetIndices< int > evaluated_points_by_curve() const
bool has_curve_with_type(CurveType type) const
MutableSpan< float > nurbs_weights_for_write()
void tag_topology_changed()
void resize(int points_num, int curves_num)
Span< float3 > handle_positions_right() const
void fill_curve_types(CurveType type)
AttributeAccessor attributes() 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
MutableSpan< int8_t > handle_types_left_for_write()
bool remove(const StringRef attribute_id)
GSpanAttributeWriter lookup_for_write_span(StringRef attribute_id)
constexpr int first() const
constexpr IndexRangeCyclic drop_front(const int n=1) const
constexpr int size_after_loop() const
constexpr int size_range() const
constexpr IndexRange curve_range() const
static IndexRangeCyclic get_range_between_endpoints(const CurvePoint start_point, const CurvePoint end_point, const int iterable_range_size)
constexpr int size_before_loop() const
constexpr int one_after_last() const
static IndexRangeCyclic get_range_from_size(const int start_index, const int iterator_size, const int iterable_range_size)
constexpr int cycles() const
void convert_to_static_type(const CPPType &cpp_type, const Func &func)
T mix2(float factor, const T &a, const T &b)
Insertion insert(const float3 &point_prev, const float3 &handle_prev, const float3 &handle_next, const float3 &point_next, float parameter)
bool has_vector_handles(int num_curve_points, int64_t evaluated_size, bool cyclic, int resolution)
T interpolate(const T &a, const T &b, const T &c, const T &d, const float parameter)
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)
void foreach_curve_by_type(const VArray< int8_t > &types, const std::array< int, CURVE_TYPES_NUM > &type_counts, const IndexMask &selection, FunctionRef< void(IndexMask)> catmull_rom_fn, FunctionRef< void(IndexMask)> poly_fn, FunctionRef< void(IndexMask)> bezier_fn, FunctionRef< void(IndexMask)> nurbs_fn)
Vector< AttributeTransferData > retrieve_attributes_for_transfer(const AttributeAccessor src_attributes, MutableAttributeAccessor dst_attributes, AttrDomainMask domain_mask, const AttributeFilter &attribute_filter={})
auto attribute_filter_with_skip_ref(AttributeFilter filter, const Span< StringRef > skip)
void copy_attributes_group_to_group(AttributeAccessor src_attributes, AttrDomain src_domain, AttrDomain dst_domain, const AttributeFilter &attribute_filter, OffsetIndices< int > src_offsets, OffsetIndices< int > dst_offsets, const IndexMask &selection, MutableAttributeAccessor dst_attributes)
static void trim_bezier_curves(const bke::CurvesGeometry &src_curves, bke::CurvesGeometry &dst_curves, const IndexMask &selection, const Span< bke::curves::CurvePoint > start_points, const Span< bke::curves::CurvePoint > end_points, const Span< bke::curves::IndexRangeCyclic > src_ranges, MutableSpan< bke::AttributeTransferData > transfer_attributes)
static bke::curves::CurvePoint lookup_point_bezier(const Span< int > bezier_offsets, const Span< float > lengths, const float sample_length, const bool cyclic, const int num_curve_points)
static void sample_interval_linear(const Span< T > src_data, MutableSpan< T > dst_data, bke::curves::IndexRangeCyclic src_range, const IndexRange dst_range, const bke::curves::CurvePoint start_point, const bke::curves::CurvePoint end_point)
static bke::curves::CurvePoint lookup_curve_point(const bke::CurvesGeometry &src_curves, const OffsetIndices< int > evaluated_points_by_curve, const CurveType curve_type, const int64_t curve_index, const Span< float > accumulated_lengths, const float sample_length, const bool cyclic, const int resolution, const int num_curve_points)
static bke::curves::bezier::Insertion knot_insert_bezier(const Span< float3 > positions, const Span< float3 > handles_left, const Span< float3 > handles_right, const bke::curves::CurvePoint insertion_point)
bke::CurvesGeometry trim_curves(const bke::CurvesGeometry &src_curves, const IndexMask &selection, const VArray< float > &starts, const VArray< float > &ends, GeometryNodeCurveSampleMode mode, const bke::AttributeFilter &attribute_filter)
static int64_t copy_point_data_between_endpoints(const Span< T > src_data, MutableSpan< T > dst_data, const bke::curves::IndexRangeCyclic src_range, int64_t dst_index)
static void trim_polygonal_curves(const bke::CurvesGeometry &src_curves, bke::CurvesGeometry &dst_curves, const IndexMask &selection, const Span< bke::curves::CurvePoint > start_points, const Span< bke::curves::CurvePoint > end_points, const Span< bke::curves::IndexRangeCyclic > src_ranges, MutableSpan< bke::AttributeTransferData > transfer_attributes)
static float trim_sample_length(const Span< float > accumulated_lengths, const float sample_length, const GeometryNodeCurveSampleMode mode)
static T interpolate_catmull_rom(const Span< T > src_data, const bke::curves::CurvePoint insertion_point, const bool src_cyclic)
static bke::curves::CurvePoint lookup_point_polygonal(const Span< float > lengths, const float sample_length, const bool cyclic, const int evaluated_size)
static bke::curves::CurvePoint lookup_point_uniform_spacing(const Span< float > lengths, const float sample_length, const bool cyclic, const int resolution, const int num_curve_points)
static void trim_attribute_linear(const bke::CurvesGeometry &src_curves, bke::CurvesGeometry &dst_curves, const IndexMask &selection, const Span< bke::curves::CurvePoint > start_points, const Span< bke::curves::CurvePoint > end_points, const Span< bke::curves::IndexRangeCyclic > src_ranges, MutableSpan< bke::AttributeTransferData > transfer_attributes)
static void compute_curve_trim_parameters(const bke::CurvesGeometry &curves, const IndexMask &selection, const VArray< float > &starts, const VArray< float > &ends, const GeometryNodeCurveSampleMode mode, MutableSpan< int > dst_curve_size, MutableSpan< bke::curves::CurvePoint > start_points, MutableSpan< bke::curves::CurvePoint > end_points, MutableSpan< bke::curves::IndexRangeCyclic > src_ranges)
static void sample_interval_catmull_rom(const Span< T > src_data, MutableSpan< T > dst_data, bke::curves::IndexRangeCyclic src_range, const IndexRange dst_range, const bke::curves::CurvePoint start_point, const bke::curves::CurvePoint end_point, const bool src_cyclic)
static void trim_catmull_rom_curves(const bke::CurvesGeometry &src_curves, bke::CurvesGeometry &dst_curves, const IndexMask &selection, const Span< bke::curves::CurvePoint > start_points, const Span< bke::curves::CurvePoint > end_points, const Span< bke::curves::IndexRangeCyclic > src_ranges, MutableSpan< bke::AttributeTransferData > transfer_attributes)
static void fill_nurbs_data(bke::CurvesGeometry &dst_curves, const IndexMask &selection)
static void sample_interval_bezier(const Span< float3 > src_positions, const Span< float3 > src_handles_l, const Span< float3 > src_handles_r, const Span< int8_t > src_types_l, const Span< int8_t > src_types_r, MutableSpan< float3 > dst_positions, MutableSpan< float3 > dst_handles_l, MutableSpan< float3 > dst_handles_r, MutableSpan< int8_t > dst_types_l, MutableSpan< int8_t > dst_types_r, bke::curves::IndexRangeCyclic src_range, const IndexRange dst_range, const bke::curves::CurvePoint start_point, const bke::curves::CurvePoint end_point)
static void trim_evaluated_curves(const bke::CurvesGeometry &src_curves, bke::CurvesGeometry &dst_curves, const IndexMask &selection, const Span< bke::curves::CurvePoint > start_points, const Span< bke::curves::CurvePoint > end_points, const Span< bke::curves::IndexRangeCyclic > src_ranges, MutableSpan< bke::AttributeTransferData > transfer_attributes)
static void fill_bezier_data(bke::CurvesGeometry &dst_curves, const IndexMask &selection)
void masked_fill(MutableSpan< T > data, const T &value, const IndexMask &mask)
void sample_at_length(const Span< float > accumulated_segment_lengths, const float sample_length, int &r_segment_index, float &r_factor, SampleSegmentHint *hint=nullptr)
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)
VecBase< float, 3 > float3
GPU_SHADER_INTERFACE_INFO(overlay_edit_curve_handle_iface, "vert").flat(Type pos vertex_in(1, Type::UINT, "data") .vertex_out(overlay_edit_curve_handle_iface) .geometry_layout(PrimitiveIn Frequency::GEOMETRY storage_buf(1, Qualifier::READ, "uint", "data[]", Frequency::GEOMETRY) .push_constant(Type Frequency::GEOMETRY selection[]
bool is_controlpoint() const