Skip to content

Make voxel collision queries generic over the voxel storage with a VoxelQuery trait - #445

Open
0xbeefd1ed wants to merge 9 commits into
dimforge:masterfrom
0xbeefd1ed:generic-voxels
Open

Make voxel collision queries generic over the voxel storage with a VoxelQuery trait#445
0xbeefd1ed wants to merge 9 commits into
dimforge:masterfrom
0xbeefd1ed:generic-voxels

Conversation

@0xbeefd1ed

@0xbeefd1ed 0xbeefd1ed commented Sep 7, 2026

Copy link
Copy Markdown

Summary

Parry's voxel collision algorithms were written directly against a concrete Voxels shape. Anyone with their own sparse voxel structure (a chunked grid, an octree, a VDB-style tree) had to copy it into a Voxels before they could get contacts, intersection tests, or shape-casts against it.

This PR introduces a VoxelQuery trait that abstracts the storage, and rewrites the voxel query functions to take any V: ?Sized + VoxelQuery instead of &Voxels. The existing Voxels shape implements the trait, so calls that pass a &Voxels keep working unchanged.

What changed

  • VoxelQuery trait (src/shape/voxels/voxel_query.rs). Implementors provide voxel_size, domain, and voxels_in_range. Grid helpers (voxel_at_point, voxel_center, voxel_aabb, voxel_range_intersecting_local_aabb, align_aabb_to_grid, local_aabb, and the aabb-based iterators) have default implementations derived from those three.
  • QueriedVoxel trait, the per-voxel view a storage hands out through the VoxelQuery::Voxel<'a> associated type. Views may borrow from the storage, so a sparse tree can compute voxel_state() lazily from leaf-local context. The cheap voxel_type() is what bulk iteration reads; the full voxel_state() is only requested for contact-candidate voxels.
  • Generic query functions. contact_manifolds_voxels_{shape,ball,composite_shape,voxels}, intersection_test_{voxels_shape,shape_voxels}, cast_shapes_{voxels_shape,shape_voxels}, cast_shapes_nonlinear_{voxels_shape,shape_voxels}, and MassProperties::from_voxels now take a VoxelQuery storage. The 2D and 3D to_outline, to_polyline, and to_trimesh conversions read through QueriedVoxel as well.
  • Voxels implements VoxelQuery with VoxelData as its view, and VoxelData implements QueriedVoxel.
  • VoxelState::with_filled_neighbors(AxisMask) builds a filled voxel's state from the set of its filled axis-aligned neighbors, for storages that only track occupancy.
  • Default for VoxelType (Empty) and VoxelState (EMPTY).
  • contact_manifolds_voxels_ball is now re-exported from parry::query alongside the other voxel manifold functions.

Test plan

  • cargo test -p parry2d and cargo test -p parry3d pass on all four crate variants.
  • cargo test --doc passes, including the new VoxelState::with_filled_neighbors example.
  • RUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps passes.
  • Existing voxel regression tests (issue_345, issue_373, issue_382, issue_404) still pass against the Voxels implementation of the trait.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant