AcademySoftwareFoundation / AcademySoftwareFoundation/openvdb
Wrong interior values after translating a levelset.
- Dominant language
- C++
- Stars
- 3.4k
- Forks
- 774
- Avg merge
- 3d 9h
- Merged PRs (30d)
- 34
Description
### Environment
**Operating System:** Windows 10
**Version / Commit SHA:** 33813dbef87734a7f0f70ca4cfed69474bce84fe
**Other:** Compiler: Microsoft Visual Studio 2019
### Describe the bug
After applying a transform to a levelset, the values in the interior may be wrong. If an asymmetric shell width is used, the value will be the exterior shell width rather than the interior shell width.
The bug is not reproducible without the transform.
### To Reproduce
The following test case reproduces the issue:
This is a variant of the `TestMeshToVolume.testConversion` test case.
```c++
TEST_F(TestMeshToVolume, testShell)
{
using namespace openvdb;
std::vector points;
std::vector quads;
// cube vertices
points.push_back(Vec3s(-4.f, -4.f, -4.f)); // 0 6--------7
points.push_back(Vec3s( 4.f, -4.f, -4.f)); // 1 /| /|
points.push_back(Vec3s(-4.f, 4.f, -4.f)); // 2 2--------3 |
points.push_back(Vec3s( 4.f, 4.f, -4.f)); // 3 | | | |
points.push_back(Vec3s(-4.f, -4.f, 4.f)); // 4 | 4------|-5
points.push_back(Vec3s( 4.f, -4.f, 4.f)); // 5 |/ |/
points.push_back(Vec3s(-4.f, 4.f, 4.f)); // 6 0--------1
points.push_back(Vec3s( 4.f, 4.f, 4.f)); // 7
// cube faces
quads.push_back(Vec4I(0, 1, 3, 2)); // front
quads.push_back(Vec4I(5, 4, 6, 7)); // back
quads.push_back(Vec4I(0, 2, 6, 4)); // left
quads.push_back(Vec4I(1, 5, 7, 3)); // right
quads.push_back(Vec4I(2, 3, 7, 6)); // top
quads.push_back(Vec4I(0, 4, 5, 1)); // bottom
math::Transform::Ptr xform = math::Transform::createLinearTransform();
tools::QuadAndTriangleDataAdapter mesh(points, quads);
// Conversion with asymmetric shell width
FloatGrid::Ptr grid = tools::meshToVolume(mesh, *xform, 6.f, 3.f);
EXPECT_TRUE(grid.get() != NULL);
EXPECT_EQ(int(GRID_LEVEL_SET), int(grid->getGridClass()));
// verify background values in the interior and exterior of the shell
EXPECT_EQ(grid->tree().getValue({-9, -9, -9}), 6); // ✅
EXPECT_EQ(grid->tree().getValue({0, 0, 0}), -3); // ✅
EXPECT_EQ(grid->tree().getValue({9, 9, 9}), 6); // ✅
// create translated copy
auto editedGrid = FloatGrid::create();
tools::GridTransformer translate(
Vec3R(0,0,0), Vec3R(1,1,1), Vec3R(0,0,0), Vec3R(9, 9, 9));
translate.setThreaded(true);
translate.setTransformTiles(true);
translate.transformGrid(*grid, *editedGrid);
// verify background values in the interior and exterior of the shell
EXPECT_EQ(editedGrid->tree().getValue({0, 0, 0}), 6); // ✅
EXPECT_EQ(editedGrid->tree().getValue({9, 9, 9}), -3); // ❌ (value is actually -6)
EXPECT_EQ(editedGrid->tree().getValue({18, 18, 18}), 6); // ✅
}
```
The background value in the interior in this case is too low, this creates a jump in the values in the shell (it jumps abruptly from -3 to -6), creating an invalid signed distance field.
Contributor guide
Research direction
Start from the TestMeshToVolume.testConversion test case and its testShell variant in the issue, then inspect tools::meshToVolume and tools::GridTransformer::transformGrid with PointSampler. Reproduce the asymmetric shell-width case, compare the translated grid's interior values with the original, and add a regression test showing that the translated interior remains -3 rather than -6.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- computer-graphics
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 45/100