250 GMutableSpan sampled_values =
params.uninitialized_single_output_if_required(5,
"Value");
252 auto return_default = [&]() {
253 if (!sampled_positions.
is_empty()) {
256 if (!sampled_tangents.is_empty()) {
259 if (!sampled_normals.is_empty()) {
265 return return_default();
270 if (curves.points_num() == 0) {
271 return return_default();
273 curves.ensure_can_interpolate_to_evaluated();
274 Span<float3> evaluated_positions = curves.evaluated_positions();
277 if (!sampled_tangents.is_empty()) {
278 evaluated_tangents = curves.evaluated_tangents();
280 if (!sampled_normals.is_empty()) {
281 evaluated_normals = curves.evaluated_normals();
284 const OffsetIndices points_by_curve = curves.points_by_curve();
285 const OffsetIndices evaluated_points_by_curve = curves.evaluated_points_by_curve();
286 const VArray<int> curve_indices =
params.readonly_single_input<
int>(0,
"Curve Index");
296 if (!sampled_positions.
is_empty()) {
299 if (!sampled_tangents.is_empty()) {
302 if (!sampled_normals.is_empty()) {
305 if (!sampled_values.is_empty()) {
307 using T = decltype(dummy);
308 index_mask::masked_fill<T>(sampled_values.typed<T>(), {}, mask);
313 auto sample_curve = [&](
const int curve_i,
const IndexMask &
mask) {
314 const Span<float> accumulated_lengths = curves.evaluated_lengths_for_curve(curve_i,
316 if (accumulated_lengths.
is_empty()) {
322 indices.reinitialize(mask.size());
323 factors.reinitialize(mask.size());
325 accumulated_lengths, lengths, length_mode_, mask, indices, factors);
327 const IndexRange evaluated_points = evaluated_points_by_curve[curve_i];
328 if (!sampled_positions.is_empty()) {
330 evaluated_positions.slice(evaluated_points),
336 if (!sampled_tangents.is_empty()) {
338 evaluated_tangents.slice(evaluated_points), indices, factors, mask, sampled_tangents);
340 [&](
const int i) { sampled_tangents[i] =
math::normalize(sampled_tangents[i]); });
342 if (!sampled_normals.is_empty()) {
344 evaluated_normals.slice(evaluated_points), indices, factors, mask, sampled_normals);
346 [&](
const int i) { sampled_normals[i] =
math::normalize(sampled_normals[i]); });
348 if (!sampled_values.is_empty()) {
349 const IndexRange points = points_by_curve[curve_i];
350 src_original_values.reinitialize(points.size());
352 src_evaluated_values.reinitialize(evaluated_points.
size());
353 curves.interpolate_to_evaluated(curve_i, src_original_values, src_evaluated_values);
355 using T = decltype(dummy);
356 const Span<T> src_evaluated_values_typed = src_evaluated_values.as_span().typed<T>();
357 MutableSpan<T> sampled_values_typed = sampled_values.typed<T>();
358 length_parameterize::interpolate_to_masked<T>(
359 src_evaluated_values_typed, indices, factors, mask, sampled_values_typed);
364 if (
const std::optional<int> curve_i = curve_indices.get_if_single()) {
365 if (curves.curves_range().contains(*curve_i)) {
366 sample_curve(*curve_i, mask);
373 Vector<int> valid_indices;
374 Vector<int> invalid_indices;
375 VectorSet<int> used_curves;
377 mask.foreach_index([&](
const int i) {
378 const int curve_i = curve_indices[i];
379 if (curves.curves_range().contains(curve_i)) {
380 used_curves.add(curve_i);
381 valid_indices.append(i);
384 invalid_indices.append(i);
389 IndexMaskMemory memory;
390 const IndexMask valid_indices_mask = valid_indices.size() == mask.size() ?
394 Array<IndexMask> mask_by_curve(used_curves.size());
398 [&](
const int i) {
return used_curves.index_of(curve_indices[i]); },
401 for (
const int i : mask_by_curve.index_range()) {
402 sample_curve(used_curves[i], mask_by_curve[i]);