41 const Mesh &surface_mesh_old,
42 const Mesh &surface_mesh_new,
52 std::atomic<int> &r_invalid_uv_count)
60 [&]() { reverse_uv_sampler_old.
sample_many(curve_attachment_uvs, surface_samples_old); },
61 [&]() { reverse_uv_sampler_new.
sample_many(curve_attachment_uvs, surface_samples_new); });
65 const Span<float3> surface_positions_old = surface_mesh_old.vert_positions();
66 const Span<int> surface_corner_verts_old = surface_mesh_old.corner_verts();
67 const Span<int3> surface_corner_tris_old = surface_mesh_old.corner_tris();
69 const Span<float3> surface_positions_new = surface_mesh_new.vert_positions();
70 const Span<int> surface_corner_verts_new = surface_mesh_new.corner_verts();
71 const Span<int3> surface_corner_tris_new = surface_mesh_new.corner_tris();
76 for (const int curve_i : range) {
77 const ReverseUVSampler::Result &surface_sample_old = surface_samples_old[curve_i];
78 if (surface_sample_old.type != ReverseUVSampler::ResultType::Ok) {
82 const ReverseUVSampler::Result &surface_sample_new = surface_samples_new[curve_i];
83 if (surface_sample_new.type != ReverseUVSampler::ResultType::Ok) {
88 const int3 &tri_old = surface_corner_tris_old[surface_sample_old.tri_index];
89 const int3 &tri_new = surface_corner_tris_new[surface_sample_new.tri_index];
90 const float3 &bary_weights_old = surface_sample_old.bary_weights;
91 const float3 &bary_weights_new = surface_sample_new.bary_weights;
93 const int corner_0_old = tri_old[0];
94 const int corner_1_old = tri_old[1];
95 const int corner_2_old = tri_old[2];
97 const int corner_0_new = tri_new[0];
98 const int corner_1_new = tri_new[1];
99 const int corner_2_new = tri_new[2];
101 const int vert_0_old = surface_corner_verts_old[corner_0_old];
102 const int vert_1_old = surface_corner_verts_old[corner_1_old];
103 const int vert_2_old = surface_corner_verts_old[corner_2_old];
105 const int vert_0_new = surface_corner_verts_new[corner_0_new];
106 const int vert_1_new = surface_corner_verts_new[corner_1_new];
107 const int vert_2_new = surface_corner_verts_new[corner_2_new];
109 const float3 &normal_0_old = corner_normals_old[corner_0_old];
110 const float3 &normal_1_old = corner_normals_old[corner_1_old];
111 const float3 &normal_2_old = corner_normals_old[corner_2_old];
112 const float3 normal_old = math::normalize(
113 mix3(bary_weights_old, normal_0_old, normal_1_old, normal_2_old));
115 const float3 &normal_0_new = corner_normals_new[corner_0_new];
116 const float3 &normal_1_new = corner_normals_new[corner_1_new];
117 const float3 &normal_2_new = corner_normals_new[corner_2_new];
118 const float3 normal_new = math::normalize(
119 mix3(bary_weights_new, normal_0_new, normal_1_new, normal_2_new));
121 const float3 &pos_0_old = surface_positions_old[vert_0_old];
122 const float3 &pos_1_old = surface_positions_old[vert_1_old];
123 const float3 &pos_2_old = surface_positions_old[vert_2_old];
124 const float3 pos_old = mix3(bary_weights_old, pos_0_old, pos_1_old, pos_2_old);
126 const float3 &pos_0_new = surface_positions_new[vert_0_new];
127 const float3 &pos_1_new = surface_positions_new[vert_1_new];
128 const float3 &pos_2_new = surface_positions_new[vert_2_new];
129 const float3 pos_new = mix3(bary_weights_new, pos_0_new, pos_1_new, pos_2_new);
132 const float3 translation = pos_new - pos_old;
134 const float3 &rest_pos_0 = rest_positions[vert_0_new];
135 const float3 &rest_pos_1 = rest_positions[vert_1_new];
147 const float3 tangent_reference_dir_old = rest_pos_1 - rest_pos_0;
148 const float3 tangent_reference_dir_new = pos_1_new - pos_0_new;
152 const float3 tangent_x_old = math::normalize(
153 math::cross(normal_old, tangent_reference_dir_old));
154 const float3 tangent_x_new = math::normalize(
155 math::cross(normal_new, tangent_reference_dir_new));
158 const float3 tangent_y_old = math::normalize(math::cross(normal_old, tangent_x_old));
159 const float3 tangent_y_new = math::normalize(math::cross(normal_new, tangent_x_new));
162 float3x3 rotation_old(tangent_x_old, tangent_y_old, normal_old);
165 float3x3 rotation_new(tangent_x_new, tangent_y_new, normal_new);
170 const float3x3 rotation_old_inv = math::transpose(rotation_old);
174 const float3x3 rotation = rotation_new * rotation_old_inv;
179 float4x4 surface_transform = math::from_origin_transform<float4x4>(float4x4(rotation),
181 surface_transform.location() += translation;
185 const float4x4 curve_transform = surface_to_curves * surface_transform * curves_to_surface;
188 const IndexRange points = points_by_curve[curve_i];
189 for (const int point_i : points) {
190 const float3 old_point_pos = r_positions[point_i];
191 const float3 new_point_pos = math::transform_point(curve_transform, old_point_pos);
192 r_positions[point_i] = new_point_pos;
195 if (!r_rotations.is_empty()) {
196 for (const int point_i : points) {
197 r_rotations[point_i] = rotation * r_rotations[point_i];
208 Mesh *surface_mesh_orig =
nullptr;
209 bool free_suface_mesh_orig =
false;
211 if (free_suface_mesh_orig) {
216 auto pass_through_input = [&]() {
params.set_output(
"Curves", std::move(curves_geometry)); };
219 if (self_ob_eval ==
nullptr || self_ob_eval->
type !=
OB_CURVES) {
220 pass_through_input();
224 const Curves *self_curves_eval =
static_cast<const Curves *
>(self_ob_eval->
data);
226 pass_through_input();
236 pass_through_input();
239 if (surface_ob_eval ==
nullptr || surface_ob_eval->
type !=
OB_MESH) {
240 pass_through_input();
245 Mesh &surface_object_data = *
static_cast<Mesh *
>(surface_ob_orig->
data);
249 free_suface_mesh_orig =
true;
252 surface_mesh_orig = &surface_object_data;
255 if (surface_mesh_eval ==
nullptr) {
256 pass_through_input();
269 if (!mesh_attributes_eval.
contains(uv_map_name)) {
270 pass_through_input();
271 const std::string message = fmt::format(
272 fmt::runtime(
TIP_(
"Evaluated surface missing UV map: \"{}\"")), uv_map_name);
276 if (!mesh_attributes_orig.
contains(uv_map_name)) {
277 pass_through_input();
278 const std::string message = fmt::format(
279 fmt::runtime(
TIP_(
"Original surface missing UV map: \"{}\"")), uv_map_name);
283 if (!mesh_attributes_eval.
contains(rest_position_name)) {
284 pass_through_input();
286 TIP_(
"Evaluated surface missing attribute: \"rest_position\""));
290 pass_through_input();
292 TIP_(
"Curves are not attached to any UV map"));
302 "surface_uv_coordinate", AttrDomain::Curve,
float2(0));
304 const Span<int3> corner_tris_orig = surface_mesh_orig->corner_tris();
305 const Span<int3> corner_tris_eval = surface_mesh_eval->corner_tris();
306 const ReverseUVSampler reverse_uv_sampler_orig{uv_map_orig, corner_tris_orig};
307 const ReverseUVSampler reverse_uv_sampler_eval{uv_map_eval, corner_tris_eval};
312 const Span<float3> corner_normals_orig = surface_mesh_orig->corner_normals();
313 const Span<float3> corner_normals_eval = surface_mesh_eval->corner_normals();
315 std::atomic<int> invalid_uv_count = 0;
322 if (edit_hints !=
nullptr) {
324 edit_hint_positions = *positions;
334 if (edit_hint_positions.
is_empty()) {
339 reverse_uv_sampler_orig,
340 reverse_uv_sampler_eval,
355 reverse_uv_sampler_orig,
356 reverse_uv_sampler_eval,
367 "surface_uv_coordinate", AttrDomain::Curve,
float2(0));
368 if (!surface_uv_coords_orig.
is_empty()) {
372 surface_uv_coords_orig,
373 reverse_uv_sampler_orig,
374 reverse_uv_sampler_eval,
387 if (invalid_uv_count) {
388 const std::string message = fmt::format(fmt::runtime(
TIP_(
"Invalid surface UVs on {} curves")),
389 invalid_uv_count.load());
393 params.set_output(
"Curves", curves_geometry);