39 const Mesh &surface_mesh_old,
40 const Mesh &surface_mesh_new,
50 std::atomic<int> &r_invalid_uv_count)
53 const int curves_num = curves.curves_num();
58 [&]() { reverse_uv_sampler_old.
sample_many(curve_attachment_uvs, surface_samples_old); },
59 [&]() { reverse_uv_sampler_new.
sample_many(curve_attachment_uvs, surface_samples_new); });
63 const Span<float3> surface_positions_old = surface_mesh_old.vert_positions();
64 const Span<int> surface_corner_verts_old = surface_mesh_old.corner_verts();
65 const Span<int3> surface_corner_tris_old = surface_mesh_old.corner_tris();
67 const Span<float3> surface_positions_new = surface_mesh_new.vert_positions();
68 const Span<int> surface_corner_verts_new = surface_mesh_new.corner_verts();
69 const Span<int3> surface_corner_tris_new = surface_mesh_new.corner_tris();
71 const OffsetIndices points_by_curve = curves.points_by_curve();
74 for (const int curve_i : range) {
75 const ReverseUVSampler::Result &surface_sample_old = surface_samples_old[curve_i];
76 if (surface_sample_old.type != ReverseUVSampler::ResultType::Ok) {
80 const ReverseUVSampler::Result &surface_sample_new = surface_samples_new[curve_i];
81 if (surface_sample_new.type != ReverseUVSampler::ResultType::Ok) {
86 const int3 &tri_old = surface_corner_tris_old[surface_sample_old.tri_index];
87 const int3 &tri_new = surface_corner_tris_new[surface_sample_new.tri_index];
88 const float3 &bary_weights_old = surface_sample_old.bary_weights;
89 const float3 &bary_weights_new = surface_sample_new.bary_weights;
91 const int corner_0_old = tri_old[0];
92 const int corner_1_old = tri_old[1];
93 const int corner_2_old = tri_old[2];
95 const int corner_0_new = tri_new[0];
96 const int corner_1_new = tri_new[1];
97 const int corner_2_new = tri_new[2];
99 const int vert_0_old = surface_corner_verts_old[corner_0_old];
100 const int vert_1_old = surface_corner_verts_old[corner_1_old];
101 const int vert_2_old = surface_corner_verts_old[corner_2_old];
103 const int vert_0_new = surface_corner_verts_new[corner_0_new];
104 const int vert_1_new = surface_corner_verts_new[corner_1_new];
105 const int vert_2_new = surface_corner_verts_new[corner_2_new];
107 const float3 &normal_0_old = corner_normals_old[corner_0_old];
108 const float3 &normal_1_old = corner_normals_old[corner_1_old];
109 const float3 &normal_2_old = corner_normals_old[corner_2_old];
110 const float3 normal_old = math::normalize(
111 mix3(bary_weights_old, normal_0_old, normal_1_old, normal_2_old));
113 const float3 &normal_0_new = corner_normals_new[corner_0_new];
114 const float3 &normal_1_new = corner_normals_new[corner_1_new];
115 const float3 &normal_2_new = corner_normals_new[corner_2_new];
116 const float3 normal_new = math::normalize(
117 mix3(bary_weights_new, normal_0_new, normal_1_new, normal_2_new));
119 const float3 &pos_0_old = surface_positions_old[vert_0_old];
120 const float3 &pos_1_old = surface_positions_old[vert_1_old];
121 const float3 &pos_2_old = surface_positions_old[vert_2_old];
122 const float3 pos_old = mix3(bary_weights_old, pos_0_old, pos_1_old, pos_2_old);
124 const float3 &pos_0_new = surface_positions_new[vert_0_new];
125 const float3 &pos_1_new = surface_positions_new[vert_1_new];
126 const float3 &pos_2_new = surface_positions_new[vert_2_new];
127 const float3 pos_new = mix3(bary_weights_new, pos_0_new, pos_1_new, pos_2_new);
130 const float3 translation = pos_new - pos_old;
132 const float3 &rest_pos_0 = rest_positions[vert_0_new];
133 const float3 &rest_pos_1 = rest_positions[vert_1_new];
145 const float3 tangent_reference_dir_old = rest_pos_1 - rest_pos_0;
146 const float3 tangent_reference_dir_new = pos_1_new - pos_0_new;
150 const float3 tangent_x_old = math::normalize(
151 math::cross(normal_old, tangent_reference_dir_old));
152 const float3 tangent_x_new = math::normalize(
153 math::cross(normal_new, tangent_reference_dir_new));
156 const float3 tangent_y_old = math::normalize(math::cross(normal_old, tangent_x_old));
157 const float3 tangent_y_new = math::normalize(math::cross(normal_new, tangent_x_new));
160 float3x3 rotation_old(tangent_x_old, tangent_y_old, normal_old);
163 float3x3 rotation_new(tangent_x_new, tangent_y_new, normal_new);
168 const float3x3 rotation_old_inv = math::transpose(rotation_old);
172 const float3x3 rotation = rotation_new * rotation_old_inv;
177 float4x4 surface_transform = math::from_origin_transform<float4x4>(float4x4(rotation),
179 surface_transform.location() += translation;
183 const float4x4 curve_transform = surface_to_curves * surface_transform * curves_to_surface;
186 const IndexRange points = points_by_curve[curve_i];
187 for (const int point_i : points) {
188 const float3 old_point_pos = r_positions[point_i];
189 const float3 new_point_pos = math::transform_point(curve_transform, old_point_pos);
190 r_positions[point_i] = new_point_pos;
193 if (!r_rotations.is_empty()) {
194 for (const int point_i : points) {
195 r_rotations[point_i] = rotation * r_rotations[point_i];
206 Mesh *surface_mesh_orig =
nullptr;
207 bool free_suface_mesh_orig =
false;
209 if (free_suface_mesh_orig) {
214 auto pass_through_input = [&]() {
params.set_output(
"Curves", std::move(curves_geometry)); };
217 if (self_ob_eval ==
nullptr || self_ob_eval->
type !=
OB_CURVES) {
218 pass_through_input();
219 params.error_message_add(NodeWarningType::Error,
TIP_(
"Node only works for curves objects"));
222 const Curves *self_curves_eval =
static_cast<const Curves *
>(self_ob_eval->
data);
224 pass_through_input();
225 params.error_message_add(NodeWarningType::Error,
TIP_(
"Surface UV map not defined"));
234 pass_through_input();
237 if (surface_ob_eval ==
nullptr || surface_ob_eval->
type !=
OB_MESH) {
238 pass_through_input();
239 params.error_message_add(NodeWarningType::Error,
TIP_(
"Curves not attached to a surface"));
243 Mesh &surface_object_data = *
static_cast<Mesh *
>(surface_ob_orig->
data);
247 free_suface_mesh_orig =
true;
250 surface_mesh_orig = &surface_object_data;
253 if (surface_mesh_eval ==
nullptr) {
254 pass_through_input();
255 params.error_message_add(NodeWarningType::Error,
TIP_(
"Surface has no mesh"));
267 if (!mesh_attributes_eval.
contains(uv_map_name)) {
268 pass_through_input();
269 const std::string message = fmt::format(
TIP_(
"Evaluated surface missing UV map: \"{}\""),
271 params.error_message_add(NodeWarningType::Error, message);
274 if (!mesh_attributes_orig.
contains(uv_map_name)) {
275 pass_through_input();
276 const std::string message = fmt::format(
TIP_(
"Original surface missing UV map: \"{}\""),
278 params.error_message_add(NodeWarningType::Error, message);
281 if (!mesh_attributes_eval.
contains(rest_position_name)) {
282 pass_through_input();
283 params.error_message_add(NodeWarningType::Error,
284 TIP_(
"Evaluated surface missing attribute: \"rest_position\""));
287 if (curves.surface_uv_coords().is_empty() && curves.curves_num() > 0) {
288 pass_through_input();
289 params.error_message_add(NodeWarningType::Error,
290 TIP_(
"Curves are not attached to any UV map"));
299 const VArraySpan surface_uv_coords = *curves.attributes().lookup_or_default<
float2>(
300 "surface_uv_coordinate", AttrDomain::Curve,
float2(0));
302 const Span<int3> corner_tris_orig = surface_mesh_orig->corner_tris();
303 const Span<int3> corner_tris_eval = surface_mesh_eval->corner_tris();
304 const ReverseUVSampler reverse_uv_sampler_orig{uv_map_orig, corner_tris_orig};
305 const ReverseUVSampler reverse_uv_sampler_eval{uv_map_eval, corner_tris_eval};
310 const Span<float3> corner_normals_orig = surface_mesh_orig->corner_normals();
311 const Span<float3> corner_normals_eval = surface_mesh_eval->corner_normals();
313 std::atomic<int> invalid_uv_count = 0;
320 if (edit_hints !=
nullptr) {
322 edit_hint_positions = *positions;
326 float3x3::identity());
327 edit_hints->
deform_mats->fill(float3x3::identity());
332 if (edit_hint_positions.
is_empty()) {
337 reverse_uv_sampler_orig,
338 reverse_uv_sampler_eval,
342 transforms.surface_to_curves,
343 curves.positions_for_write(),
353 reverse_uv_sampler_orig,
354 reverse_uv_sampler_eval,
358 transforms.surface_to_curves,
359 curves.positions_for_write(),
365 "surface_uv_coordinate", AttrDomain::Curve,
float2(0));
366 if (!surface_uv_coords_orig.
is_empty()) {
370 surface_uv_coords_orig,
371 reverse_uv_sampler_orig,
372 reverse_uv_sampler_eval,
376 transforms.surface_to_curves,
383 curves.tag_positions_changed();
385 if (invalid_uv_count) {
386 const std::string message = fmt::format(
TIP_(
"Invalid surface UVs on {} curves"),
387 invalid_uv_count.load());
388 params.error_message_add(NodeWarningType::Warning, message);
391 params.set_output(
"Curves", curves_geometry);