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:
committed by
Weizhen Huang
parent
f41a0d5ab9
commit
83dcaf0501
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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) /
|
||||
|
||||
Reference in New Issue
Block a user