45 const Mesh &surface_mesh_old,
46 const Mesh &surface_mesh_new,
56 std::atomic<int> &r_invalid_uv_count)
59 const int curves_num =
curves.curves_num();
64 [&]() { reverse_uv_sampler_old.
sample_many(curve_attachment_uvs, surface_samples_old); },
65 [&]() { reverse_uv_sampler_new.
sample_many(curve_attachment_uvs, surface_samples_new); });
70 for (const int curve_i : range) {
71 const ReverseUVSampler::Result &surface_sample_old = surface_samples_old[curve_i];
72 if (surface_sample_old.type != ReverseUVSampler::ResultType::Ok) {
76 const ReverseUVSampler::Result &surface_sample_new = surface_samples_new[curve_i];
77 if (surface_sample_new.type != ReverseUVSampler::ResultType::Ok) {
82 const MLoopTri &looptri_old = *surface_sample_old.looptri;
83 const MLoopTri &looptri_new = *surface_sample_new.looptri;
84 const float3 &bary_weights_old = surface_sample_old.bary_weights;
85 const float3 &bary_weights_new = surface_sample_new.bary_weights;
87 const int corner_0_old = looptri_old.tri[0];
88 const int corner_1_old = looptri_old.tri[1];
89 const int corner_2_old = looptri_old.tri[2];
91 const int corner_0_new = looptri_new.tri[0];
92 const int corner_1_new = looptri_new.tri[1];
93 const int corner_2_new = looptri_new.tri[2];
95 const int vert_0_old = surface_mesh_old.mloop[corner_0_old].v;
96 const int vert_1_old = surface_mesh_old.mloop[corner_1_old].v;
97 const int vert_2_old = surface_mesh_old.mloop[corner_2_old].v;
99 const int vert_0_new = surface_mesh_new.mloop[corner_0_new].v;
100 const int vert_1_new = surface_mesh_new.mloop[corner_1_new].v;
101 const int vert_2_new = surface_mesh_new.mloop[corner_2_new].v;
103 const float3 &normal_0_old = corner_normals_old[corner_0_old];
104 const float3 &normal_1_old = corner_normals_old[corner_1_old];
105 const float3 &normal_2_old = corner_normals_old[corner_2_old];
106 const float3 normal_old = math::normalize(
107 mix3(bary_weights_old, normal_0_old, normal_1_old, normal_2_old));
109 const float3 &normal_0_new = corner_normals_new[corner_0_new];
110 const float3 &normal_1_new = corner_normals_new[corner_1_new];
111 const float3 &normal_2_new = corner_normals_new[corner_2_new];
112 const float3 normal_new = math::normalize(
113 mix3(bary_weights_new, normal_0_new, normal_1_new, normal_2_new));
115 const float3 &pos_0_old = surface_mesh_old.mvert[vert_0_old].co;
116 const float3 &pos_1_old = surface_mesh_old.mvert[vert_1_old].co;
117 const float3 &pos_2_old = surface_mesh_old.mvert[vert_2_old].co;
118 const float3 pos_old = mix3(bary_weights_old, pos_0_old, pos_1_old, pos_2_old);
120 const float3 &pos_0_new = surface_mesh_new.mvert[vert_0_new].co;
121 const float3 &pos_1_new = surface_mesh_new.mvert[vert_1_new].co;
122 const float3 &pos_2_new = surface_mesh_new.mvert[vert_2_new].co;
123 const float3 pos_new = mix3(bary_weights_new, pos_0_new, pos_1_new, pos_2_new);
126 const float3 translation = pos_new - pos_old;
128 const float3 &rest_pos_0 = rest_positions[vert_0_new];
129 const float3 &rest_pos_1 = rest_positions[vert_1_new];
141 const float3 tangent_reference_dir_old = rest_pos_1 - rest_pos_0;
142 const float3 tangent_reference_dir_new = pos_1_new - pos_0_new;
146 const float3 tangent_x_old = math::normalize(
147 math::cross(normal_old, tangent_reference_dir_old));
148 const float3 tangent_x_new = math::normalize(
149 math::cross(normal_new, tangent_reference_dir_new));
152 const float3 tangent_y_old = math::normalize(math::cross(normal_old, tangent_x_old));
153 const float3 tangent_y_new = math::normalize(math::cross(normal_new, tangent_x_new));
156 float3x3 rotation_old;
157 copy_v3_v3(rotation_old.values[0], tangent_x_old);
158 copy_v3_v3(rotation_old.values[1], tangent_y_old);
159 copy_v3_v3(rotation_old.values[2], normal_old);
162 float3x3 rotation_new;
163 copy_v3_v3(rotation_new.values[0], tangent_x_new);
164 copy_v3_v3(rotation_new.values[1], tangent_y_new);
165 copy_v3_v3(rotation_new.values[2], normal_new);
170 const float3x3 rotation_old_inv = rotation_old.transposed();
174 const float3x3 rotation = rotation_new * rotation_old_inv;
175 float4x4 rotation_4x4;
176 copy_m4_m3(rotation_4x4.values, rotation.values);
180 float4x4 surface_transform = float4x4::identity();
182 sub_v3_v3(surface_transform.values[3], pos_old);
183 mul_m4_m4_pre(surface_transform.values, rotation_4x4.values);
184 add_v3_v3(surface_transform.values[3], pos_old);
185 add_v3_v3(surface_transform.values[3], translation);
189 const float4x4 curve_transform = surface_to_curves * surface_transform * curves_to_surface;
192 const IndexRange points = curves.points_for_curve(curve_i);
193 for (const int point_i : points) {
194 const float3 old_point_pos = r_positions[point_i];
195 const float3 new_point_pos = curve_transform * old_point_pos;
196 r_positions[point_i] = new_point_pos;
199 if (!r_rotations.is_empty()) {
200 for (const int point_i : points) {
201 r_rotations[point_i] = rotation * r_rotations[point_i];
212 Mesh *surface_mesh_orig =
nullptr;
213 bool free_suface_mesh_orig =
false;
215 if (free_suface_mesh_orig) {
220 auto pass_through_input = [&]() {
params.set_output(
"Curves", std::move(curves_geometry)); };
223 if (self_ob_eval ==
nullptr || self_ob_eval->
type !=
OB_CURVES) {
224 pass_through_input();
225 params.error_message_add(NodeWarningType::Error,
TIP_(
"Node only works for curves objects"));
228 const Curves *self_curves_eval =
static_cast<const Curves *
>(self_ob_eval->
data);
230 pass_through_input();
231 params.error_message_add(NodeWarningType::Error,
TIP_(
"Surface UV map not defined"));
240 pass_through_input();
243 if (surface_ob_eval ==
nullptr || surface_ob_eval->
type !=
OB_MESH) {
244 pass_through_input();
245 params.error_message_add(NodeWarningType::Error,
TIP_(
"Curves not attached to a surface"));
249 Mesh &surface_object_data = *
static_cast<Mesh *
>(surface_ob_orig->
data);
253 free_suface_mesh_orig =
true;
256 surface_mesh_orig = &surface_object_data;
259 if (surface_mesh_eval ==
nullptr) {
260 pass_through_input();
261 params.error_message_add(NodeWarningType::Error,
TIP_(
"Surface has no mesh"));
273 if (!mesh_attributes_eval.
contains(uv_map_name)) {
274 pass_through_input();
275 char *message =
BLI_sprintfN(
TIP_(
"Evaluated surface missing UV map: \"%s\""),
276 uv_map_name.
c_str());
277 params.error_message_add(NodeWarningType::Error, message);
281 if (!mesh_attributes_orig.
contains(uv_map_name)) {
282 pass_through_input();
283 char *message =
BLI_sprintfN(
TIP_(
"Original surface missing UV map: \"%s\""),
284 uv_map_name.
c_str());
285 params.error_message_add(NodeWarningType::Error, message);
289 if (!mesh_attributes_eval.
contains(rest_position_name)) {
290 pass_through_input();
291 params.error_message_add(NodeWarningType::Error,
292 TIP_(
"Evaluated surface missing attribute: \"rest_position\""));
295 if (
curves.surface_uv_coords().is_empty() &&
curves.curves_num() > 0) {
296 pass_through_input();
297 params.error_message_add(NodeWarningType::Error,
298 TIP_(
"Curves are not attached to any UV map"));
320 Array<float3> corner_normals_orig(surface_mesh_orig->totloop);
323 surface_mesh_orig,
nullptr,
reinterpret_cast<float(*)[3]
>(corner_normals_orig.
data()));
325 surface_mesh_eval,
nullptr,
reinterpret_cast<float(*)[3]
>(corner_normals_eval.
data()));
327 std::atomic<int> invalid_uv_count = 0;
334 if (edit_hints !=
nullptr) {
336 edit_hint_positions = *edit_hints->
positions;
340 float3x3::identity());
341 edit_hints->
deform_mats->fill(float3x3::identity());
346 if (edit_hint_positions.
is_empty()) {
351 reverse_uv_sampler_orig,
352 reverse_uv_sampler_eval,
356 transforms.surface_to_curves,
357 curves.positions_for_write(),
367 reverse_uv_sampler_orig,
368 reverse_uv_sampler_eval,
372 transforms.surface_to_curves,
373 curves.positions_for_write(),
382 reverse_uv_sampler_orig,
383 reverse_uv_sampler_eval,
387 transforms.surface_to_curves,
393 curves.tag_positions_changed();
395 if (invalid_uv_count) {
397 invalid_uv_count.load());
398 params.error_message_add(NodeWarningType::Warning, message);
402 params.set_output(
"Curves", curves_geometry);
Low-level operations for curves.
@ GEO_COMPONENT_TYPE_CURVE
void BKE_id_free(struct Main *bmain, void *idv)
struct Mesh * BKE_mesh_from_bmesh_for_eval_nomain(struct BMesh *bm, const struct CustomData_MeshMasks *cd_mask_extra, const struct Mesh *me_settings)
void BKE_mesh_calc_normals_split_ex(struct Mesh *mesh, struct MLoopNorSpaceArray *r_lnors_spacearr, float(*r_corner_normals)[3])
const struct MLoopTri * BKE_mesh_runtime_looptri_ensure(const struct Mesh *mesh)
int BKE_mesh_runtime_looptri_len(const struct Mesh *mesh)
void BKE_mesh_wrapper_ensure_mdata(struct Mesh *me)
struct Mesh * BKE_modifier_get_evaluated_mesh_from_evaluated_object(struct Object *ob_eval)
void node_type_size(struct bNodeType *ntype, int width, int minwidth, int maxwidth)
#define GEO_NODE_DEFORM_CURVES_ON_SURFACE
#define NODE_STORAGE_FUNCS(StorageT)
#define NODE_CLASS_GEOMETRY
void nodeRegisterType(struct bNodeType *ntype)
#define BLI_SCOPED_DEFER(function_to_defer)
size_t size_t char * BLI_sprintfN(const char *__restrict format,...) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_PRINTF_FORMAT(1
struct Object * DEG_get_original_object(struct Object *object)
struct CurvesGeometry CurvesGeometry
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to curves
constexpr bool is_empty() const
constexpr const char * c_str() const
bool contains(const AttributeIDRef &attribute_id) const
GAttributeReader lookup(const AttributeIDRef &attribute_id) const
const Curves & curves_id_orig
std::optional< Array< float3 > > positions
std::optional< Array< float3x3 > > deform_mats
void sample_many(Span< float2 > query_uvs, MutableSpan< Result > r_results) const
void(* MEM_freeN)(void *vmemh)
T mix3(const float3 &weights, const T &v0, const T &v1, const T &v2)
static struct PartialUpdateUser * wrap(PartialUpdateUserImpl *user)
AttributeAccessor mesh_attributes(const Mesh &mesh)
void parallel_for(IndexRange range, int64_t grain_size, const Function &function)
void parallel_invoke(Functions &&...functions)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
void geo_node_type_base(bNodeType *ntype, int type, const char *name, short nclass)
Curves * get_curves_for_write()
blender::bke::CurvesEditHints * get_curve_edit_hints_for_write()
struct BMEditMesh * edit_mesh
NodeGeometryExecFunction geometry_node_execute
NodeDeclareFunction declare
float4x4 inverted() const