From fcc17780a8305895d060bab2c0ef00b672e361dd Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Thu, 1 Feb 2024 13:18:35 +0100 Subject: [PATCH] Geometry Nodes: extract geometry transform functions to separate file --- source/blender/geometry/CMakeLists.txt | 2 + source/blender/geometry/GEO_transform.hh | 30 ++ source/blender/geometry/intern/transform.cc | 273 ++++++++++++++++ .../nodes/geometry/node_geometry_util.hh | 7 - .../geometry/nodes/node_geo_bounding_box.cc | 3 +- .../nodes/node_geo_mesh_primitive_cube.cc | 5 +- .../geometry/nodes/node_geo_object_info.cc | 4 +- .../nodes/node_geo_transform_geometry.cc | 294 ++---------------- 8 files changed, 334 insertions(+), 284 deletions(-) create mode 100644 source/blender/geometry/GEO_transform.hh create mode 100644 source/blender/geometry/intern/transform.cc diff --git a/source/blender/geometry/CMakeLists.txt b/source/blender/geometry/CMakeLists.txt index 29eff81a4f3..ec1e93a12a8 100644 --- a/source/blender/geometry/CMakeLists.txt +++ b/source/blender/geometry/CMakeLists.txt @@ -41,6 +41,7 @@ set(SRC intern/set_curve_type.cc intern/smooth_curves.cc intern/subdivide_curves.cc + intern/transform.cc intern/trim_curves.cc intern/uv_pack.cc intern/uv_parametrizer.cc @@ -71,6 +72,7 @@ set(SRC GEO_set_curve_type.hh GEO_smooth_curves.hh GEO_subdivide_curves.hh + GEO_transform.hh GEO_trim_curves.hh GEO_uv_pack.hh GEO_uv_parametrizer.hh diff --git a/source/blender/geometry/GEO_transform.hh b/source/blender/geometry/GEO_transform.hh new file mode 100644 index 00000000000..ec694904db6 --- /dev/null +++ b/source/blender/geometry/GEO_transform.hh @@ -0,0 +1,30 @@ +/* SPDX-FileCopyrightText: 2024 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +#include + +#include "BLI_math_quaternion_types.hh" +#include "BLI_math_vector_types.hh" + +struct Mesh; +namespace blender::bke { +struct GeometrySet; +} + +namespace blender::geometry { + +void transform_mesh(Mesh &mesh, float3 translation, math::Quaternion rotation, float3 scale); + +struct TransformGeometryErrors { + bool volume_too_small = false; +}; + +std::optional transform_geometry(bke::GeometrySet &geometry, + const float4x4 &transform); + +void translate_geometry(bke::GeometrySet &geometry, const float3 translation); + +} // namespace blender::geometry diff --git a/source/blender/geometry/intern/transform.cc b/source/blender/geometry/intern/transform.cc new file mode 100644 index 00000000000..6eab95c7f05 --- /dev/null +++ b/source/blender/geometry/intern/transform.cc @@ -0,0 +1,273 @@ +/* SPDX-FileCopyrightText: 2024 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifdef WITH_OPENVDB +# include +#endif + +#include "GEO_transform.hh" + +#include "BLI_math_base.h" +#include "BLI_math_matrix.h" +#include "BLI_math_rotation.hh" +#include "BLI_math_vector.hh" +#include "BLI_task.hh" + +#include "DNA_grease_pencil_types.h" +#include "DNA_mesh_types.h" +#include "DNA_pointcloud_types.h" +#include "DNA_volume_types.h" + +#include "BKE_attribute.hh" +#include "BKE_curves.hh" +#include "BKE_geometry_set.hh" +#include "BKE_grease_pencil.hh" +#include "BKE_instances.hh" +#include "BKE_mesh.hh" +#include "BKE_pointcloud.hh" +#include "BKE_volume.hh" + +namespace blender::geometry { + +static void translate_positions(MutableSpan positions, const float3 &translation) +{ + threading::parallel_for(positions.index_range(), 2048, [&](const IndexRange range) { + for (float3 &position : positions.slice(range)) { + position += translation; + } + }); +} + +static void transform_positions(MutableSpan positions, const float4x4 &matrix) +{ + threading::parallel_for(positions.index_range(), 1024, [&](const IndexRange range) { + for (float3 &position : positions.slice(range)) { + position = math::transform_point(matrix, position); + } + }); +} + +static void transform_mesh(Mesh &mesh, const float4x4 &transform) +{ + transform_positions(mesh.vert_positions_for_write(), transform); + mesh.tag_positions_changed(); +} + +static void translate_pointcloud(PointCloud &pointcloud, const float3 translation) +{ + if (math::is_zero(translation)) { + return; + } + + std::optional> bounds; + if (pointcloud.runtime->bounds_cache.is_cached()) { + bounds = pointcloud.runtime->bounds_cache.data(); + } + + bke::MutableAttributeAccessor attributes = pointcloud.attributes_for_write(); + bke::SpanAttributeWriter position = attributes.lookup_or_add_for_write_span( + "position", bke::AttrDomain::Point); + translate_positions(position.span, translation); + position.finish(); + + if (bounds) { + bounds->min += translation; + bounds->max += translation; + pointcloud.runtime->bounds_cache.ensure([&](Bounds &r_data) { r_data = *bounds; }); + } +} + +static void transform_pointcloud(PointCloud &pointcloud, const float4x4 &transform) +{ + bke::MutableAttributeAccessor attributes = pointcloud.attributes_for_write(); + bke::SpanAttributeWriter position = attributes.lookup_or_add_for_write_span( + "position", bke::AttrDomain::Point); + transform_positions(position.span, transform); + position.finish(); +} + +static void translate_greasepencil(GreasePencil &grease_pencil, const float3 translation) +{ + using namespace blender::bke::greasepencil; + for (const int layer_index : grease_pencil.layers().index_range()) { + if (Drawing *drawing = get_eval_grease_pencil_layer_drawing_for_write(grease_pencil, + layer_index)) + { + drawing->strokes_for_write().translate(translation); + } + } +} + +static void transform_greasepencil(GreasePencil &grease_pencil, const float4x4 &transform) +{ + using namespace blender::bke::greasepencil; + for (const int layer_index : grease_pencil.layers().index_range()) { + if (Drawing *drawing = get_eval_grease_pencil_layer_drawing_for_write(grease_pencil, + layer_index)) + { + drawing->strokes_for_write().transform(transform); + } + } +} + +static void translate_instances(bke::Instances &instances, const float3 translation) +{ + MutableSpan transforms = instances.transforms(); + threading::parallel_for(transforms.index_range(), 1024, [&](const IndexRange range) { + for (float4x4 &instance_transform : transforms.slice(range)) { + add_v3_v3(instance_transform.ptr()[3], translation); + } + }); +} + +static void transform_instances(bke::Instances &instances, const float4x4 &transform) +{ + MutableSpan transforms = instances.transforms(); + threading::parallel_for(transforms.index_range(), 1024, [&](const IndexRange range) { + for (float4x4 &instance_transform : transforms.slice(range)) { + instance_transform = transform * instance_transform; + } + }); +} + +static bool transform_volume(Volume &volume, const float4x4 &transform) +{ + bool found_too_small_scale = false; +#ifdef WITH_OPENVDB + openvdb::Mat4s vdb_matrix; + memcpy(vdb_matrix.asPointer(), &transform, sizeof(float[4][4])); + openvdb::Mat4d vdb_matrix_d{vdb_matrix}; + + const int grids_num = BKE_volume_num_grids(&volume); + for (const int i : IndexRange(grids_num)) { + bke::VolumeGridData *volume_grid = BKE_volume_grid_get_for_write(&volume, i); + + float4x4 grid_matrix = bke::volume_grid::get_transform_matrix(*volume_grid); + grid_matrix = transform * grid_matrix; + const float determinant = math::determinant(grid_matrix); + if (!BKE_volume_grid_determinant_valid(determinant)) { + found_too_small_scale = true; + /* Clear the tree because it is too small. */ + bke::volume_grid::clear_tree(*volume_grid); + if (determinant == 0) { + /* Reset rotation and scale. */ + grid_matrix.x_axis() = float3(1, 0, 0); + grid_matrix.y_axis() = float3(0, 1, 0); + grid_matrix.z_axis() = float3(0, 0, 1); + } + else { + /* Keep rotation but reset scale. */ + grid_matrix.x_axis() = math::normalize(grid_matrix.x_axis()); + grid_matrix.y_axis() = math::normalize(grid_matrix.y_axis()); + grid_matrix.z_axis() = math::normalize(grid_matrix.z_axis()); + } + } + bke::volume_grid::set_transform_matrix(*volume_grid, grid_matrix); + } + +#else + UNUSED_VARS(volume, transform); +#endif + return found_too_small_scale; +} + +static void translate_volume(Volume &volume, const float3 translation) +{ + transform_volume(volume, math::from_location(translation)); +} + +static void transform_curve_edit_hints(bke::CurvesEditHints &edit_hints, const float4x4 &transform) +{ + if (edit_hints.positions.has_value()) { + transform_positions(*edit_hints.positions, transform); + } + float3x3 deform_mat; + copy_m3_m4(deform_mat.ptr(), transform.ptr()); + if (edit_hints.deform_mats.has_value()) { + MutableSpan deform_mats = *edit_hints.deform_mats; + threading::parallel_for(deform_mats.index_range(), 1024, [&](const IndexRange range) { + for (const int64_t i : range) { + deform_mats[i] = deform_mat * deform_mats[i]; + } + }); + } + else { + edit_hints.deform_mats.emplace(edit_hints.curves_id_orig.geometry.point_num, deform_mat); + } +} + +static void translate_curve_edit_hints(bke::CurvesEditHints &edit_hints, const float3 &translation) +{ + if (edit_hints.positions.has_value()) { + translate_positions(*edit_hints.positions, translation); + } +} + +void translate_geometry(bke::GeometrySet &geometry, const float3 translation) +{ + if (Curves *curves = geometry.get_curves_for_write()) { + curves->geometry.wrap().translate(translation); + } + if (Mesh *mesh = geometry.get_mesh_for_write()) { + BKE_mesh_translate(mesh, translation, false); + } + if (PointCloud *pointcloud = geometry.get_pointcloud_for_write()) { + translate_pointcloud(*pointcloud, translation); + } + if (GreasePencil *grease_pencil = geometry.get_grease_pencil_for_write()) { + translate_greasepencil(*grease_pencil, translation); + } + if (Volume *volume = geometry.get_volume_for_write()) { + translate_volume(*volume, translation); + } + if (bke::Instances *instances = geometry.get_instances_for_write()) { + translate_instances(*instances, translation); + } + if (bke::CurvesEditHints *curve_edit_hints = geometry.get_curve_edit_hints_for_write()) { + translate_curve_edit_hints(*curve_edit_hints, translation); + } +} + +std::optional transform_geometry(bke::GeometrySet &geometry, + const float4x4 &transform) +{ + TransformGeometryErrors errors; + if (Curves *curves = geometry.get_curves_for_write()) { + curves->geometry.wrap().transform(transform); + } + if (Mesh *mesh = geometry.get_mesh_for_write()) { + transform_mesh(*mesh, transform); + } + if (PointCloud *pointcloud = geometry.get_pointcloud_for_write()) { + transform_pointcloud(*pointcloud, transform); + } + if (GreasePencil *grease_pencil = geometry.get_grease_pencil_for_write()) { + transform_greasepencil(*grease_pencil, transform); + } + if (Volume *volume = geometry.get_volume_for_write()) { + errors.volume_too_small = transform_volume(*volume, transform); + } + if (bke::Instances *instances = geometry.get_instances_for_write()) { + transform_instances(*instances, transform); + } + if (bke::CurvesEditHints *curve_edit_hints = geometry.get_curve_edit_hints_for_write()) { + transform_curve_edit_hints(*curve_edit_hints, transform); + } + + if (errors.volume_too_small) { + return errors; + } + return std::nullopt; +} + +void transform_mesh(Mesh &mesh, + const float3 translation, + const math::Quaternion rotation, + const float3 scale) +{ + const float4x4 matrix = math::from_loc_rot_scale(translation, rotation, scale); + transform_mesh(mesh, matrix); +} + +} // namespace blender::geometry diff --git a/source/blender/nodes/geometry/node_geometry_util.hh b/source/blender/nodes/geometry/node_geometry_util.hh index ab42f9fb838..55eb55bc394 100644 --- a/source/blender/nodes/geometry/node_geometry_util.hh +++ b/source/blender/nodes/geometry/node_geometry_util.hh @@ -33,13 +33,6 @@ namespace blender::nodes { bool check_tool_context_and_error(GeoNodeExecParams ¶ms); void search_link_ops_for_tool_node(GatherLinkSearchOpParams ¶ms); -void transform_mesh(Mesh &mesh, float3 translation, math::Quaternion rotation, float3 scale); - -void transform_geometry_set(GeoNodeExecParams ¶ms, - GeometrySet &geometry, - const float4x4 &transform, - const Depsgraph &depsgraph); - /** * Returns the parts of the geometry that are on the selection for the given domain. If the domain * is not applicable for the component, e.g. face domain for point cloud, nothing happens to that diff --git a/source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc b/source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc index 5a62d6214f7..3f255ba695d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc @@ -3,6 +3,7 @@ * SPDX-License-Identifier: GPL-2.0-or-later */ #include "GEO_mesh_primitive_cuboid.hh" +#include "GEO_transform.hh" #include "node_geometry_util.hh" @@ -54,7 +55,7 @@ static void node_geo_exec(GeoNodeExecParams params) const float3 scale = sub_bounds->max - sub_bounds->min; const float3 center = sub_bounds->min + scale / 2.0f; Mesh *mesh = geometry::create_cuboid_mesh(scale, 2, 2, 2, "uv_map"); - transform_mesh(*mesh, center, math::Quaternion::identity(), float3(1)); + geometry::transform_mesh(*mesh, center, math::Quaternion::identity(), float3(1)); sub_geometry.replace_mesh(mesh); sub_geometry.keep_only_during_modify({GeometryComponent::Type::Mesh}); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc index b6cac1a8796..2ace258acbf 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc @@ -10,6 +10,7 @@ #include "GEO_mesh_primitive_cuboid.hh" #include "GEO_mesh_primitive_grid.hh" #include "GEO_mesh_primitive_line.hh" +#include "GEO_transform.hh" #include "node_geometry_util.hh" @@ -75,13 +76,13 @@ static Mesh *create_cube_mesh(const float3 size, } if (verts_y == 1) { /* XZ plane. */ Mesh *mesh = geometry::create_grid_mesh(verts_x, verts_z, size.x, size.z, uv_map_id); - transform_mesh( + geometry::transform_mesh( *mesh, float3(0), math::to_quaternion(math::EulerXYZ(M_PI_2, 0.0f, 0.0f)), float3(1)); return mesh; } /* YZ plane. */ Mesh *mesh = geometry::create_grid_mesh(verts_z, verts_y, size.z, size.y, uv_map_id); - transform_mesh( + geometry::transform_mesh( *mesh, float3(0), math::to_quaternion(math::EulerXYZ(0.0f, M_PI_2, 0.0f)), float3(1)); return mesh; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_object_info.cc b/source/blender/nodes/geometry/nodes/node_geo_object_info.cc index 7625774e276..35bd7c607c2 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_object_info.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_object_info.cc @@ -14,6 +14,8 @@ #include "UI_interface.hh" #include "UI_resources.hh" +#include "GEO_transform.hh" + #include "node_geometry_util.hh" namespace blender::nodes::node_geo_object_info_cc { @@ -90,7 +92,7 @@ static void node_geo_exec(GeoNodeExecParams params) else { geometry_set = bke::object_get_evaluated_geometry_set(*object); if (transform_space_relative) { - transform_geometry_set(params, geometry_set, transform, *params.depsgraph()); + geometry::transform_geometry(geometry_set, transform); } } diff --git a/source/blender/nodes/geometry/nodes/node_geo_transform_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_transform_geometry.cc index 96b2556783c..d9780315b23 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_transform_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_transform_geometry.cc @@ -2,10 +2,6 @@ * * SPDX-License-Identifier: GPL-2.0-or-later */ -#ifdef WITH_OPENVDB -# include -#endif - #include "BLI_math_matrix.h" #include "BLI_math_matrix.hh" #include "BLI_math_rotation.hh" @@ -24,9 +20,20 @@ #include "DEG_depsgraph_query.hh" +#include "GEO_transform.hh" + #include "node_geometry_util.hh" -namespace blender::nodes { +namespace blender::nodes::node_geo_transform_geometry_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input("Geometry"); + b.add_input("Translation").subtype(PROP_TRANSLATION); + b.add_input("Rotation"); + b.add_input("Scale").default_value({1, 1, 1}).subtype(PROP_XYZ); + b.add_output("Geometry").propagate_all(); +} static bool use_translate(const math::Quaternion &rotation, const float3 scale) { @@ -41,269 +48,6 @@ static bool use_translate(const math::Quaternion &rotation, const float3 scale) return true; } -static void translate_positions(MutableSpan positions, const float3 &translation) -{ - threading::parallel_for(positions.index_range(), 2048, [&](const IndexRange range) { - for (float3 &position : positions.slice(range)) { - position += translation; - } - }); -} - -static void transform_positions(MutableSpan positions, const float4x4 &matrix) -{ - threading::parallel_for(positions.index_range(), 1024, [&](const IndexRange range) { - for (float3 &position : positions.slice(range)) { - position = math::transform_point(matrix, position); - } - }); -} - -static void transform_mesh(Mesh &mesh, const float4x4 &transform) -{ - transform_positions(mesh.vert_positions_for_write(), transform); - mesh.tag_positions_changed(); -} - -static void translate_pointcloud(PointCloud &pointcloud, const float3 translation) -{ - if (math::is_zero(translation)) { - return; - } - - std::optional> bounds; - if (pointcloud.runtime->bounds_cache.is_cached()) { - bounds = pointcloud.runtime->bounds_cache.data(); - } - - MutableAttributeAccessor attributes = pointcloud.attributes_for_write(); - SpanAttributeWriter position = attributes.lookup_or_add_for_write_span( - "position", AttrDomain::Point); - translate_positions(position.span, translation); - position.finish(); - - if (bounds) { - bounds->min += translation; - bounds->max += translation; - pointcloud.runtime->bounds_cache.ensure([&](Bounds &r_data) { r_data = *bounds; }); - } -} - -static void transform_pointcloud(PointCloud &pointcloud, const float4x4 &transform) -{ - MutableAttributeAccessor attributes = pointcloud.attributes_for_write(); - SpanAttributeWriter position = attributes.lookup_or_add_for_write_span( - "position", AttrDomain::Point); - transform_positions(position.span, transform); - position.finish(); -} - -static void translate_greasepencil(GreasePencil &grease_pencil, const float3 translation) -{ - using namespace blender::bke::greasepencil; - for (const int layer_index : grease_pencil.layers().index_range()) { - if (Drawing *drawing = get_eval_grease_pencil_layer_drawing_for_write(grease_pencil, - layer_index)) - { - drawing->strokes_for_write().translate(translation); - } - } -} - -static void transform_greasepencil(GreasePencil &grease_pencil, const float4x4 &transform) -{ - using namespace blender::bke::greasepencil; - for (const int layer_index : grease_pencil.layers().index_range()) { - if (Drawing *drawing = get_eval_grease_pencil_layer_drawing_for_write(grease_pencil, - layer_index)) - { - drawing->strokes_for_write().transform(transform); - } - } -} - -static void translate_instances(bke::Instances &instances, const float3 translation) -{ - MutableSpan transforms = instances.transforms(); - threading::parallel_for(transforms.index_range(), 1024, [&](const IndexRange range) { - for (float4x4 &instance_transform : transforms.slice(range)) { - add_v3_v3(instance_transform.ptr()[3], translation); - } - }); -} - -static void transform_instances(bke::Instances &instances, const float4x4 &transform) -{ - MutableSpan transforms = instances.transforms(); - threading::parallel_for(transforms.index_range(), 1024, [&](const IndexRange range) { - for (float4x4 &instance_transform : transforms.slice(range)) { - instance_transform = transform * instance_transform; - } - }); -} - -static void transform_volume(GeoNodeExecParams ¶ms, - Volume &volume, - const float4x4 &transform, - const Depsgraph &depsgraph) -{ -#ifdef WITH_OPENVDB - const Main *bmain = DEG_get_bmain(&depsgraph); - BKE_volume_load(&volume, bmain); - - openvdb::Mat4s vdb_matrix; - memcpy(vdb_matrix.asPointer(), &transform, sizeof(float[4][4])); - openvdb::Mat4d vdb_matrix_d{vdb_matrix}; - - bool found_too_small_scale = false; - const int grids_num = BKE_volume_num_grids(&volume); - for (const int i : IndexRange(grids_num)) { - bke::VolumeGridData *volume_grid = BKE_volume_grid_get_for_write(&volume, i); - - float4x4 grid_matrix = bke::volume_grid::get_transform_matrix(*volume_grid); - grid_matrix = transform * grid_matrix; - const float determinant = math::determinant(grid_matrix); - if (!BKE_volume_grid_determinant_valid(determinant)) { - found_too_small_scale = true; - /* Clear the tree because it is too small. */ - bke::volume_grid::clear_tree(*volume_grid); - if (determinant == 0) { - /* Reset rotation and scale. */ - grid_matrix.x_axis() = float3(1, 0, 0); - grid_matrix.y_axis() = float3(0, 1, 0); - grid_matrix.z_axis() = float3(0, 0, 1); - } - else { - /* Keep rotation but reset scale. */ - grid_matrix.x_axis() = math::normalize(grid_matrix.x_axis()); - grid_matrix.y_axis() = math::normalize(grid_matrix.y_axis()); - grid_matrix.z_axis() = math::normalize(grid_matrix.z_axis()); - } - } - bke::volume_grid::set_transform_matrix(*volume_grid, grid_matrix); - } - if (found_too_small_scale) { - params.error_message_add(NodeWarningType::Warning, - TIP_("Volume scale is lower than permitted by OpenVDB")); - } -#else - UNUSED_VARS(params, volume, transform, depsgraph); -#endif -} - -static void translate_volume(GeoNodeExecParams ¶ms, - Volume &volume, - const float3 translation, - const Depsgraph &depsgraph) -{ - transform_volume(params, volume, math::from_location(translation), depsgraph); -} - -static void transform_curve_edit_hints(bke::CurvesEditHints &edit_hints, const float4x4 &transform) -{ - if (edit_hints.positions.has_value()) { - transform_positions(*edit_hints.positions, transform); - } - float3x3 deform_mat; - copy_m3_m4(deform_mat.ptr(), transform.ptr()); - if (edit_hints.deform_mats.has_value()) { - MutableSpan deform_mats = *edit_hints.deform_mats; - threading::parallel_for(deform_mats.index_range(), 1024, [&](const IndexRange range) { - for (const int64_t i : range) { - deform_mats[i] = deform_mat * deform_mats[i]; - } - }); - } - else { - edit_hints.deform_mats.emplace(edit_hints.curves_id_orig.geometry.point_num, deform_mat); - } -} - -static void translate_curve_edit_hints(bke::CurvesEditHints &edit_hints, const float3 &translation) -{ - if (edit_hints.positions.has_value()) { - translate_positions(*edit_hints.positions, translation); - } -} - -static void translate_geometry_set(GeoNodeExecParams ¶ms, - GeometrySet &geometry, - const float3 translation, - const Depsgraph &depsgraph) -{ - if (Curves *curves = geometry.get_curves_for_write()) { - curves->geometry.wrap().translate(translation); - } - if (Mesh *mesh = geometry.get_mesh_for_write()) { - BKE_mesh_translate(mesh, translation, false); - } - if (PointCloud *pointcloud = geometry.get_pointcloud_for_write()) { - translate_pointcloud(*pointcloud, translation); - } - if (GreasePencil *grease_pencil = geometry.get_grease_pencil_for_write()) { - translate_greasepencil(*grease_pencil, translation); - } - if (Volume *volume = geometry.get_volume_for_write()) { - translate_volume(params, *volume, translation, depsgraph); - } - if (bke::Instances *instances = geometry.get_instances_for_write()) { - translate_instances(*instances, translation); - } - if (bke::CurvesEditHints *curve_edit_hints = geometry.get_curve_edit_hints_for_write()) { - translate_curve_edit_hints(*curve_edit_hints, translation); - } -} - -void transform_geometry_set(GeoNodeExecParams ¶ms, - GeometrySet &geometry, - const float4x4 &transform, - const Depsgraph &depsgraph) -{ - if (Curves *curves = geometry.get_curves_for_write()) { - curves->geometry.wrap().transform(transform); - } - if (Mesh *mesh = geometry.get_mesh_for_write()) { - transform_mesh(*mesh, transform); - } - if (PointCloud *pointcloud = geometry.get_pointcloud_for_write()) { - transform_pointcloud(*pointcloud, transform); - } - if (GreasePencil *grease_pencil = geometry.get_grease_pencil_for_write()) { - transform_greasepencil(*grease_pencil, transform); - } - if (Volume *volume = geometry.get_volume_for_write()) { - transform_volume(params, *volume, transform, depsgraph); - } - if (bke::Instances *instances = geometry.get_instances_for_write()) { - transform_instances(*instances, transform); - } - if (bke::CurvesEditHints *curve_edit_hints = geometry.get_curve_edit_hints_for_write()) { - transform_curve_edit_hints(*curve_edit_hints, transform); - } -} - -void transform_mesh(Mesh &mesh, - const float3 translation, - const math::Quaternion rotation, - const float3 scale) -{ - const float4x4 matrix = math::from_loc_rot_scale(translation, rotation, scale); - transform_mesh(mesh, matrix); -} - -} // namespace blender::nodes - -namespace blender::nodes::node_geo_transform_geometry_cc { - -static void node_declare(NodeDeclarationBuilder &b) -{ - b.add_input("Geometry"); - b.add_input("Translation").subtype(PROP_TRANSLATION); - b.add_input("Rotation"); - b.add_input("Scale").default_value({1, 1, 1}).subtype(PROP_XYZ); - b.add_output("Geometry").propagate_all(); -} - static void node_geo_exec(GeoNodeExecParams params) { GeometrySet geometry_set = params.extract_input("Geometry"); @@ -313,13 +57,17 @@ static void node_geo_exec(GeoNodeExecParams params) /* Use only translation if rotation and scale don't apply. */ if (use_translate(rotation, scale)) { - translate_geometry_set(params, geometry_set, translation, *params.depsgraph()); + geometry::translate_geometry(geometry_set, translation); } else { - transform_geometry_set(params, - geometry_set, - math::from_loc_rot_scale(translation, rotation, scale), - *params.depsgraph()); + if (auto errors = geometry::transform_geometry( + geometry_set, math::from_loc_rot_scale(translation, rotation, scale))) + { + if (errors->volume_too_small) { + params.error_message_add(NodeWarningType::Warning, + TIP_("Volume scale is lower than permitted by OpenVDB")); + } + } } params.set_output("Geometry", std::move(geometry_set));