61 const KDTree_3d &old_roots_kdtree)
63 const int tot_added_curves = root_positions.
size();
66 for (
const int i :
range) {
67 const float3 root = root_positions[i];
68 std::array<KDTreeNearest_3d, max_neighbors> nearest_n;
69 const int found_neighbors = BLI_kdtree_3d_find_nearest_n(
71 float tot_weight = 0.0f;
72 for (
const int neighbor_i :
IndexRange(found_neighbors)) {
73 KDTreeNearest_3d &nearest = nearest_n[neighbor_i];
74 const float weight = 1.0f / std::max(nearest.dist, 0.00001f);
76 neighbors_per_curve[i].append({nearest.index, weight});
80 neighbor.weight /= tot_weight;
84 return neighbors_per_curve;
140 const int old_curves_num,
149 const int added_curves_num = root_positions_cu.
size();
151 const OffsetIndices points_by_curve = curves.points_by_curve();
152 const Span<float2> uv_coords = curves.surface_uv_coords();
155 for (
const int added_curve_i :
range) {
156 const NeighborCurves &neighbors = neighbors_per_curve[added_curve_i];
157 const int curve_i = old_curves_num + added_curve_i;
158 const IndexRange points = points_by_curve[curve_i];
160 const float length_cu = new_lengths_cu[added_curve_i];
161 const float3 &normal_su = new_normals_su[added_curve_i];
165 const float3 &root_cu = root_positions_cu[added_curve_i];
169 const float3 tip_cu = root_cu + length_cu * normal_cu;
174 positions_cu.
slice(points).
fill(root_cu);
177 const int neighbor_curve_i = neighbor.index;
178 const float2 neighbor_uv = uv_coords[neighbor_curve_i];
180 if (result.type != ReverseUVSampler::ResultType::Ok) {
185 corner_tris[result.tri_index], result.bary_weights, corner_normals_su);
191 float normal_rotation_cu[3][3];
194 const IndexRange neighbor_points = points_by_curve[neighbor_curve_i];
195 const float3 &neighbor_root_cu = positions_cu[neighbor_points[0]];
205 if (neighbor_positions_cu.
size() == 1) {
210 length_parameterize::accumulate_lengths<float3>(neighbor_positions_cu,
false, lengths);
211 const float neighbor_length_cu = lengths.last();
214 const float length_factor = std::min(1.0f, length_cu / neighbor_length_cu);
215 const float resample_factor = (1.0f / (points.size() - 1.0f)) * length_factor;
217 sample_lengths[i] = i * resample_factor * neighbor_length_cu;
222 length_parameterize::sample_at_lengths(lengths, sample_lengths, indices, factors);
224 for (
const int i :
IndexRange(points.size())) {
226 neighbor_positions_cu[indices[i] + 1],
228 const float3 relative_to_root_cu = sample_cu - neighbor_root_cu;
229 float3 rotated_relative_coord = relative_to_root_cu;
230 mul_m3_v3(normal_rotation_cu, rotated_relative_coord);
231 positions_cu[points[i]] += neighbor.weight * rotated_relative_coord;
250 const int old_curves_num,
255 const int added_curves_num = new_lengths_cu.
size();
256 const OffsetIndices points_by_curve = curves.points_by_curve();
267 for (
const int i :
range) {
269 const float length_cu = new_lengths_cu[i];
270 const int curve_i = old_curves_num + i;
271 const IndexRange points = points_by_curve[curve_i];
282 const int neighbor_curve_i = neighbor.index;
283 const IndexRange neighbor_points = points_by_curve[neighbor_curve_i];
285 const Span<float> neighbor_radii_cu = radius_attr.
span.slice(neighbor_points);
288 length_parameterize::accumulate_lengths<float3>(neighbor_positions_cu,
false, lengths);
290 const float neighbor_length_cu = lengths.last();
293 const float length_factor = std::min(1.0f, length_cu / neighbor_length_cu);
294 const float resample_factor = (1.0f / (points.size() - 1.0f)) * length_factor;
296 sample_lengths[i] = i * resample_factor * neighbor_length_cu;
301 length_parameterize::sample_at_lengths(lengths, sample_lengths, indices, factors);
303 for (
const int i :
IndexRange(points.size())) {
305 neighbor_radii_cu[indices[i]], neighbor_radii_cu[indices[i] + 1], factors[i]);
307 radii_cu[points[i]] += neighbor.weight * sample_cu;
320 const bool use_interpolation = inputs.interpolate_length || inputs.interpolate_point_count ||
321 inputs.interpolate_radius || inputs.interpolate_shape ||
322 inputs.interpolate_resolution;
330 const Span<float3> surface_positions = inputs.surface->vert_positions();
331 const Span<int> surface_corner_verts = inputs.surface->corner_verts();
332 for (
const int i : inputs.uvs.index_range()) {
333 const float2 &uv = inputs.uvs[i];
335 if (result.type != ReverseUVSampler::ResultType::Ok) {
336 outputs.uv_error =
true;
339 const int3 &tri = inputs.surface_corner_tris[result.tri_index];
340 bary_coords.
append(result.bary_weights);
341 tri_indices.
append(result.tri_index);
342 const float3 root_position_su = bke::attribute_math::mix3<float3>(
344 surface_positions[surface_corner_verts[tri[0]]],
345 surface_positions[surface_corner_verts[tri[1]]],
346 surface_positions[surface_corner_verts[tri[2]]]);
353 if (use_interpolation) {
354 BLI_assert(inputs.old_roots_kdtree !=
nullptr);
358 const int added_curves_num = root_positions_cu.
size();
359 const int old_points_num = curves.points_num();
360 const int old_curves_num = curves.curves_num();
361 const int new_curves_num = old_curves_num + added_curves_num;
364 curves.resize(old_points_num, new_curves_num);
365 if (new_curves_num == 0) {
371 Array<int> new_point_counts_per_curve(added_curves_num);
372 if (inputs.interpolate_point_count && old_curves_num > 0) {
374 interpolate_from_neighbor_curves<int>(
376 inputs.fallback_point_count,
377 [&](
const int curve_i) { return old_points_by_curve[curve_i].size(); },
378 new_point_counts_per_curve);
381 new_point_counts_per_curve.
fill(inputs.fallback_point_count);
383 curve_offsets[old_curves_num] = old_points_num;
384 int offset = old_points_num;
385 for (
const int i : new_point_counts_per_curve.
index_range()) {
386 const int point_count_in_curve = new_point_counts_per_curve[i];
387 curve_offsets[old_curves_num + i + 1] = offset + point_count_in_curve;
388 offset += point_count_in_curve;
391 const int new_points_num = curves.offsets().
last();
392 curves.resize(new_points_num, new_curves_num);
393 const OffsetIndices points_by_curve = curves.points_by_curve();
396 outputs.new_points_range = curves.points_range().drop_front(old_points_num);
397 outputs.new_curves_range = curves.curves_range().drop_front(old_curves_num);
406 if (inputs.interpolate_length) {
407 interpolate_from_neighbor_curves<float>(
409 inputs.fallback_curve_length,
410 [&](
const int curve_i) {
411 const IndexRange points = points_by_curve[curve_i];
413 for (const int segment_i : points.drop_back(1)) {
414 const float3 &p1 = positions_cu[segment_i];
415 const float3 &p2 = positions_cu[segment_i + 1];
416 length += math::distance(p1, p2);
423 new_lengths_cu.fill(inputs.fallback_curve_length);
427 Array<float3> new_normals_su(added_curves_num);
428 bke::mesh_surface_sample::sample_corner_normals(inputs.surface_corner_tris,
431 inputs.corner_normals_su,
432 IndexMask(added_curves_num),
436 if (inputs.interpolate_shape) {
437 calc_position_with_interpolation(curves,
444 inputs.surface_corner_tris,
445 *inputs.reverse_uv_sampler,
446 inputs.corner_normals_su);
454 inputs.transforms->surface_to_curves_normal);
458 if (inputs.interpolate_radius) {
460 curves, old_curves_num, inputs.fallback_curve_radius, new_lengths_cu, neighbors_per_curve);
464 curves, outputs.new_points_range, inputs.fallback_curve_radius);
469 bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
471 if (bke::SpanAttributeWriter<int> resolution = attributes.lookup_for_write_span<
int>(
474 if (inputs.interpolate_resolution) {
478 [&](
const int curve_i) {
return resolution.span[curve_i]; },
479 resolution.span.take_back(added_curves_num));
483 resolution.span.take_back(added_curves_num).fill(12);
488 bke::fill_attribute_range_default(attributes,
489 bke::AttrDomain::Point,
490 bke::attribute_filter_from_skip_ref({
"position",
"radius"}),
491 outputs.new_points_range);
492 bke::fill_attribute_range_default(
494 bke::AttrDomain::Curve,
495 bke::attribute_filter_from_skip_ref({
"curve_type",
"surface_uv_coordinate",
"resolution"}),
496 outputs.new_curves_range);
static blender::bke::bNodeSocketTemplate outputs[]