Skip to content

volume_world_to_index: document int() truncation risk for FEM node placement #1323

@jf---

Description

@jf---

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:

  1. Document that int(wp.round(...)) is needed for exact index placement
  2. 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.

Metadata

Metadata

Assignees

Labels

docsImprovements or additions to documentation

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions