-
Notifications
You must be signed in to change notification settings - Fork 473
volume_world_to_index: document int() truncation risk for FEM node placement #1323
Description
Summary
When using volume_world_to_index to map positions to voxel indices for discrete value storage (rather than continuous field sampling), int() truncation of the returned float coordinates silently produces wrong indices at non-power-of-2 grid resolutions.
Reproduction
import warp as wp
# Domain [0,1] with 20 voxels → voxel_size = 0.05
vol = wp.Volume.allocate(min=[0,0,0], max=[19,0,0], voxel_size=0.05)
@wp.kernel
def demo(vol_id: wp.uint64):
# Position at x=1.0 → expected index 20
uvw = wp.volume_world_to_index(vol_id, wp.vec3(1.0, 0.0, 0.0))
# float32: 1.0 / 0.05_f32 = 19.999998...
idx_truncated = int(uvw[0]) # → 19 (WRONG)
idx_rounded = int(wp.round(uvw[0])) # → 20 (correct)Impact
For SDF/density storage, this is irrelevant — trilinear interpolation smooths over sub-voxel errors. But when using volume_store_f to write discrete values at specific positions and later reading them back with volume_sample_f(CLOSEST), the stored value ends up in the wrong voxel. The readback returns the background value instead of the stored value.
Suggestion
Either:
- Document that
int(wp.round(...))is needed for exact index placement - Provide an integer-returning variant:
volume_world_to_index_i(vol, pos) → vec3i
Context
Discovered while using NanoVDB volumes for data transfer between different spatial discretizations. The bug only manifests on non-power-of-2 grid resolutions with float32 voxel sizes.