22 [](
int value) {
return std::max(1, value); },
24 auto clamp_op = std::make_shared<fn::FieldOperation>(
33 "Length Input to Count",
34 [](
const float curve_length,
const float sample_length) {
37 const int count = int(curve_length / sample_length) + 1;
44 {
fn::Field<float>(std::make_shared<bke::CurveLengthFieldInput>()), length_field}));
54 const std::array<int, CURVE_TYPES_NUM> &type_counts)
66 if (
ELEM(attribute_id.
name(),
"nurbs_weight")) {
84 return !(attribute_id.
is_named() && no_interpolation.contains(attribute_id.
name()));
107 dst_attributes.
append(std::move(dst_attribute));
145 ids_no_interpolation.
add_new(
id);
162 result.src_no_interpolation,
163 result.dst_no_interpolation,
189 evaluator.set_selection(selection_field);
190 evaluator.add_with_destination(count_field, dst_offsets);
191 evaluator.evaluate();
192 const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
228 const IndexMask sliced_selection = selection.slice(selection_range);
230 Vector<std::byte> evaluated_buffer;
233 for (const int i_curve : sliced_selection) {
234 const bool cyclic = curves_cyclic[i_curve];
235 const IndexRange dst_points = dst_curves.points_for_curve(i_curve);
236 const Span<float> lengths = src_curves.evaluated_lengths_for_curve(i_curve, cyclic);
237 if (lengths.is_empty()) {
239 sample_indices.as_mutable_span().slice(dst_points).fill(0);
240 sample_factors.as_mutable_span().slice(dst_points).fill(0.0f);
243 length_parameterize::sample_uniform(lengths,
244 !curves_cyclic[i_curve],
245 sample_indices.as_mutable_span().slice(dst_points),
246 sample_factors.as_mutable_span().slice(dst_points));
252 for (
const int i_attribute : attributes.
dst.index_range()) {
253 attribute_math::convert_to_static_type(attributes.src[i_attribute].type(), [&](auto dummy) {
254 using T = decltype(dummy);
255 Span<T> src = attributes.src[i_attribute].typed<T>();
256 MutableSpan<T> dst = attributes.dst[i_attribute].typed<T>();
258 for (const int i_curve : sliced_selection) {
259 const IndexRange src_points = src_curves.points_for_curve(i_curve);
260 const IndexRange dst_points = dst_curves.points_for_curve(i_curve);
262 if (curve_types[i_curve] == CURVE_TYPE_POLY) {
263 length_parameterize::interpolate(src.slice(src_points),
264 sample_indices.as_span().slice(dst_points),
265 sample_factors.as_span().slice(dst_points),
266 dst.slice(dst_points));
269 const int evaluated_size = src_curves.evaluated_points_for_curve(i_curve).size();
270 evaluated_buffer.clear();
271 evaluated_buffer.resize(sizeof(T) * evaluated_size);
272 MutableSpan<T> evaluated = evaluated_buffer.as_mutable_span().cast<T>();
273 src_curves.interpolate_to_evaluated(i_curve, src.slice(src_points), evaluated);
275 length_parameterize::interpolate(evaluated.as_span(),
276 sample_indices.as_span().slice(dst_points),
277 sample_factors.as_span().slice(dst_points),
278 dst.slice(dst_points));
285 for (
const int i_curve : sliced_selection) {
286 const IndexRange src_points = src_curves.evaluated_points_for_curve(i_curve);
287 const IndexRange dst_points = dst_curves.points_for_curve(i_curve);
289 sample_indices.as_span().slice(dst_points),
290 sample_factors.as_span().slice(dst_points),
291 dst_positions.slice(dst_points));
295 for (GMutableSpan dst : attributes.dst_no_interpolation) {
296 for (
const int i_curve : sliced_selection) {
297 const IndexRange dst_points = dst_curves.points_for_curve(i_curve);
298 dst.type().value_initialize_n(dst.slice(dst_points).data(), dst_points.size());
304 for (
const int i : attributes.src.index_range()) {
306 src_curves, dst_curves, unselected_ranges, attributes.src[i], attributes.dst[i]);
308 for (
const int i : attributes.src_no_interpolation.index_range()) {
312 attributes.src_no_interpolation[i],
313 attributes.dst_no_interpolation[i]);
317 Span<float3> src_positions = src_curves.positions();
319 src_curves, dst_curves, unselected_ranges, src_positions, dst_positions);
321 for (bke::GSpanAttributeWriter &
attribute : attributes.dst_attributes) {
325 return dst_curves_id;
352 evaluator.set_selection(selection_field);
353 evaluator.evaluate();
354 const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
373 for (const int i : selection.slice(range)) {
374 dst_offsets[i] = src_curves.evaluated_points_for_curve(i).size();
380 dst_curves.resize(dst_offsets.last(), dst_curves.curves_num());
383 Span<float3> evaluated_positions = src_curves.evaluated_positions();
386 AttributesForInterpolation attributes;
392 const IndexMask sliced_selection = selection.slice(selection_range);
395 for (const int i_attribute : attributes.dst.index_range()) {
396 attribute_math::convert_to_static_type(attributes.src[i_attribute].type(), [&](auto dummy) {
397 using T = decltype(dummy);
398 Span<T> src = attributes.src[i_attribute].typed<T>();
399 MutableSpan<T> dst = attributes.dst[i_attribute].typed<T>();
401 for (const int i_curve : sliced_selection) {
402 const IndexRange src_points = src_curves.points_for_curve(i_curve);
403 const IndexRange dst_points = dst_curves.points_for_curve(i_curve);
404 src_curves.interpolate_to_evaluated(
405 i_curve, src.slice(src_points), dst.slice(dst_points));
411 for (
const int i_curve : sliced_selection) {
412 const IndexRange src_points = src_curves.evaluated_points_for_curve(i_curve);
413 const IndexRange dst_points = dst_curves.points_for_curve(i_curve);
414 dst_positions.
slice(dst_points).copy_from(evaluated_positions.
slice(src_points));
418 for (GMutableSpan dst : attributes.dst_no_interpolation) {
419 for (const int i_curve : sliced_selection) {
420 const IndexRange dst_points = dst_curves.points_for_curve(i_curve);
421 dst.type().value_initialize_n(dst.slice(dst_points).data(), dst_points.size());
427 for (
const int i : attributes.src.index_range()) {
429 src_curves, dst_curves, unselected_ranges, attributes.src[i], attributes.dst[i]);
431 for (
const int i : attributes.src_no_interpolation.index_range()) {
435 attributes.src_no_interpolation[i],
436 attributes.dst_no_interpolation[i]);
440 Span<float3> src_positions = src_curves.positions();
442 src_curves, dst_curves, unselected_ranges, src_positions, dst_positions);
444 for (bke::GSpanAttributeWriter &
attribute : attributes.dst_attributes) {
448 return dst_curves_id;
Low-level operations for curves.
Low-level operations for curves.
void CustomData_copy(const struct CustomData *source, struct CustomData *dest, eCustomDataMask mask, eCDAllocType alloctype, int totelem)
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 Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise 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
const Curves * get_for_read() const
void replace(Curves *curve, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
std::optional< blender::bke::AttributeAccessor > attributes() const final
std::optional< blender::bke::MutableAttributeAccessor > attributes_for_write() final
GSpan get_internal_span() const
const CPPType & type() const
Vector< IndexRange > extract_ranges_invert(const IndexRange full_range, Vector< int64_t > *r_skip_amounts=nullptr) const
IndexRange index_range() const
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
constexpr T & last(const int64_t n=0) const
constexpr Span slice(int64_t start, int64_t size) const
constexpr IndexRange index_range() const
void add_new(const Key &key)
void remove_contained(const Key &key)
void append(const T &value)
MutableSpan< float3 > positions_for_write()
void ensure_can_interpolate_to_evaluated() const
IndexRange curves_range() const
const std::array< int, CURVE_TYPES_NUM > & curve_type_counts() const
void ensure_evaluated_offsets() const
static CurvesGeometry & wrap(::CurvesGeometry &dna_struct)
void resize(int points_num, int curves_num)
void fill_curve_types(CurveType type)
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
SyclQueue void void * src
void fill_curve_counts(const bke::CurvesGeometry &curves, Span< IndexRange > curve_ranges, MutableSpan< int > counts)
void accumulate_counts_to_offsets(MutableSpan< int > counts_to_offsets, int start_offset=0)
void copy_point_data(const CurvesGeometry &src_curves, const CurvesGeometry &dst_curves, Span< IndexRange > curve_ranges, GSpan src, GMutableSpan dst)
static struct PartialUpdateUser * wrap(PartialUpdateUserImpl *user)
eCustomDataType cpp_type_to_custom_data_type(const blender::CPPType &type)
Curves * curves_new_nomain(int points_num, int curves_num)
Curves * resample_to_count(const CurveComponent &src_component, const fn::Field< bool > &selection_field, const fn::Field< int > &count_field)
static void gather_point_attributes_to_interpolate(const CurveComponent &src_component, CurveComponent &dst_component, AttributesForInterpolation &result)
static fn::Field< int > get_count_input_from_length(const fn::Field< float > &length_field)
static void retrieve_attribute_spans(const Span< bke::AttributeIDRef > ids, const CurveComponent &src_component, CurveComponent &dst_component, Vector< GSpan > &src, Vector< GMutableSpan > &dst, Vector< bke::GSpanAttributeWriter > &dst_attributes)
static Curves * resample_to_uniform(const CurveComponent &src_component, const fn::Field< bool > &selection_field, const fn::Field< int > &count_field)
static fn::Field< int > get_count_input_max_one(const fn::Field< int > &count_field)
Curves * resample_to_evaluated(const CurveComponent &src_component, const fn::Field< bool > &selection_field)
Curves * resample_to_length(const CurveComponent &src_component, const fn::Field< bool > &selection_field, const fn::Field< float > &segment_length_field)
static bool interpolate_attribute_to_poly_curve(const bke::AttributeIDRef &attribute_id)
static bool interpolate_attribute_to_curves(const bke::AttributeIDRef &attribute_id, const std::array< int, CURVE_TYPES_NUM > &type_counts)
void interpolate(const Span< T > src, const Span< int > indices, const Span< float > factors, MutableSpan< T > dst)
void parallel_for(IndexRange range, int64_t grain_size, const Function &function)
Vector< GMutableSpan > dst_no_interpolation
Vector< GSpan > src_no_interpolation
Vector< GMutableSpan > dst
Vector< bke::GSpanAttributeWriter > dst_attributes