Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacques Lucke <jacques@blender.org>2022-06-22 13:40:40 +0300
committerJacques Lucke <jacques@blender.org>2022-06-22 13:40:40 +0300
commit8100721dab8ad2c66762dad7332b359b3ae26210 (patch)
treebfbe2ac94ebc4cdc95f33d1dc872d09f6ca5c984
parent2d0dc88209e166159bd0b68dc54103280b09193c (diff)
support translation
-rw-r--r--release/scripts/startup/nodeitems_builtins.py2
-rw-r--r--source/blender/blenkernel/BKE_node.h2
-rw-r--r--source/blender/blenkernel/intern/node.cc2
-rw-r--r--source/blender/nodes/NOD_geometry.h2
-rw-r--r--source/blender/nodes/NOD_static_types.h2
-rw-r--r--source/blender/nodes/geometry/CMakeLists.txt2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_deform_curves_with_surface.cc168
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_sample_mesh_deformation.cc200
8 files changed, 206 insertions, 174 deletions
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index f4acc71a6da..1187927a9e8 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -80,7 +80,6 @@ def curve_node_items(context):
yield NodeItem("GeometryNodeSampleCurve")
yield NodeItem("GeometryNodeSubdivideCurve")
yield NodeItem("GeometryNodeTrimCurve")
- yield NodeItem("GeometryNodeDeformCurvesWithSurface")
yield NodeItemCustom(draw=lambda self, layout, context: layout.separator())
yield NodeItem("GeometryNodeInputCurveHandlePositions")
yield NodeItem("GeometryNodeInputTangent")
@@ -114,6 +113,7 @@ def mesh_node_items(context):
yield NodeItem("GeometryNodeMeshBoolean")
yield NodeItem("GeometryNodeMeshToCurve")
yield NodeItem("GeometryNodeMeshToPoints")
+ yield NodeItem("GeometryNodeSampleMeshDeformation")
yield NodeItem("GeometryNodeSplitEdges")
yield NodeItem("GeometryNodeSubdivideMesh")
yield NodeItem("GeometryNodeSubdivisionSurface")
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 5917f9b88d7..e6bea7b23fe 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -1496,7 +1496,7 @@ struct TexResult;
#define GEO_NODE_INPUT_INSTANCE_ROTATION 1159
#define GEO_NODE_INPUT_INSTANCE_SCALE 1160
#define GEO_NODE_VOLUME_CUBE 1161
-#define GEO_NODE_DEFORM_CURVES_WITH_SURFACE 1162
+#define GEO_NODE_SAMPLE_MESH_DEFORMATION 1162
/** \} */
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index d4d14ca45be..7b7ad3fe4b4 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -4749,7 +4749,6 @@ static void registerGeometryNodes()
register_node_type_geo_curve_to_mesh();
register_node_type_geo_curve_to_points();
register_node_type_geo_curve_trim();
- register_node_type_geo_deform_curves_with_surface();
register_node_type_geo_delete_geometry();
register_node_type_geo_duplicate_elements();
register_node_type_geo_distribute_points_on_faces();
@@ -4812,6 +4811,7 @@ static void registerGeometryNodes()
register_node_type_geo_realize_instances();
register_node_type_geo_remove_attribute();
register_node_type_geo_rotate_instances();
+ register_node_type_geo_sample_mesh_deformation();
register_node_type_geo_scale_elements();
register_node_type_geo_scale_instances();
register_node_type_geo_separate_components();
diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h
index b9da2b17319..f0856e3b44a 100644
--- a/source/blender/nodes/NOD_geometry.h
+++ b/source/blender/nodes/NOD_geometry.h
@@ -47,7 +47,6 @@ void register_node_type_geo_curve_subdivide(void);
void register_node_type_geo_curve_to_mesh(void);
void register_node_type_geo_curve_to_points(void);
void register_node_type_geo_curve_trim(void);
-void register_node_type_geo_deform_curves_with_surface(void);
void register_node_type_geo_delete_geometry(void);
void register_node_type_geo_duplicate_elements(void);
void register_node_type_geo_distribute_points_on_faces(void);
@@ -110,6 +109,7 @@ void register_node_type_geo_raycast(void);
void register_node_type_geo_realize_instances(void);
void register_node_type_geo_remove_attribute(void);
void register_node_type_geo_rotate_instances(void);
+void register_node_type_geo_sample_mesh_deformation(void);
void register_node_type_geo_scale_elements(void);
void register_node_type_geo_scale_instances(void);
void register_node_type_geo_select_by_handle_type(void);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index 54336ac65d0..ac78b75fe99 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -399,7 +399,7 @@ DefNode(GeometryNode, GEO_NODE_TRIM_CURVE, def_geo_curve_trim, "TRIM_CURVE", Tri
DefNode(GeometryNode, GEO_NODE_VIEWER, def_geo_viewer, "VIEWER", Viewer, "Viewer", "")
DefNode(GeometryNode, GEO_NODE_VOLUME_CUBE, 0, "VOLUME_CUBE", VolumeCube, "Volume Cube", "")
DefNode(GeometryNode, GEO_NODE_VOLUME_TO_MESH, def_geo_volume_to_mesh, "VOLUME_TO_MESH", VolumeToMesh, "Volume to Mesh", "")
-DefNode(GeometryNode, GEO_NODE_DEFORM_CURVES_WITH_SURFACE, 0, "DEFORM_CURVES_WITH_SURFACE", DeformCurvesWithSurface, "Deform Curves with Surface", "")
+DefNode(GeometryNode, GEO_NODE_SAMPLE_MESH_DEFORMATION, 0, "SAMPLE_MESH_DEFORMATION", SampleMeshDeformation, "Sample Mesh Deformation", "")
/* undefine macros */
#undef DefNode
diff --git a/source/blender/nodes/geometry/CMakeLists.txt b/source/blender/nodes/geometry/CMakeLists.txt
index fba13db0a49..02db28fd9d2 100644
--- a/source/blender/nodes/geometry/CMakeLists.txt
+++ b/source/blender/nodes/geometry/CMakeLists.txt
@@ -57,7 +57,6 @@ set(SRC
nodes/node_geo_curve_to_mesh.cc
nodes/node_geo_curve_to_points.cc
nodes/node_geo_curve_trim.cc
- nodes/node_geo_deform_curves_with_surface.cc
nodes/node_geo_delete_geometry.cc
nodes/node_geo_distribute_points_on_faces.cc
nodes/node_geo_dual_mesh.cc
@@ -120,6 +119,7 @@ set(SRC
nodes/node_geo_realize_instances.cc
nodes/node_geo_remove_attribute.cc
nodes/node_geo_rotate_instances.cc
+ nodes/node_geo_sample_mesh_deformation.cc
nodes/node_geo_scale_elements.cc
nodes/node_geo_scale_instances.cc
nodes/node_geo_separate_components.cc
diff --git a/source/blender/nodes/geometry/nodes/node_geo_deform_curves_with_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_deform_curves_with_surface.cc
deleted file mode 100644
index b3c7ec8fb9c..00000000000
--- a/source/blender/nodes/geometry/nodes/node_geo_deform_curves_with_surface.cc
+++ /dev/null
@@ -1,168 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-
-#include "BKE_curves.hh"
-#include "BKE_mesh_runtime.h"
-#include "BKE_spline.hh"
-
-#include "BLI_task.hh"
-
-#include "UI_interface.h"
-#include "UI_resources.h"
-
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-
-#include "NOD_socket_search_link.hh"
-
-#include "node_geometry_util.hh"
-
-namespace blender::nodes::node_geo_deform_curves_with_surface_cc {
-
-using blender::attribute_math::mix2;
-
-NODE_STORAGE_FUNCS(NodeGeometryCurveTrim)
-
-static void node_declare(NodeDeclarationBuilder &b)
-{
- b.add_input<decl::Geometry>(N_("Curves")).supported_type(GEO_COMPONENT_TYPE_CURVE);
- b.add_input<decl::Geometry>(N_("Mesh")).supported_type(GEO_COMPONENT_TYPE_MESH);
- b.add_input<decl::Vector>(N_("Rest Position")).hide_value().supports_field();
- b.add_output<decl::Geometry>(N_("Curves"));
-}
-
-static void node_layout(uiLayout *UNUSED(layout), bContext *UNUSED(C), PointerRNA *UNUSED(ptr))
-{
-}
-
-static void node_init(bNodeTree *UNUSED(tree), bNode *UNUSED(node))
-{
-}
-
-static void node_update(bNodeTree *UNUSED(ntree), bNode *UNUSED(node))
-{
-}
-
-static void deform_curves(const MeshComponent &mesh_component,
- const Span<float3> rest_positions,
- CurveComponent &curves_component)
-{
- bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(
- curves_component.get_for_write()->geometry);
-
- const MutableSpan<float3> positions = curves.positions_for_write();
- const VArray<int> surface_triangle_indices_varray = curves.surface_triangle_indices();
- if (surface_triangle_indices_varray.is_single() &&
- surface_triangle_indices_varray.get_internal_single() < 0) {
- return;
- }
- const VArray_Span<int> surface_triangle_indices{surface_triangle_indices_varray};
- const Span<float2> surface_triangle_coordinates = curves.surface_triangle_coords();
- if (surface_triangle_coordinates.is_empty()) {
- return;
- }
-
- const Mesh &mesh = *mesh_component.get_for_read();
- const Span<MLoopTri> looptris{BKE_mesh_runtime_looptri_ensure(&mesh),
- BKE_mesh_runtime_looptri_len(&mesh)};
-
- threading::parallel_for(curves.curves_range(), 512, [&](const IndexRange curves_range) {
- for (const int curve_i : curves_range) {
- const int looptri_i = surface_triangle_indices[curve_i];
- if (looptri_i < 0 || looptri_i >= looptris.size()) {
- continue;
- }
- const IndexRange points = curves.points_for_curve(curve_i);
- const int root_point_i = points[0];
-
- const float3 bary_coord = bke::curves::decode_surface_bary_coord(
- surface_triangle_coordinates[curve_i]);
- const MLoopTri &looptri = looptris[looptri_i];
- const int v0 = mesh.mloop[looptri.tri[0]].v;
- const int v1 = mesh.mloop[looptri.tri[1]].v;
- const int v2 = mesh.mloop[looptri.tri[2]].v;
-
- const float3 &rest_v0 = rest_positions[v0];
- const float3 &rest_v1 = rest_positions[v1];
- const float3 &rest_v2 = rest_positions[v2];
-
- const float3 &deformed_v0 = mesh.mvert[v0].co;
- const float3 &deformed_v1 = mesh.mvert[v1].co;
- const float3 &deformed_v2 = mesh.mvert[v2].co;
-
- float3 old_normal;
- normal_tri_v3(old_normal, rest_v0, rest_v1, rest_v2);
- float3 new_normal;
- normal_tri_v3(new_normal, deformed_v0, deformed_v1, deformed_v2);
-
- /* TODO: Take tangend axis into account as well. */
- float rotation_mat[3][3];
- rotation_between_vecs_to_mat3(rotation_mat, old_normal, new_normal);
-
- const float3 old_curve_root = positions[root_point_i];
- const float3 old_surface_pos = attribute_math::mix3(bary_coord, rest_v0, rest_v1, rest_v2);
- const float3 new_surface_pos = attribute_math::mix3(
- bary_coord, deformed_v0, deformed_v1, deformed_v2);
- const float3 root_pos_diff = new_surface_pos - old_surface_pos;
-
- for (const int point_i : points) {
- const float3 old_pos = positions[point_i];
- const float3 old_relative_pos = old_pos - old_surface_pos;
- float3 new_relative_pos = old_relative_pos;
- mul_m3_v3(rotation_mat, new_relative_pos);
- const float3 new_pos = new_surface_pos + new_relative_pos;
- positions[point_i] = new_pos;
- }
- }
- });
-
- curves.tag_positions_changed();
-}
-
-static void node_geo_exec(GeoNodeExecParams params)
-{
- GeometrySet curves_geometry = params.extract_input<GeometrySet>("Curves");
- GeometrySet mesh_geometry = params.extract_input<GeometrySet>("Mesh");
- Field<float3> rest_positions_field = params.extract_input<Field<float3>>("Rest Position");
-
- if (!mesh_geometry.has_mesh()) {
- params.set_output("Curves", std::move(curves_geometry));
- return;
- }
-
- const MeshComponent &mesh_component = *mesh_geometry.get_component_for_read<MeshComponent>();
- GeometryComponentFieldContext field_context{mesh_component, ATTR_DOMAIN_POINT};
- FieldEvaluator field_evaluator{field_context,
- mesh_component.attribute_domain_size(ATTR_DOMAIN_POINT)};
- field_evaluator.add(rest_positions_field);
- field_evaluator.evaluate();
- const VArray_Span<float3> rest_positions = field_evaluator.get_evaluated<float3>(0);
-
- curves_geometry.modify_geometry_sets([&](GeometrySet &curve_geometry) {
- if (!curve_geometry.has_curves()) {
- return;
- }
- CurveComponent &curves_component = curves_geometry.get_component_for_write<CurveComponent>();
- deform_curves(mesh_component, rest_positions, curves_component);
- });
-
- params.set_output("Curves", std::move(curves_geometry));
-}
-
-} // namespace blender::nodes::node_geo_deform_curves_with_surface_cc
-
-void register_node_type_geo_deform_curves_with_surface()
-{
- namespace file_ns = blender::nodes::node_geo_deform_curves_with_surface_cc;
-
- static bNodeType ntype;
- geo_node_type_base(&ntype,
- GEO_NODE_DEFORM_CURVES_WITH_SURFACE,
- "Deform Curves with Surface",
- NODE_CLASS_GEOMETRY);
- ntype.geometry_node_execute = file_ns::node_geo_exec;
- ntype.draw_buttons = file_ns::node_layout;
- ntype.declare = file_ns::node_declare;
- node_type_init(&ntype, file_ns::node_init);
- node_type_update(&ntype, file_ns::node_update);
- nodeRegisterType(&ntype);
-}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_sample_mesh_deformation.cc b/source/blender/nodes/geometry/nodes/node_geo_sample_mesh_deformation.cc
new file mode 100644
index 00000000000..ad39e77a810
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_sample_mesh_deformation.cc
@@ -0,0 +1,200 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "BKE_attribute_math.hh"
+#include "BKE_curves.hh"
+#include "BKE_mesh_runtime.h"
+#include "BKE_type_conversions.hh"
+
+#include "BLI_task.hh"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "NOD_socket_search_link.hh"
+
+#include "GEO_reverse_uv_sampler.hh"
+
+#include "node_geometry_util.hh"
+
+namespace blender::nodes::node_geo_sample_mesh_deformation_cc {
+
+using attribute_math::mix3;
+using geometry::ReverseUVSampler;
+
+NODE_STORAGE_FUNCS(NodeGeometryCurveTrim)
+
+static void node_declare(NodeDeclarationBuilder &b)
+{
+ b.add_input<decl::Geometry>(N_("Mesh")).supported_type(GEO_COMPONENT_TYPE_MESH);
+ b.add_input<decl::Vector>(N_("Rest Position")).hide_value().supports_field();
+ b.add_input<decl::Vector>(N_("UV Map")).hide_value().supports_field();
+ b.add_input<decl::Vector>(N_("Sample UV")).supports_field();
+ b.add_output<decl::Vector>(N_("Translation")).dependent_field({3});
+ b.add_output<decl::Vector>(N_("Rotation")).dependent_field({3});
+}
+
+static void node_layout(uiLayout *UNUSED(layout), bContext *UNUSED(C), PointerRNA *UNUSED(ptr))
+{
+}
+
+static void node_init(bNodeTree *UNUSED(tree), bNode *UNUSED(node))
+{
+}
+
+static void node_update(bNodeTree *UNUSED(ntree), bNode *UNUSED(node))
+{
+}
+
+class SampleMeshDeformationFunction : public fn::MultiFunction {
+ private:
+ GeometrySet geometry_;
+ const Mesh *mesh_;
+ Span<MVert> verts_;
+ Array<float3> rest_positions_;
+ Array<float2> uv_map_;
+ std::optional<ReverseUVSampler> reverse_uv_sampler;
+
+ public:
+ SampleMeshDeformationFunction(GeometrySet geometry,
+ VArray<float3> rest_positions,
+ VArray<float2> uv_map)
+ : geometry_(std::move(geometry)),
+ rest_positions_(VArray_Span(rest_positions)),
+ uv_map_(VArray_Span(uv_map))
+ {
+ mesh_ = geometry_.get_mesh_for_read();
+ verts_ = Span<MVert>(mesh_->mvert, mesh_->totvert);
+ const Span<MLoopTri> looptris{BKE_mesh_runtime_looptri_ensure(mesh_),
+ BKE_mesh_runtime_looptri_len(mesh_)};
+ reverse_uv_sampler.emplace(uv_map_, looptris);
+
+ static fn::MFSignature signature = create_signature();
+ this->set_signature(&signature);
+ }
+
+ static fn::MFSignature create_signature()
+ {
+ blender::fn::MFSignatureBuilder signature{"Sample Mesh Deformation"};
+ signature.single_input<float2>("Sample UV");
+ signature.single_output<float3>("Translation");
+ signature.single_output<float3>("Rotation");
+ return signature.build();
+ }
+
+ void call(const IndexMask mask,
+ fn::MFParams params,
+ fn::MFContext UNUSED(context)) const override
+ {
+ const VArray_Span<float2> sample_uvs = params.readonly_single_input<float2>(0, "Sample UV");
+ MutableSpan<float3> r_translations = params.uninitialized_single_output_if_required<float3>(
+ 1, "Translation");
+ MutableSpan<float3> r_rotations = params.uninitialized_single_output_if_required<float3>(
+ 2, "Rotation");
+
+ const bool compute_translation = !r_translations.is_empty();
+ const bool compute_rotation = !r_rotations.is_empty();
+
+ for (const int i : mask) {
+ const float2 &sample_uv = sample_uvs[i];
+ const ReverseUVSampler::Result sample_result = reverse_uv_sampler->sample(sample_uv);
+ if (sample_result.type != ReverseUVSampler::ResultType::Ok) {
+ if (compute_translation) {
+ r_translations[i] = float3(0.0f);
+ }
+ if (compute_rotation) {
+ r_rotations[i] = float3(0.0f);
+ }
+ continue;
+ }
+
+ const MLoopTri &looptri = *sample_result.looptri;
+ const float3 &bary_weights = sample_result.bary_weights;
+
+ const int corner_0 = looptri.tri[0];
+ const int corner_1 = looptri.tri[1];
+ const int corner_2 = looptri.tri[2];
+
+ const int vert_0 = mesh_->mloop[corner_0].v;
+ const int vert_1 = mesh_->mloop[corner_1].v;
+ const int vert_2 = mesh_->mloop[corner_2].v;
+
+ const float3 &old_pos_0 = rest_positions_[corner_0];
+ const float3 &old_pos_1 = rest_positions_[corner_1];
+ const float3 &old_pos_2 = rest_positions_[corner_2];
+
+ const float3 &new_pos_0 = verts_[vert_0].co;
+ const float3 &new_pos_1 = verts_[vert_1].co;
+ const float3 &new_pos_2 = verts_[vert_2].co;
+
+ if (compute_translation) {
+ const float3 old_pos = mix3(bary_weights, old_pos_0, old_pos_1, old_pos_2);
+ const float3 new_pos = mix3(bary_weights, new_pos_0, new_pos_1, new_pos_2);
+ const float3 translation = new_pos - old_pos;
+ r_translations[i] = translation;
+ }
+ if (compute_rotation) {
+ r_rotations[i] = float3(0.0f);
+ }
+ }
+ }
+};
+
+static void node_geo_exec(GeoNodeExecParams params)
+{
+ GeometrySet geometry = params.extract_input<GeometrySet>("Mesh");
+ Field<float3> rest_positions_field = params.extract_input<Field<float3>>("Rest Position");
+ Field<float3> uv_map_field = params.extract_input<Field<float3>>("UV Map");
+ Field<float3> sample_uv_field = params.extract_input<Field<float3>>("Sample UV");
+
+ if (!geometry.has_mesh()) {
+ params.set_default_remaining_outputs();
+ return;
+ }
+
+ geometry.ensure_owns_direct_data();
+
+ const bke::DataTypeConversions &conversions = bke::get_implicit_type_conversions();
+
+ const MeshComponent &mesh_component = *geometry.get_component_for_read<MeshComponent>();
+ GeometryComponentFieldContext field_context{mesh_component, ATTR_DOMAIN_CORNER};
+ FieldEvaluator field_evaluator{field_context,
+ mesh_component.attribute_domain_num(ATTR_DOMAIN_CORNER)};
+ field_evaluator.add(rest_positions_field);
+ field_evaluator.add(conversions.try_convert(std::move(uv_map_field), CPPType::get<float2>()));
+ field_evaluator.evaluate();
+ VArray<float3> rest_positions = field_evaluator.get_evaluated<float3>(0);
+ VArray<float2> uv_map = field_evaluator.get_evaluated<float2>(1);
+
+ auto fn = std::make_unique<SampleMeshDeformationFunction>(
+ std::move(geometry), std::move(rest_positions), std::move(uv_map));
+
+ Field<float2> sample_uv_field_float2 = conversions.try_convert(std::move(sample_uv_field),
+ CPPType::get<float2>());
+ auto operation = std::make_shared<FieldOperation>(
+ std::move(fn), Vector<GField>{std::move(sample_uv_field_float2)});
+
+ params.set_output("Translation", Field<float3>(operation, 0));
+ params.set_output("Rotation", Field<float3>(operation, 1));
+
+ params.set_default_remaining_outputs();
+}
+
+} // namespace blender::nodes::node_geo_sample_mesh_deformation_cc
+
+void register_node_type_geo_sample_mesh_deformation()
+{
+ namespace file_ns = blender::nodes::node_geo_sample_mesh_deformation_cc;
+
+ static bNodeType ntype;
+ geo_node_type_base(
+ &ntype, GEO_NODE_SAMPLE_MESH_DEFORMATION, "Sample Mesh Deformation", NODE_CLASS_GEOMETRY);
+ ntype.geometry_node_execute = file_ns::node_geo_exec;
+ ntype.draw_buttons = file_ns::node_layout;
+ ntype.declare = file_ns::node_declare;
+ node_type_init(&ntype, file_ns::node_init);
+ node_type_update(&ntype, file_ns::node_update);
+ nodeRegisterType(&ntype);
+}