Fix #144610: Cycles: do not convert open volume mesh to sdf

because we can't determine the interior. Sample densities in the whole
bounding box instead.

Pull Request: https://projects.blender.org/blender/blender/pulls/144732
This commit is contained in:
Weizhen Huang
2025-08-19 13:26:11 +02:00
committed by Weizhen Huang
parent f41a0d5ab9
commit 83dcaf0501
2 changed files with 51 additions and 1 deletions

View File

@@ -105,7 +105,7 @@ static bool vdb_voxel_intersect(const float3 p_min,
const openvdb::tools::FindActiveValues<openvdb::BoolTree> &find)
{
if (grid->empty()) {
/* Non-mesh volume. */
/* Non-mesh volume or open mesh. */
return true;
}

View File

@@ -655,6 +655,50 @@ bool VolumeManager::is_homogeneous_volume(const Object *object, const Shader *sh
}
#ifdef WITH_OPENVDB
/* Given a mesh, check if every edge has exactly two incident triangles, and if the two triangles
* have the same orientation. */
static bool mesh_is_closed(const std::vector<openvdb::Vec3I> &triangles)
{
const size_t num_triangles = triangles.size();
if (num_triangles % 2) {
return false;
}
/* Store the two vertices that forms an edge. */
std::multiset<std::pair<int, int>> edges;
int num_edges = 0;
for (const auto &tri : triangles) {
for (int i = 0; i < 3; i++) {
const std::pair<int, int> e = {tri[i], tri[(i + 1) % 3]};
if (edges.count(e)) {
/* Same edge exists. */
return false;
}
/* Check if an edge in the opposite order exists. */
const auto count = edges.count({e.second, e.first});
if (count > 1) {
/* Edge has more than 2 incident faces. */
return false;
}
if (count == 1) {
/* If an edge in the opposite order exists, increment the count. */
edges.insert({e.second, e.first});
}
else {
/* Insert a new edge. */
num_edges++;
edges.insert(e);
}
}
}
/* Until this point, the count of each element in the set is at most 2; to check if they are
* exactly 2, we just need to compare the total numbers. */
return num_triangles * 3 == num_edges * 2;
}
openvdb::BoolGrid::ConstPtr VolumeManager::mesh_to_sdf_grid(const Mesh *mesh,
const Shader *shader,
const float half_width)
@@ -679,6 +723,12 @@ openvdb::BoolGrid::ConstPtr VolumeManager::mesh_to_sdf_grid(const Mesh *mesh,
}
}
if (!mesh_is_closed(triangles)) {
/* `meshToLevelSet()` requires a closed mesh, otherwise we can not determine the interior of
* the mesh. Evaluate the whole bounding box in this case. */
return openvdb::BoolGrid::create();
}
/* TODO(weizhen): Should consider object instead of mesh size. */
const float3 mesh_size = mesh->bounds.size();
const auto vdb_voxel_size = openvdb::Vec3d(mesh_size.x, mesh_size.y, mesh_size.z) /