feat: add support for Voxels collider (#823)

* feat: start adding voxels support and some additional testbed demo settings

* feat: add support for parry’s new Voxels collider shape

* fix voxels demos

* feat: support rectangular voxels and additional voxels initialization

* chore: switch to parry 0.20

* chore: fix cargo doc

* Fix testbed build
This commit is contained in:
Sébastien Crozet
2025-04-24 12:11:53 +02:00
committed by GitHub
parent 1c67c5e7f2
commit e44f636249
27 changed files with 891 additions and 223 deletions

View File

@@ -1,4 +1,6 @@
use crate::dynamics::{CoefficientCombineRule, MassProperties, RigidBodyHandle};
#[cfg(feature = "dim3")]
use crate::geometry::HeightFieldFlags;
use crate::geometry::{
ActiveCollisionTypes, BroadPhaseProxyIndex, ColliderBroadPhaseData, ColliderChanges,
ColliderFlags, ColliderMassProps, ColliderMaterial, ColliderParent, ColliderPosition,
@@ -10,10 +12,8 @@ use crate::pipeline::{ActiveEvents, ActiveHooks};
use crate::prelude::ColliderEnabled;
use na::Unit;
use parry::bounding_volume::{Aabb, BoundingVolume};
use parry::shape::{Shape, TriMeshBuilderError, TriMeshFlags};
#[cfg(feature = "dim3")]
use crate::geometry::HeightFieldFlags;
use parry::shape::{Shape, TriMeshBuilderError, TriMeshFlags, VoxelPrimitiveGeometry};
use parry::transformation::voxelization::FillMode;
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
#[derive(Clone, Debug)]
@@ -573,6 +573,55 @@ impl ColliderBuilder {
Self::new(SharedShape::halfspace(outward_normal))
}
/// Initializes a shape made of voxels.
///
/// Each voxel has the size `voxel_size` and grid coordinate given by `centers`.
/// The `primitive_geometry` controls the behavior of collision detection at voxels boundaries.
///
/// For initializing a voxels shape from points in space, see [`Self::voxels_from_points`].
/// For initializing a voxels shape from a mesh to voxelize, see [`Self::voxelized_mesh`].
pub fn voxels(
primitive_geometry: VoxelPrimitiveGeometry,
voxel_size: Vector<Real>,
voxels: &[Point<i32>],
) -> Self {
Self::new(SharedShape::voxels(primitive_geometry, voxel_size, voxels))
}
/// Initializes a collider made of voxels.
///
/// Each voxel has the size `voxel_size` and contains at least one point from `centers`.
/// The `primitive_geometry` controls the behavior of collision detection at voxels boundaries.
pub fn voxels_from_points(
primitive_geometry: VoxelPrimitiveGeometry,
voxel_size: Vector<Real>,
points: &[Point<Real>],
) -> Self {
Self::new(SharedShape::voxels_from_points(
primitive_geometry,
voxel_size,
points,
))
}
/// Initializes a voxels obtained from the decomposition of the given trimesh (in 3D)
/// or polyline (in 2D) into voxelized convex parts.
pub fn voxelized_mesh(
primitive_geometry: VoxelPrimitiveGeometry,
vertices: &[Point<Real>],
indices: &[[u32; DIM]],
voxel_size: Real,
fill_mode: FillMode,
) -> Self {
Self::new(SharedShape::voxelized_mesh(
primitive_geometry,
vertices,
indices,
voxel_size,
fill_mode,
))
}
/// Initialize a new collider builder with a cylindrical shape defined by its half-height
/// (along the Y axis) and its radius.
#[cfg(feature = "dim3")]

View File

@@ -17,7 +17,7 @@ pub use self::narrow_phase::NarrowPhase;
pub use parry::bounding_volume::BoundingVolume;
pub use parry::query::{PointQuery, PointQueryWithLocation, RayCast, TrackedContact};
pub use parry::shape::SharedShape;
pub use parry::shape::{SharedShape, VoxelPrimitiveGeometry, VoxelState, VoxelType, Voxels};
use crate::math::{Real, Vector};

View File

@@ -459,6 +459,10 @@ impl DebugRenderPipeline {
let vtx = s.to_polyline(self.style.border_subdivisions);
backend.draw_line_strip(object, &vtx, pos, &Vector::repeat(1.0), color, true)
}
TypedShape::Voxels(s) => {
let (vtx, idx) = s.to_polyline();
backend.draw_polyline(object, &vtx, &idx, pos, &Vector::repeat(1.0), color)
}
TypedShape::Custom(_) => {}
}
}
@@ -613,6 +617,10 @@ impl DebugRenderPipeline {
let (vtx, idx) = s.to_outline(self.style.border_subdivisions);
backend.draw_polyline(object, &vtx, &idx, pos, &Vector::repeat(1.0), color)
}
TypedShape::Voxels(s) => {
let (vtx, idx) = s.to_outline();
backend.draw_polyline(object, &vtx, &idx, pos, &Vector::repeat(1.0), color)
}
TypedShape::Custom(_) => {}
}
}