From ce8f30f92cdf9d9cf8f7448ed8212581a565b9d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20T=C3=B6nne?= Date: Tue, 6 May 2025 16:08:24 +0200 Subject: [PATCH] Fix #138447: Invalid voxel size due to arbitrary threshold OpenVDB has a voxel size limit defined by the determinant of the grid transform, which is equivalent to a uniform voxel size of `sqrt3(3e-15) ~= 1.44e-5`. The `mesh_to_density_grid` function was using an arbitrary threshold of `1.0e-5` for the uniform voxel size. In this case the voxel size is `~1.343e-5` so it passes the Blender threshold but crashes in OpenVDB. This fix adds some convenience functions to check for valid grid voxel size and transform based on the same determinant metric. This is now employed consistently in the mesh_to_density_grid, mesh_to_sdf_grid, and points_to_sdf_grid functions to avoid exceptions in OpenVDB. MOD_volume_to_mesh, node_geo_volume_to_mesh, BKE_mesh_remesh_voxel have not been modified, since they have their own error checks with larger thresholds. Pull Request: https://projects.blender.org/blender/blender/pulls/138481 --- source/blender/blenkernel/BKE_volume.hh | 3 +++ source/blender/blenkernel/intern/volume.cc | 10 ++++++++++ source/blender/geometry/intern/mesh_to_volume.cc | 4 ++-- source/blender/geometry/intern/points_to_volume.cc | 4 ++++ .../geometry/nodes/node_geo_points_to_sdf_grid.cc | 3 +-- .../nodes/geometry/nodes/node_geo_points_to_volume.cc | 3 +-- .../nodes/geometry/nodes/node_geo_volume_cube.cc | 2 +- 7 files changed, 22 insertions(+), 7 deletions(-) diff --git a/source/blender/blenkernel/BKE_volume.hh b/source/blender/blenkernel/BKE_volume.hh index b128fed1353..68ee2f4d3b2 100644 --- a/source/blender/blenkernel/BKE_volume.hh +++ b/source/blender/blenkernel/BKE_volume.hh @@ -13,6 +13,7 @@ #include #include "BLI_bounds_types.hh" +#include "BLI_math_matrix_types.hh" #include "BLI_math_vector_types.hh" #include "BLI_memory_counter_fwd.hh" #include "BLI_string_ref.hh" @@ -118,6 +119,8 @@ void BKE_volume_grid_add(Volume *volume, const blender::bke::VolumeGridData &gri * OpenVDB crashes when the determinant of the transform matrix becomes too small. */ bool BKE_volume_grid_determinant_valid(double determinant); +bool BKE_volume_voxel_size_valid(const blender::float3 &voxel_size); +bool BKE_volume_grid_transform_valid(const blender::float4x4 &transform); /* Simplify */ int BKE_volume_simplify_level(const Depsgraph *depsgraph); diff --git a/source/blender/blenkernel/intern/volume.cc b/source/blender/blenkernel/intern/volume.cc index c0d80964b39..0ec7f0f1093 100644 --- a/source/blender/blenkernel/intern/volume.cc +++ b/source/blender/blenkernel/intern/volume.cc @@ -1029,6 +1029,16 @@ bool BKE_volume_grid_determinant_valid(const double determinant) #endif } +bool BKE_volume_voxel_size_valid(const float3 &voxel_size) +{ + return BKE_volume_grid_determinant_valid(voxel_size[0] * voxel_size[1] * voxel_size[2]); +} + +bool BKE_volume_grid_transform_valid(const float4x4 &transform) +{ + return BKE_volume_grid_determinant_valid(blender::math::determinant(transform)); +} + int BKE_volume_simplify_level(const Depsgraph *depsgraph) { if (DEG_get_mode(depsgraph) != DAG_EVAL_RENDER) { diff --git a/source/blender/geometry/intern/mesh_to_volume.cc b/source/blender/geometry/intern/mesh_to_volume.cc index 34e143114e4..5fc0713bcb9 100644 --- a/source/blender/geometry/intern/mesh_to_volume.cc +++ b/source/blender/geometry/intern/mesh_to_volume.cc @@ -119,7 +119,7 @@ static openvdb::FloatGrid::Ptr mesh_to_density_grid_impl( const float interior_band_width, const float density) { - if (voxel_size < 1e-5f) { + if (!BKE_volume_voxel_size_valid(float3(voxel_size))) { return nullptr; } @@ -174,7 +174,7 @@ bke::VolumeGrid mesh_to_sdf_grid(const Span positions, const float voxel_size, const float half_band_width) { - if (voxel_size <= 0.0f || half_band_width <= 0.0f) { + if (!BKE_volume_voxel_size_valid(float3(voxel_size)) || half_band_width <= 0.0f) { return {}; } diff --git a/source/blender/geometry/intern/points_to_volume.cc b/source/blender/geometry/intern/points_to_volume.cc index 326bdfce334..a52cd4a78bd 100644 --- a/source/blender/geometry/intern/points_to_volume.cc +++ b/source/blender/geometry/intern/points_to_volume.cc @@ -60,6 +60,10 @@ static openvdb::FloatGrid::Ptr points_to_sdf_grid_impl(const Span positi const Span radii, const float voxel_size) { + if (!BKE_volume_voxel_size_valid(float3(voxel_size))) { + return nullptr; + } + /* Create a new grid that will be filled. #ParticlesToLevelSet requires * the background value to be positive */ openvdb::FloatGrid::Ptr new_grid = openvdb::FloatGrid::create(1.0f); 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 index f326c7d978d..4c16608457c 100644 --- 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 @@ -61,8 +61,7 @@ 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)) { + if (!BKE_volume_voxel_size_valid(float3(voxel_size))) { return {}; } 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 4af09ba6c3a..e29d195a8d7 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 @@ -108,8 +108,7 @@ static void initialize_volume_component_from_points(GeoNodeExecParams ¶ms, BLI_assert_msg(0, "Unknown volume resolution mode"); } - const double determinant = std::pow(double(voxel_size), 3.0); - if (!BKE_volume_grid_determinant_valid(determinant)) { + if (!BKE_volume_voxel_size_valid(float3(voxel_size))) { return; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_volume_cube.cc b/source/blender/nodes/geometry/nodes/node_geo_volume_cube.cc index 2eb0c9959bd..1e0bdde6351 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_volume_cube.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_volume_cube.cc @@ -136,7 +136,7 @@ static void node_geo_exec(GeoNodeExecParams params) } const double3 scale_fac = double3(bounds_max - bounds_min) / double3(resolution - 1); - if (!BKE_volume_grid_determinant_valid(scale_fac.x * scale_fac.y * scale_fac.z)) { + if (!BKE_volume_voxel_size_valid(float3(scale_fac))) { params.error_message_add(NodeWarningType::Warning, TIP_("Volume scale is lower than permitted by OpenVDB")); params.set_default_remaining_outputs();