openvdb icon indicating copy to clipboard operation
openvdb copied to clipboard

[BUG] NaN handling in background change

Open Xilef11 opened this issue 1 year ago • 0 comments

Environment

Operating System: Ubuntu 22.04 Version / Commit SHA: v9.1.0 Other: Using the Python bindings

Describe the bug

When setting the background value of a (Float) grid, if the previous background value was NaN, the values of all inactive voxels get changed to the new value.

To Reproduce

Example script:

import pyopenvdb as vdb
import math
import itertools

grid = vdb.FloatGrid()
grid.background = 0.0

accessor = grid.getAccessor()
# create a few blocks of active voxels
on_list = [(5,5,5), (-5,-5,-5)]
for coords in on_list:
    accessor.setValueOn(coords, 1.0)

# set a few off voxels
off_list = [(-2,-2,-2),(2,2,2)]
for coords in off_list:
    accessor.setValueOff(coords, 5.0)

# check values
unchanged = [(0,0,0)]
print("** initial values **")
for coords in itertools.chain(on_list, off_list, unchanged):
    print(f"Voxel {coords} is {accessor.probeValue(coords)}")

# change background
grid.background = -1.0
print("** after background change to -1.0 **")  # here, our custom inactive voxels are still at 5.0
# check values
for coords in itertools.chain(on_list, off_list, unchanged):
    print(f"Voxel {coords} is {accessor.probeValue(coords)}")

# change background again
grid.background = math.nan
print("** after background change to nan **")  # still at 5.0
# check values
for coords in itertools.chain(on_list, off_list, unchanged):
    print(f"Voxel {coords} is {accessor.probeValue(coords)}")

# change background again
grid.background = -12.0
print("** after background change to -12 **")  # changed from 5.0 to -12
# check values
for coords in itertools.chain(on_list, off_list, unchanged):
    print(f"Voxel {coords} is {accessor.probeValue(coords)}")

Output:

** initial values **
Voxel (5, 5, 5) is (1.0, True)
Voxel (-5, -5, -5) is (1.0, True)
Voxel (-2, -2, -2) is (5.0, False)
Voxel (2, 2, 2) is (5.0, False)
Voxel (0, 0, 0) is (0.0, False)
** after background change to -1.0 **
Voxel (5, 5, 5) is (1.0, True)
Voxel (-5, -5, -5) is (1.0, True)
Voxel (-2, -2, -2) is (5.0, False)
Voxel (2, 2, 2) is (5.0, False)
Voxel (0, 0, 0) is (-1.0, False)
** after background change to nan **
Voxel (5, 5, 5) is (1.0, True)
Voxel (-5, -5, -5) is (1.0, True)
Voxel (-2, -2, -2) is (5.0, False)
Voxel (2, 2, 2) is (5.0, False)
Voxel (0, 0, 0) is (nan, False)
** after background change to -12 **
Voxel (5, 5, 5) is (1.0, True)
Voxel (-5, -5, -5) is (1.0, True)
Voxel (-2, -2, -2) is (-12.0, False)
Voxel (2, 2, 2) is (-12.0, False)
Voxel (0, 0, 0) is (-12.0, False)

Expected behavior

Inactive voxels with a value different from the previous background value should not be changed when the background value is changed. This is specified in the documentation of tools::changeBackground which gets called when setting grid.background through the Python API

Additional context

As a side note, it is unclear from the python API that setting grid.background will change the values (by calling tools::changeBackground) instead of setting a reference value. Understanding this behaviour required digging through the pyopenvdb source code. https://github.com/AcademySoftwareFoundation/openvdb/blob/de7a496febd51ce142d9321ab4fff42da0a8a375/openvdb/openvdb/python/pyGrid.h#L1476 https://github.com/AcademySoftwareFoundation/openvdb/blob/de7a496febd51ce142d9321ab4fff42da0a8a375/openvdb/openvdb/python/pyGrid.h#L119

Xilef11 avatar Sep 20 '24 15:09 Xilef11