43 const Mesh &surface_mesh_old,
44 const Mesh &surface_mesh_new,
54 std::atomic<int> &r_invalid_uv_count)
62 [&]() { reverse_uv_sampler_old.
sample_many(curve_attachment_uvs, surface_samples_old); },
63 [&]() { reverse_uv_sampler_new.
sample_many(curve_attachment_uvs, surface_samples_new); });
67 const Span<float3> surface_positions_old = surface_mesh_old.vert_positions();
68 const Span<int> surface_corner_verts_old = surface_mesh_old.corner_verts();
69 const Span<int3> surface_corner_tris_old = surface_mesh_old.corner_tris();
71 const Span<float3> surface_positions_new = surface_mesh_new.vert_positions();
72 const Span<int> surface_corner_verts_new = surface_mesh_new.corner_verts();
73 const Span<int3> surface_corner_tris_new = surface_mesh_new.corner_tris();
78 for (const int curve_i : range) {
79 const ReverseUVSampler::Result &surface_sample_old = surface_samples_old[curve_i];
80 if (surface_sample_old.type != ReverseUVSampler::ResultType::Ok) {
84 const ReverseUVSampler::Result &surface_sample_new = surface_samples_new[curve_i];
85 if (surface_sample_new.type != ReverseUVSampler::ResultType::Ok) {
90 const int3 &tri_old = surface_corner_tris_old[surface_sample_old.tri_index];
91 const int3 &tri_new = surface_corner_tris_new[surface_sample_new.tri_index];
92 const float3 &bary_weights_old = surface_sample_old.bary_weights;
93 const float3 &bary_weights_new = surface_sample_new.bary_weights;
95 const int corner_0_old = tri_old[0];
96 const int corner_1_old = tri_old[1];
97 const int corner_2_old = tri_old[2];
99 const int corner_0_new = tri_new[0];
100 const int corner_1_new = tri_new[1];
101 const int corner_2_new = tri_new[2];
103 const int vert_0_old = surface_corner_verts_old[corner_0_old];
104 const int vert_1_old = surface_corner_verts_old[corner_1_old];
105 const int vert_2_old = surface_corner_verts_old[corner_2_old];
107 const int vert_0_new = surface_corner_verts_new[corner_0_new];
108 const int vert_1_new = surface_corner_verts_new[corner_1_new];
109 const int vert_2_new = surface_corner_verts_new[corner_2_new];
111 const float3 &normal_0_old = corner_normals_old[corner_0_old];
112 const float3 &normal_1_old = corner_normals_old[corner_1_old];
113 const float3 &normal_2_old = corner_normals_old[corner_2_old];
114 const float3 normal_old = math::normalize(
115 mix3(bary_weights_old, normal_0_old, normal_1_old, normal_2_old));
117 const float3 &normal_0_new = corner_normals_new[corner_0_new];
118 const float3 &normal_1_new = corner_normals_new[corner_1_new];
119 const float3 &normal_2_new = corner_normals_new[corner_2_new];
120 const float3 normal_new = math::normalize(
121 mix3(bary_weights_new, normal_0_new, normal_1_new, normal_2_new));
123 const float3 &pos_0_old = surface_positions_old[vert_0_old];
124 const float3 &pos_1_old = surface_positions_old[vert_1_old];
125 const float3 &pos_2_old = surface_positions_old[vert_2_old];
126 const float3 pos_old = mix3(bary_weights_old, pos_0_old, pos_1_old, pos_2_old);
128 const float3 &pos_0_new = surface_positions_new[vert_0_new];
129 const float3 &pos_1_new = surface_positions_new[vert_1_new];
130 const float3 &pos_2_new = surface_positions_new[vert_2_new];
131 const float3 pos_new = mix3(bary_weights_new, pos_0_new, pos_1_new, pos_2_new);
134 const float3 translation = pos_new - pos_old;
136 const float3 &rest_pos_0 = rest_positions[vert_0_new];
137 const float3 &rest_pos_1 = rest_positions[vert_1_new];
149 const float3 tangent_reference_dir_old = rest_pos_1 - rest_pos_0;
150 const float3 tangent_reference_dir_new = pos_1_new - pos_0_new;
154 const float3 tangent_x_old = math::normalize(
155 math::cross(normal_old, tangent_reference_dir_old));
156 const float3 tangent_x_new = math::normalize(
157 math::cross(normal_new, tangent_reference_dir_new));
160 const float3 tangent_y_old = math::normalize(math::cross(normal_old, tangent_x_old));
161 const float3 tangent_y_new = math::normalize(math::cross(normal_new, tangent_x_new));
164 float3x3 rotation_old(tangent_x_old, tangent_y_old, normal_old);
167 float3x3 rotation_new(tangent_x_new, tangent_y_new, normal_new);
172 const float3x3 rotation_old_inv = math::transpose(rotation_old);
176 const float3x3 rotation = rotation_new * rotation_old_inv;
181 float4x4 surface_transform = math::from_origin_transform<float4x4>(float4x4(rotation),
183 surface_transform.location() += translation;
187 const float4x4 curve_transform = surface_to_curves * surface_transform * curves_to_surface;
190 const IndexRange points = points_by_curve[curve_i];
191 for (const int point_i : points) {
192 const float3 old_point_pos = r_positions[point_i];
193 const float3 new_point_pos = math::transform_point(curve_transform, old_point_pos);
194 r_positions[point_i] = new_point_pos;
197 if (!r_rotations.is_empty()) {
198 for (const int point_i : points) {
199 r_rotations[point_i] = rotation * r_rotations[point_i];
210 Mesh *surface_mesh_orig =
nullptr;
211 bool free_suface_mesh_orig =
false;
213 if (free_suface_mesh_orig) {
218 auto pass_through_input = [&]() {
params.set_output(
"Curves", std::move(curves_geometry)); };
221 if (self_ob_eval ==
nullptr || self_ob_eval->
type !=
OB_CURVES) {
222 pass_through_input();
226 const Curves *self_curves_eval =
static_cast<const Curves *
>(self_ob_eval->
data);
228 pass_through_input();
238 pass_through_input();
241 if (surface_ob_eval ==
nullptr || surface_ob_eval->
type !=
OB_MESH) {
242 pass_through_input();
247 Mesh &surface_object_data = *
static_cast<Mesh *
>(surface_ob_orig->
data);
251 free_suface_mesh_orig =
true;
254 surface_mesh_orig = &surface_object_data;
257 if (surface_mesh_eval ==
nullptr) {
258 pass_through_input();
271 if (!mesh_attributes_eval.
contains(uv_map_name)) {
272 pass_through_input();
273 const std::string message = fmt::format(
274 fmt::runtime(
TIP_(
"Evaluated surface missing UV map: \"{}\"")), uv_map_name);
278 if (!mesh_attributes_orig.
contains(uv_map_name)) {
279 pass_through_input();
280 const std::string message = fmt::format(
281 fmt::runtime(
TIP_(
"Original surface missing UV map: \"{}\"")), uv_map_name);
285 if (!mesh_attributes_eval.
contains(rest_position_name)) {
286 pass_through_input();
288 TIP_(
"Evaluated surface missing attribute: \"rest_position\""));
292 pass_through_input();
294 TIP_(
"Curves are not attached to any UV map"));
304 "surface_uv_coordinate", AttrDomain::Curve,
float2(0));
306 const Span<int3> corner_tris_orig = surface_mesh_orig->corner_tris();
307 const Span<int3> corner_tris_eval = surface_mesh_eval->corner_tris();
308 const ReverseUVSampler reverse_uv_sampler_orig{uv_map_orig, corner_tris_orig};
309 const ReverseUVSampler reverse_uv_sampler_eval{uv_map_eval, corner_tris_eval};
314 const Span<float3> corner_normals_orig = surface_mesh_orig->corner_normals();
315 const Span<float3> corner_normals_eval = surface_mesh_eval->corner_normals();
317 std::atomic<int> invalid_uv_count = 0;
324 if (edit_hints !=
nullptr) {
326 edit_hint_positions = *positions;
336 if (edit_hint_positions.
is_empty()) {
341 reverse_uv_sampler_orig,
342 reverse_uv_sampler_eval,
357 reverse_uv_sampler_orig,
358 reverse_uv_sampler_eval,
369 "surface_uv_coordinate", AttrDomain::Curve,
float2(0));
370 if (!surface_uv_coords_orig.
is_empty()) {
374 surface_uv_coords_orig,
375 reverse_uv_sampler_orig,
376 reverse_uv_sampler_eval,
389 if (invalid_uv_count) {
390 const std::string message = fmt::format(fmt::runtime(
TIP_(
"Invalid surface UVs on {} curves")),
391 invalid_uv_count.load());
395 params.set_output(
"Curves", curves_geometry);