Fix: Mantaflow OpenVDB cache hollow volume artifacts

If an OpenVDB grid has an 8x8x8 block with the same value, it is stored as
a tile with a single value. Now iterate over the bounding box and copy the
value to all voxels for this case.

Fix #91174: Hollow emission artifacts
Fix #124064: Hollow density artifacts

Pull Request: https://projects.blender.org/blender/blender/pulls/139231
This commit is contained in:
Bartosz Kosiorek
2025-06-02 16:20:43 +02:00
committed by Brecht Van Lommel
parent 6e3b483c6d
commit f2ad6b1ef0
3 changed files with 63 additions and 2 deletions

View File

@@ -7,6 +7,7 @@ Local modifications:
* ./patches/local_namespace.diff to support loading MANTA variables into an isolated __main__ name-space.
* ./patches/fix-computation-errors.patch to fix computation errors for normalization functions for 3d vectors by using std::hypot.
* ./patches/fluid-viscosity-performance.patch improve fluid viscosity performance by moving var checking outside loop.
* ./patches/import-openvdb-empty-cubes-fix.patch to fix OpenVDB import visual glitches, by copying full 8x8x8 nodes.
* ./patches/precision-of-4d-vector.patch to increase precision of 4D vector normalization functions.
* ./patches/liquid-mesh-performance.patch improve liquid mesh generation by puting calculation of inverse radius outside for loops.
* ./patches/liquid-performance.patch improve liquid generation (without mesh) by precalculate sum of vectors and put it outside for loop.

View File

@@ -0,0 +1,46 @@
commit 725df6eb883dadf2225938baecf97c005da5b549
Author: Bartosz Kosiorek <gang65@poczta.onet.pl>
Date: Wed May 21 22:44:01 2025 +0200
Physics: Fix OpenVDB import visual glitches, by copying full 8x8x8 nodes
If grid has 8x8x8 block with the same value, it is stored as Tile with single value.
We need to iterate over the bounding box and copy such value to all voxels in 8x8x8 node.
Fixes: #91174 #124064
diff --git a/extern/mantaflow/preprocessed/fileio/iovdb.cpp b/extern/mantaflow/preprocessed/fileio/iovdb.cpp
index 4b7463782da..85ab3781e5a 100644
--- a/extern/mantaflow/preprocessed/fileio/iovdb.cpp
+++ b/extern/mantaflow/preprocessed/fileio/iovdb.cpp
@@ -54,14 +54,28 @@ template<class GridType, class T> void importVDB(typename GridType::Ptr from, Gr
using ValueT = typename GridType::ValueType;
// Check if current grid is to be read as a sparse grid, active voxels (only) will be copied
+
if (to->saveSparse()) {
to->clear(); // Ensure that destination grid is empty before writing
for (typename GridType::ValueOnCIter iter = from->cbeginValueOn(); iter.test(); ++iter) {
ValueT vdbValue = *iter;
- openvdb::Coord coord = iter.getCoord();
T toMantaValue;
convertFrom(vdbValue, &toMantaValue);
- to->set(coord.x(), coord.y(), coord.z(), toMantaValue);
+ // #91174 #124064 - Check if iteration is Voxel or Tile
+ if (iter.isVoxelValue()) {
+ openvdb::Coord coord = iter.getCoord();
+ to->set(coord.x(), coord.y(), coord.z(), toMantaValue);
+ }
+ else {
+ openvdb::CoordBBox bbox;
+ iter.getBoundingBox(bbox);
+ // If grid has 8x8x8 block with the same value, it is stored as Tile with single value.
+ // We need to iterate over the bounding box and copy such value to all voxels in 8x8x8 node.
+ for (openvdb::CoordBBox::Iterator<true> ijk(bbox); ijk; ++ijk) {
+ openvdb::Coord coord = *ijk;
+ to->set(coord.x(), coord.y(), coord.z(), toMantaValue);
+ }
+ }
}
}
// When importing all grid cells, using a grid accessor is usually faster than a value iterator

View File

@@ -54,14 +54,28 @@ template<class GridType, class T> void importVDB(typename GridType::Ptr from, Gr
using ValueT = typename GridType::ValueType;
// Check if current grid is to be read as a sparse grid, active voxels (only) will be copied
if (to->saveSparse()) {
to->clear(); // Ensure that destination grid is empty before writing
for (typename GridType::ValueOnCIter iter = from->cbeginValueOn(); iter.test(); ++iter) {
ValueT vdbValue = *iter;
openvdb::Coord coord = iter.getCoord();
T toMantaValue;
convertFrom(vdbValue, &toMantaValue);
to->set(coord.x(), coord.y(), coord.z(), toMantaValue);
// #91174 #124064 - Check if iteration is Voxel or Tile
if (iter.isVoxelValue()) {
openvdb::Coord coord = iter.getCoord();
to->set(coord.x(), coord.y(), coord.z(), toMantaValue);
}
else {
openvdb::CoordBBox bbox;
iter.getBoundingBox(bbox);
// If grid has 8x8x8 block with the same value, it is stored as Tile with single value.
// We need to iterate over the bounding box and copy such value to all voxels in 8x8x8 node.
for (openvdb::CoordBBox::Iterator<true> ijk(bbox); ijk; ++ijk) {
openvdb::Coord coord = *ijk;
to->set(coord.x(), coord.y(), coord.z(), toMantaValue);
}
}
}
}
// When importing all grid cells, using a grid accessor is usually faster than a value iterator