diff --git a/scripts/startup/bl_ui/node_add_menu_geometry.py b/scripts/startup/bl_ui/node_add_menu_geometry.py index cd5b22e5161..f8168e99052 100644 --- a/scripts/startup/bl_ui/node_add_menu_geometry.py +++ b/scripts/startup/bl_ui/node_add_menu_geometry.py @@ -410,7 +410,11 @@ class NODE_MT_geometry_node_GEO_MESH_OPERATIONS(Menu): node_add_menu.add_node_type(layout, "GeometryNodeFlipFaces") node_add_menu.add_node_type(layout, "GeometryNodeMeshBoolean") node_add_menu.add_node_type(layout, "GeometryNodeMeshToCurve") + if context.preferences.experimental.use_new_volume_nodes: + node_add_menu.add_node_type(layout, "GeometryNodeMeshToDensityGrid") node_add_menu.add_node_type(layout, "GeometryNodeMeshToPoints") + if context.preferences.experimental.use_new_volume_nodes: + node_add_menu.add_node_type(layout, "GeometryNodeMeshToSDFGrid") node_add_menu.add_node_type(layout, "GeometryNodeMeshToVolume") node_add_menu.add_node_type(layout, "GeometryNodeScaleElements") node_add_menu.add_node_type(layout, "GeometryNodeSplitEdges") @@ -476,6 +480,8 @@ class NODE_MT_category_GEO_POINT(Menu): layout.separator() node_add_menu.add_node_type(layout, "GeometryNodePoints") node_add_menu.add_node_type(layout, "GeometryNodePointsToCurves") + if context.preferences.experimental.use_new_volume_nodes: + node_add_menu.add_node_type(layout, "GeometryNodePointsToSDFGrid") node_add_menu.add_node_type(layout, "GeometryNodePointsToVertices") node_add_menu.add_node_type(layout, "GeometryNodePointsToVolume") layout.separator() diff --git a/source/blender/blenkernel/BKE_node.hh b/source/blender/blenkernel/BKE_node.hh index 43580ee1b94..c8bb5969792 100644 --- a/source/blender/blenkernel/BKE_node.hh +++ b/source/blender/blenkernel/BKE_node.hh @@ -1330,6 +1330,9 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i #define GEO_NODE_SORT_ELEMENTS 2123 #define GEO_NODE_MENU_SWITCH 2124 #define GEO_NODE_SAMPLE_GRID 2125 +#define GEO_NODE_MESH_TO_DENSITY_GRID 2126 +#define GEO_NODE_MESH_TO_SDF_GRID 2127 +#define GEO_NODE_POINTS_TO_SDF_GRID 2128 /** \} */ diff --git a/source/blender/geometry/GEO_mesh_to_volume.hh b/source/blender/geometry/GEO_mesh_to_volume.hh index 2c837f0e4e6..c87b9eb2e09 100644 --- a/source/blender/geometry/GEO_mesh_to_volume.hh +++ b/source/blender/geometry/GEO_mesh_to_volume.hh @@ -56,15 +56,19 @@ bke::VolumeGridData *fog_volume_grid_add_from_mesh(Volume *volume, float voxel_size, float interior_band_width, float density); -/** - * Add a new SDF VolumeGrid to the Volume by converting the supplied mesh. - */ -bke::VolumeGridData *sdf_volume_grid_add_from_mesh(Volume *volume, - StringRefNull name, - Span positions, - Span corner_verts, - Span corner_tris, - float voxel_size, - float half_band_width); + +bke::VolumeGrid mesh_to_density_grid(const Span positions, + const Span corner_verts, + const Span corner_tris, + const float voxel_size, + const float interior_band_width, + const float density); + +bke::VolumeGrid mesh_to_sdf_grid(Span positions, + Span corner_verts, + Span corner_tris, + float voxel_size, + float half_band_width); + #endif } // namespace blender::geometry diff --git a/source/blender/geometry/GEO_points_to_volume.hh b/source/blender/geometry/GEO_points_to_volume.hh index 89b3a101f91..689dfaeaaea 100644 --- a/source/blender/geometry/GEO_points_to_volume.hh +++ b/source/blender/geometry/GEO_points_to_volume.hh @@ -2,12 +2,8 @@ * * SPDX-License-Identifier: GPL-2.0-or-later */ -#include "BLI_function_ref.hh" -#include "BLI_math_matrix_types.hh" #include "BLI_string_ref.hh" -#include "DNA_modifier_types.h" - #include "BKE_volume_grid_fwd.hh" #pragma once @@ -31,13 +27,10 @@ bke::VolumeGridData *fog_volume_grid_add_from_points(Volume *volume, Span radii, float voxel_size, float density); -/** - * Add a new SDF VolumeGrid to the Volume by converting the supplied points. - */ -bke::VolumeGridData *sdf_volume_grid_add_from_points(Volume *volume, - StringRefNull name, - Span positions, - Span radii, - float voxel_size); + +bke::VolumeGrid points_to_sdf_grid(Span positions, + Span radii, + float voxel_size); + #endif } // namespace blender::geometry diff --git a/source/blender/geometry/intern/mesh_to_volume.cc b/source/blender/geometry/intern/mesh_to_volume.cc index fad4a8ee7fc..a339a520c05 100644 --- a/source/blender/geometry/intern/mesh_to_volume.cc +++ b/source/blender/geometry/intern/mesh_to_volume.cc @@ -6,6 +6,7 @@ #include "BLI_task.hh" #include "BKE_volume.hh" +#include "BKE_volume_grid.hh" #include "BKE_volume_openvdb.hh" #include "GEO_mesh_to_volume.hh" @@ -109,7 +110,7 @@ float volume_compute_voxel_size(const Depsgraph *depsgraph, return voxel_size / volume_simplify; } -static openvdb::FloatGrid::Ptr mesh_to_fog_volume_grid( +static openvdb::FloatGrid::Ptr mesh_to_density_grid_impl( const Span positions, const Span corner_verts, const Span corner_tris, @@ -147,14 +148,34 @@ static openvdb::FloatGrid::Ptr mesh_to_fog_volume_grid( return new_grid; } -static openvdb::FloatGrid::Ptr mesh_to_sdf_volume_grid(const Span positions, - const Span corner_verts, - const Span corner_tris, - const float voxel_size, - const float half_band_width) +bke::VolumeGrid mesh_to_density_grid(const Span positions, + const Span corner_verts, + const Span corner_tris, + const float voxel_size, + const float interior_band_width, + const float density) +{ + openvdb::FloatGrid::Ptr grid = mesh_to_density_grid_impl(positions, + corner_verts, + corner_tris, + float4x4::identity(), + voxel_size, + interior_band_width, + density); + if (!grid) { + return {}; + } + return bke::VolumeGrid(std::move(grid)); +} + +bke::VolumeGrid mesh_to_sdf_grid(const Span positions, + const Span corner_verts, + const Span corner_tris, + const float voxel_size, + const float half_band_width) { if (voxel_size <= 0.0f || half_band_width <= 0.0f) { - return nullptr; + return {}; } std::vector points(positions.size()); @@ -180,7 +201,7 @@ static openvdb::FloatGrid::Ptr mesh_to_sdf_volume_grid(const Span positi openvdb::FloatGrid::Ptr new_grid = openvdb::tools::meshToLevelSet( *transform, points, triangles, half_band_width); - return new_grid; + return bke::VolumeGrid(std::move(new_grid)); } bke::VolumeGridData *fog_volume_grid_add_from_mesh(Volume *volume, @@ -193,27 +214,15 @@ bke::VolumeGridData *fog_volume_grid_add_from_mesh(Volume *volume, const float interior_band_width, const float density) { - openvdb::FloatGrid::Ptr mesh_grid = mesh_to_fog_volume_grid(positions, - corner_verts, - corner_tris, - mesh_to_volume_space_transform, - voxel_size, - interior_band_width, - density); + openvdb::FloatGrid::Ptr mesh_grid = mesh_to_density_grid_impl(positions, + corner_verts, + corner_tris, + mesh_to_volume_space_transform, + voxel_size, + interior_band_width, + density); return mesh_grid ? BKE_volume_grid_add_vdb(*volume, name, std::move(mesh_grid)) : nullptr; } -bke::VolumeGridData *sdf_volume_grid_add_from_mesh(Volume *volume, - const StringRefNull name, - const Span positions, - const Span corner_verts, - const Span corner_tris, - const float voxel_size, - const float half_band_width) -{ - openvdb::FloatGrid::Ptr mesh_grid = mesh_to_sdf_volume_grid( - positions, corner_verts, corner_tris, voxel_size, half_band_width); - return mesh_grid ? BKE_volume_grid_add_vdb(*volume, name, std::move(mesh_grid)) : nullptr; -} } // namespace blender::geometry #endif diff --git a/source/blender/geometry/intern/points_to_volume.cc b/source/blender/geometry/intern/points_to_volume.cc index 9a62d91904a..ee13375c004 100644 --- a/source/blender/geometry/intern/points_to_volume.cc +++ b/source/blender/geometry/intern/points_to_volume.cc @@ -5,6 +5,7 @@ #include "BLI_math_matrix.hh" #include "BKE_volume.hh" +#include "BKE_volume_grid.hh" #include "BKE_volume_openvdb.hh" #include "GEO_points_to_volume.hh" @@ -17,31 +18,47 @@ namespace blender::geometry { /* Implements the interface required by #openvdb::tools::ParticlesToLevelSet. */ -struct OpenVDBParticleList { +class OpenVDBParticleList { + public: using PosType = openvdb::Vec3R; - Span positions; - Span radii; + private: + Span positions_; + Span radii_; + float voxel_size_inv_; + + public: + OpenVDBParticleList(const Span positions, + const Span radii, + const float voxel_size) + : positions_(positions), radii_(radii), voxel_size_inv_(math::rcp(voxel_size)) + { + BLI_assert(voxel_size > 0.0f); + } size_t size() const { - return size_t(positions.size()); + return size_t(positions_.size()); } void getPos(size_t n, openvdb::Vec3R &xyz) const { - xyz = &positions[n].x; + float3 pos = positions_[n] * voxel_size_inv_; + /* Better align generated grid with source points. */ + pos -= float3(0.5f); + xyz = &pos.x; } void getPosRad(size_t n, openvdb::Vec3R &xyz, openvdb::Real &radius) const { - xyz = &positions[n].x; - radius = radii[n]; + this->getPos(n, xyz); + radius = radii_[n] * voxel_size_inv_; } }; -static openvdb::FloatGrid::Ptr points_to_sdf_grid(const Span positions, - const Span radii) +static openvdb::FloatGrid::Ptr points_to_sdf_grid_impl(const Span positions, + const Span radii, + const float voxel_size) { /* Create a new grid that will be filled. #ParticlesToLevelSet requires * the background value to be positive */ @@ -52,13 +69,23 @@ static openvdb::FloatGrid::Ptr points_to_sdf_grid(const Span positions, /* Don't ignore particles based on their radius. */ op.setRmin(0.0f); op.setRmax(std::numeric_limits::max()); - OpenVDBParticleList particles{positions, radii}; + OpenVDBParticleList particles{positions, radii, voxel_size}; op.rasterizeSpheres(particles); op.finalize(); + new_grid->transform().postScale(voxel_size); + new_grid->setGridClass(openvdb::GRID_LEVEL_SET); + return new_grid; } +bke::VolumeGrid points_to_sdf_grid(const Span positions, + const Span radii, + const float voxel_size) +{ + return bke::VolumeGrid(points_to_sdf_grid_impl(positions, radii, voxel_size)); +} + bke::VolumeGridData *fog_volume_grid_add_from_points(Volume *volume, const StringRefNull name, const Span positions, @@ -66,8 +93,7 @@ bke::VolumeGridData *fog_volume_grid_add_from_points(Volume *volume, const float voxel_size, const float density) { - openvdb::FloatGrid::Ptr new_grid = points_to_sdf_grid(positions, radii); - new_grid->transform().postScale(voxel_size); + openvdb::FloatGrid::Ptr new_grid = points_to_sdf_grid_impl(positions, radii, voxel_size); new_grid->setGridClass(openvdb::GRID_FOG_VOLUME); /* Convert the level set to a fog volume. This also sets the background value to zero. Inside the @@ -83,17 +109,5 @@ bke::VolumeGridData *fog_volume_grid_add_from_points(Volume *volume, return BKE_volume_grid_add_vdb(*volume, name, std::move(new_grid)); } -bke::VolumeGridData *sdf_volume_grid_add_from_points(Volume *volume, - const StringRefNull name, - const Span positions, - const Span radii, - const float voxel_size) -{ - openvdb::FloatGrid::Ptr new_grid = points_to_sdf_grid(positions, radii); - new_grid->transform().postScale(voxel_size); - new_grid->setGridClass(openvdb::GRID_LEVEL_SET); - - return BKE_volume_grid_add_vdb(*volume, name, std::move(new_grid)); -} } // namespace blender::geometry #endif diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index d14eab18e89..7269b2220b4 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -395,7 +395,9 @@ DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_ICO_SPHERE, 0, "MESH_PRIMITIVE_ICO DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_LINE, 0, "MESH_PRIMITIVE_LINE",MeshLine, "Mesh Line", "Generate vertices in a line and connect them with edges") DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_UV_SPHERE, 0, "MESH_PRIMITIVE_UV_SPHERE", MeshUVSphere, "UV Sphere", "Generate a spherical mesh with quads, except for triangles at the top and bottom") DefNode(GeometryNode, GEO_NODE_MESH_TO_CURVE, 0, "MESH_TO_CURVE", MeshToCurve, "Mesh to Curve", "Generate a curve from a mesh") +DefNode(GeometryNode, GEO_NODE_MESH_TO_DENSITY_GRID, 0, "MESH_TO_DENSITY_GRID", MeshToDensityGrid, "Mesh to Density Grid", "Create a filled volume grid from a mesh") DefNode(GeometryNode, GEO_NODE_MESH_TO_POINTS, 0, "MESH_TO_POINTS", MeshToPoints, "Mesh to Points", "Generate a point cloud from a mesh's vertices") +DefNode(GeometryNode, GEO_NODE_MESH_TO_SDF_GRID, 0, "MESH_TO_SDF_GRID", MeshToSDFGrid, "Mesh to SDF Grid", "Create a signed distance volume grid from a mesh") DefNode(GeometryNode, GEO_NODE_MESH_TO_VOLUME, 0, "MESH_TO_VOLUME", MeshToVolume, "Mesh to Volume", "Create a fog volume with the shape of the input mesh's surface") DefNode(GeometryNode, GEO_NODE_MESH_TOPOLOGY_CORNERS_OF_EDGE, 0, "CORNERS_OF_EDGE", CornersOfEdge, "Corners of Edge", "Retrieve face corners connected to edges") DefNode(GeometryNode, GEO_NODE_MESH_TOPOLOGY_CORNERS_OF_FACE, 0, "CORNERS_OF_FACE", CornersOfFace, "Corners of Face", "Retrieve corners that make up a face") @@ -408,6 +410,7 @@ DefNode(GeometryNode, GEO_NODE_MESH_TOPOLOGY_VERTEX_OF_CORNER, 0, "VERTEX_OF_COR DefNode(GeometryNode, GEO_NODE_OBJECT_INFO, 0, "OBJECT_INFO", ObjectInfo, "Object Info", "Retrieve information from an object") DefNode(GeometryNode, GEO_NODE_OFFSET_POINT_IN_CURVE, 0, "OFFSET_POINT_IN_CURVE", OffsetPointInCurve, "Offset Point in Curve", "Offset a control point index within its curve") DefNode(GeometryNode, GEO_NODE_POINTS_TO_CURVES, 0, "POINTS_TO_CURVES", PointsToCurves, "Points to Curves", "Split all points to curve by its group ID and reorder by weight") +DefNode(GeometryNode, GEO_NODE_POINTS_TO_SDF_GRID, 0, "POINTS_TO_SDF_GRID", PointsToSDFGrid, "Points to SDF Grid", "Create a signed distance volume grid from points") DefNode(GeometryNode, GEO_NODE_POINTS_TO_VERTICES, 0, "POINTS_TO_VERTICES", PointsToVertices, "Points to Vertices", "Generate a mesh vertex for each point cloud point") DefNode(GeometryNode, GEO_NODE_POINTS_TO_VOLUME, 0, "POINTS_TO_VOLUME", PointsToVolume, "Points to Volume", "Generate a fog volume sphere around every point") DefNode(GeometryNode, GEO_NODE_POINTS, 0, "POINTS", Points, "Points", "Generate a point cloud with positions and radii defined by fields") diff --git a/source/blender/nodes/geometry/CMakeLists.txt b/source/blender/nodes/geometry/CMakeLists.txt index 4b5a4fefbcb..e9cb3adcc0f 100644 --- a/source/blender/nodes/geometry/CMakeLists.txt +++ b/source/blender/nodes/geometry/CMakeLists.txt @@ -133,7 +133,9 @@ set(SRC nodes/node_geo_mesh_primitive_uv_sphere.cc nodes/node_geo_mesh_subdivide.cc nodes/node_geo_mesh_to_curve.cc + nodes/node_geo_mesh_to_density_grid.cc nodes/node_geo_mesh_to_points.cc + nodes/node_geo_mesh_to_sdf_grid.cc nodes/node_geo_mesh_to_volume.cc nodes/node_geo_mesh_topology_corners_of_edge.cc nodes/node_geo_mesh_topology_corners_of_face.cc @@ -147,6 +149,7 @@ set(SRC nodes/node_geo_offset_point_in_curve.cc nodes/node_geo_points.cc nodes/node_geo_points_to_curves.cc + nodes/node_geo_points_to_sdf_grid.cc nodes/node_geo_points_to_vertices.cc nodes/node_geo_points_to_volume.cc nodes/node_geo_proximity.cc diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_density_grid.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_density_grid.cc new file mode 100644 index 00000000000..e12c53f220d --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_density_grid.cc @@ -0,0 +1,68 @@ +/* SPDX-FileCopyrightText: 2024 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BKE_mesh.hh" +#include "BKE_volume_grid.hh" + +#include "GEO_mesh_to_volume.hh" + +#include "node_geometry_util.hh" + +namespace blender::nodes::node_geo_mesh_to_density_grid_cc { + +NODE_STORAGE_FUNCS(NodeGeometryMeshToVolume) + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input("Mesh").supported_type(GeometryComponent::Type::Mesh); + b.add_input("Density").default_value(1.0f).min(0.01f).max(FLT_MAX); + b.add_input("Voxel Size") + .default_value(0.3f) + .min(0.01f) + .max(FLT_MAX) + .subtype(PROP_DISTANCE); + b.add_input("Gradient Width") + .default_value(0.2f) + .min(0.0001f) + .max(FLT_MAX) + .subtype(PROP_DISTANCE) + .description("Width of the gradient inside of the mesh"); + b.add_output("Density Grid"); +} + +static void node_geo_exec(GeoNodeExecParams params) +{ +#ifdef WITH_OPENVDB + const GeometrySet geometry_set = params.extract_input("Mesh"); + const Mesh *mesh = geometry_set.get_mesh(); + if (!mesh || mesh->faces_num == 0) { + params.set_default_remaining_outputs(); + return; + } + bke::VolumeGrid grid = geometry::mesh_to_density_grid( + mesh->vert_positions(), + mesh->corner_verts(), + mesh->corner_tris(), + params.extract_input("Voxel Size"), + params.extract_input("Gradient Width"), + params.extract_input("Density")); + params.set_output("Density Grid", std::move(grid)); +#else + node_geo_exec_with_missing_openvdb(params); +#endif +} + +static void node_register() +{ + static bNodeType ntype; + + geo_node_type_base( + &ntype, GEO_NODE_MESH_TO_DENSITY_GRID, "Mesh to Density Grid", NODE_CLASS_GEOMETRY); + ntype.declare = node_declare; + ntype.geometry_node_execute = node_geo_exec; + nodeRegisterType(&ntype); +} +NOD_REGISTER_NODE(node_register) + +} // namespace blender::nodes::node_geo_mesh_to_density_grid_cc diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_sdf_grid.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_sdf_grid.cc new file mode 100644 index 00000000000..b6df47a5f8f --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_sdf_grid.cc @@ -0,0 +1,62 @@ +/* SPDX-FileCopyrightText: 2024 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BKE_mesh.hh" +#include "BKE_volume_grid.hh" + +#include "GEO_mesh_to_volume.hh" + +#include "node_geometry_util.hh" + +namespace blender::nodes::node_geo_mesh_to_sdf_grid_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input("Mesh").supported_type(GeometryComponent::Type::Mesh); + b.add_input("Voxel Size") + .default_value(0.3f) + .min(0.01f) + .max(FLT_MAX) + .subtype(PROP_DISTANCE); + b.add_input("Band Width") + .default_value(3) + .min(0) + .max(100) + .description("Width of the active voxel surface, in voxels"); + b.add_output("SDF Grid"); +} + +static void node_geo_exec(GeoNodeExecParams params) +{ +#ifdef WITH_OPENVDB + const GeometrySet geometry_set = params.extract_input("Mesh"); + const Mesh *mesh = geometry_set.get_mesh(); + if (!mesh || mesh->faces_num == 0) { + params.set_default_remaining_outputs(); + return; + } + bke::VolumeGrid grid = geometry::mesh_to_sdf_grid( + mesh->vert_positions(), + mesh->corner_verts(), + mesh->corner_tris(), + params.extract_input("Voxel Size"), + params.extract_input("Band Width")); + params.set_output("SDF Grid", std::move(grid)); +#else + node_geo_exec_with_missing_openvdb(params); +#endif +} + +static void node_register() +{ + static bNodeType ntype; + + geo_node_type_base(&ntype, GEO_NODE_MESH_TO_SDF_GRID, "Mesh to SDF Grid", NODE_CLASS_GEOMETRY); + ntype.declare = node_declare; + ntype.geometry_node_execute = node_geo_exec; + nodeRegisterType(&ntype); +} +NOD_REGISTER_NODE(node_register) + +} // namespace blender::nodes::node_geo_mesh_to_sdf_grid_cc diff --git a/source/blender/nodes/geometry/nodes/node_geo_points_to_sdf_grid.cc b/source/blender/nodes/geometry/nodes/node_geo_points_to_sdf_grid.cc new file mode 100644 index 00000000000..b2b52e89e03 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_points_to_sdf_grid.cc @@ -0,0 +1,114 @@ +/* SPDX-FileCopyrightText: 2024 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BKE_volume.hh" +#include "BKE_volume_grid.hh" + +#include "GEO_points_to_volume.hh" + +#include "node_geometry_util.hh" + +namespace blender::nodes::node_geo_points_to_sdf_grid_cc { + +static void node_declare(NodeDeclarationBuilder &b) +{ + b.add_input("Points"); + b.add_input("Radius") + .default_value(0.5f) + .min(0.0f) + .subtype(PROP_DISTANCE) + .field_on_all(); + b.add_input("Voxel Size").default_value(0.3f).min(0.01f).subtype(PROP_DISTANCE); + b.add_output("SDF Grid"); +} + +#ifdef WITH_OPENVDB + +static void gather_positions_from_component(const GeometryComponent &component, + Vector &r_positions) +{ + if (component.is_empty()) { + return; + } + const VArray positions = *component.attributes()->lookup("position"); + r_positions.resize(r_positions.size() + positions.size()); + positions.materialize(r_positions.as_mutable_span().take_back(positions.size())); +} + +static void gather_radii_from_component(const GeometryComponent &component, + const Field radius_field, + Vector &r_radii) +{ + if (component.is_empty()) { + return; + } + + const bke::GeometryFieldContext field_context{component, AttrDomain::Point}; + const int domain_num = component.attribute_domain_size(AttrDomain::Point); + + r_radii.resize(r_radii.size() + domain_num); + fn::FieldEvaluator evaluator{field_context, domain_num}; + evaluator.add_with_destination(radius_field, r_radii.as_mutable_span().take_back(domain_num)); + evaluator.evaluate(); +} + +/** + * Initializes the VolumeComponent of a GeometrySet with a new Volume from points. + * The grid class should be either openvdb::GRID_FOG_VOLUME or openvdb::GRID_LEVEL_SET. + */ +static bke::VolumeGrid points_to_grid(const GeometrySet &geometry_set, + const Field &radius_field, + const float voxel_size) +{ + const double determinant = std::pow(double(voxel_size), 3.0); + if (!BKE_volume_grid_determinant_valid(determinant)) { + return {}; + } + + Vector positions; + Vector radii; + for (const GeometryComponent::Type type : {GeometryComponent::Type::Mesh, + GeometryComponent::Type::PointCloud, + GeometryComponent::Type::Curve}) + { + if (const GeometryComponent *component = geometry_set.get_component(type)) { + gather_positions_from_component(*component, positions); + gather_radii_from_component(*component, radius_field, radii); + } + } + + if (positions.is_empty()) { + return {}; + } + + return geometry::points_to_sdf_grid(positions, radii, voxel_size); +} + +#endif /* WITH_OPENVDB */ + +static void node_geo_exec(GeoNodeExecParams params) +{ +#ifdef WITH_OPENVDB + bke::VolumeGrid grid = points_to_grid(params.extract_input("Points"), + params.extract_input>("Radius"), + params.extract_input("Voxel Size")); + params.set_output("SDF Grid", std::move(grid)); +#else + node_geo_exec_with_missing_openvdb(params); +#endif +} + +static void node_register() +{ + static bNodeType ntype; + + geo_node_type_base( + &ntype, GEO_NODE_POINTS_TO_SDF_GRID, "Points to SDF Grid", NODE_CLASS_GEOMETRY); + ntype.declare = node_declare; + ntype.geometry_node_execute = node_geo_exec; + nodeRegisterType(&ntype); +} +NOD_REGISTER_NODE(node_register) + +} // namespace blender::nodes::node_geo_points_to_sdf_grid_cc diff --git a/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc b/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc index 18f8c876dee..f522a7c0d69 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc @@ -69,19 +69,6 @@ static float compute_voxel_size_from_amount(const float voxel_amount, return voxel_size; } -static void convert_to_grid_index_space(const float voxel_size, - MutableSpan positions, - MutableSpan radii) -{ - const float voxel_size_inv = 1.0f / voxel_size; - for (const int i : positions.index_range()) { - positions[i] *= voxel_size_inv; - /* Better align generated grid with source points. */ - positions[i] -= float3(0.5f); - radii[i] *= voxel_size_inv; - } -} - /** * Initializes the VolumeComponent of a GeometrySet with a new Volume from points. * The grid class should be either openvdb::GRID_FOG_VOLUME or openvdb::GRID_LEVEL_SET. @@ -128,8 +115,6 @@ static void initialize_volume_component_from_points(GeoNodeExecParams ¶ms, Volume *volume = reinterpret_cast(BKE_id_new_nomain(ID_VO, nullptr)); - convert_to_grid_index_space(voxel_size, positions, radii); - const float density = params.get_input("Density"); blender::geometry::fog_volume_grid_add_from_points( volume, "density", positions, radii, voxel_size, density);