pub struct VHACD { /* private fields */ }Expand description
Approximate convex decomposition using the VHACD algorithm.
This structure holds the result of the V-HACD (Volumetric Hierarchical Approximate Convex Decomposition) algorithm, which decomposes a concave shape into multiple approximately-convex parts.
§Overview
The VHACD struct stores the decomposition result as a collection of voxelized parts,
where each part is approximately convex. These parts can be converted to convex hulls
for use in collision detection and physics simulation.
§Basic Workflow
- Decompose: Create a
VHACDinstance usingVHACD::decomposeorVHACD::from_voxels - Access Parts: Get the voxelized parts using
voxel_parts - Generate Hulls: Compute convex hulls with
compute_convex_hullsorcompute_exact_convex_hulls
§Examples
§Basic Usage
use parry3d::math::Point;
use parry3d::transformation::vhacd::{VHACD, VHACDParameters};
// Define a simple mesh (tetrahedron)
let vertices = vec![
Point::new(0.0, 0.0, 0.0),
Point::new(1.0, 0.0, 0.0),
Point::new(0.5, 1.0, 0.0),
Point::new(0.5, 0.5, 1.0),
];
let indices = vec![
[0, 1, 2], [0, 2, 3], [0, 3, 1], [1, 3, 2],
];
// Decompose with default parameters
let decomposition = VHACD::decompose(
&VHACDParameters::default(),
&vertices,
&indices,
false,
);
// Access the results
println!("Generated {} parts", decomposition.voxel_parts().len());
// Get convex hulls for collision detection
let hulls = decomposition.compute_convex_hulls(4);§With Custom Parameters
use parry3d::math::Point;
use parry3d::transformation::vhacd::{VHACD, VHACDParameters};
// High-quality decomposition settings
let params = VHACDParameters {
resolution: 128,
concavity: 0.001,
max_convex_hulls: 32,
..Default::default()
};
let decomposition = VHACD::decompose(¶ms, &vertices, &indices, false);§See Also
VHACDParameters: Configuration for the decomposition algorithmcompute_convex_hulls: Generate convex hulls from voxelscompute_exact_convex_hulls: Generate hulls from original mesh- Module documentation:
crate::transformation::vhacd
Implementations§
Source§impl VHACD
impl VHACD
Sourcepub fn decompose(
params: &VHACDParameters,
points: &[Point<f32>],
indices: &[[u32; 3]],
keep_voxel_to_primitives_map: bool,
) -> Self
pub fn decompose( params: &VHACDParameters, points: &[Point<f32>], indices: &[[u32; 3]], keep_voxel_to_primitives_map: bool, ) -> Self
Decompose the given polyline (in 2D) or triangle mesh (in 3D).
This is the primary method for performing approximate convex decomposition. It takes a mesh defined by vertices and indices, voxelizes it, and decomposes it into approximately-convex parts using the V-HACD algorithm.
§Parameters
-
params- Configuration parameters controlling the decomposition process. SeeVHACDParametersfor details on each parameter. -
points- The vertex positions of your mesh (3D) or polyline (2D). Each point represents a vertex in world space. -
indices- The connectivity information:- 3D: Triangle indices
[u32; 3]- each entry defines a triangle using 3 vertex indices - 2D: Segment indices
[u32; 2]- each entry defines a line segment using 2 vertex indices
- 3D: Triangle indices
-
keep_voxel_to_primitives_map- Whether to maintain a mapping between voxels and the original mesh primitives (triangles/segments) they intersect.true: Enablescompute_exact_convex_hullswhich uses original mesh geometry for more accurate results. Uses more memory.false: Only voxel-based hulls available viacompute_convex_hulls. More memory efficient.
§Returns
A VHACD instance containing the decomposition results. Use voxel_parts
to access the raw voxelized parts, or compute_convex_hulls
to generate convex hull geometry.
§Performance
Decomposition time depends primarily on:
resolution: Higher = slower (cubic scaling in 3D)max_convex_hulls: More parts = more splits = longer time- Mesh complexity: More vertices/triangles = slower voxelization
Typical times (on modern CPU):
- Simple mesh (1K triangles, resolution 64): 100-500ms
- Complex mesh (10K triangles, resolution 128): 1-5 seconds
- Very complex (100K triangles, resolution 256): 10-60 seconds
§Examples
§Basic Decomposition
use parry3d::math::Point;
use parry3d::transformation::vhacd::{VHACD, VHACDParameters};
// Simple L-shaped mesh
let vertices = vec![
Point::new(0.0, 0.0, 0.0), Point::new(2.0, 0.0, 0.0),
Point::new(2.0, 1.0, 0.0), Point::new(1.0, 1.0, 0.0),
];
let indices = vec![
[0, 1, 2], [0, 2, 3],
];
let decomposition = VHACD::decompose(
&VHACDParameters::default(),
&vertices,
&indices,
false, // Don't need exact hulls
);
println!("Parts: {}", decomposition.voxel_parts().len());§With Exact Hull Generation
use parry3d::math::Point;
use parry3d::transformation::vhacd::{VHACD, VHACDParameters};
// Enable voxel-to-primitive mapping for exact hulls
let decomposition = VHACD::decompose(
&VHACDParameters::default(),
&vertices,
&indices,
true, // <-- Enable for exact hulls
);
// Now we can compute exact hulls using original mesh
let exact_hulls = decomposition.compute_exact_convex_hulls(&vertices, &indices);§Custom Parameters
use parry3d::math::Point;
use parry3d::transformation::vhacd::{VHACD, VHACDParameters};
// High-quality settings for important objects
let params = VHACDParameters {
resolution: 128, // High detail
concavity: 0.001, // Tight fit
max_convex_hulls: 32, // Allow many parts
..Default::default()
};
let decomposition = VHACD::decompose(¶ms, &vertices, &indices, false);§See Also
VHACDParameters: Detailed parameter documentationfrom_voxels: Decompose pre-voxelized datacompute_convex_hulls: Generate voxel-based hullscompute_exact_convex_hulls: Generate mesh-based hulls
Sourcepub fn from_voxels(params: &VHACDParameters, voxels: VoxelSet) -> Self
pub fn from_voxels(params: &VHACDParameters, voxels: VoxelSet) -> Self
Perform an approximate convex decomposition of a pre-voxelized set of voxels.
This method allows you to decompose a shape that has already been voxelized, bypassing the voxelization step. This is useful if you:
- Already have voxelized data from another source
- Want to decompose the same voxelization with different parameters
- Need more control over the voxelization process
§Parameters
-
params- Configuration parameters for the decomposition algorithm. SeeVHACDParametersfor details. -
voxels- A pre-voxelized volume represented as aVoxelSet. You can create this usingVoxelizedVolume::voxelizeor other voxelization methods.
§Returns
A VHACD instance containing the decomposition results.
§Examples
use parry3d::math::Point;
use parry3d::transformation::vhacd::{VHACD, VHACDParameters};
use parry3d::transformation::voxelization::{VoxelizedVolume, FillMode};
// First, voxelize the mesh manually
let voxelized = VoxelizedVolume::voxelize(
&vertices,
&indices,
64, // resolution
FillMode::FloodFill {
detect_cavities: false,
},
false, // don't keep primitive mapping
);
// Then decompose the voxels
let decomposition = VHACD::from_voxels(
&VHACDParameters::default(),
voxelized.into(),
);§See Also
decompose: Decompose directly from mesh (includes voxelization)VoxelizedVolume: For manual voxelizationVoxelSet: The voxel data structure
Sourcepub fn voxel_parts(&self) -> &[VoxelSet]
pub fn voxel_parts(&self) -> &[VoxelSet]
Returns the approximately-convex voxelized parts computed by the VHACD algorithm.
Each part in the returned slice represents an approximately-convex region of the original shape, stored as a set of voxels. These voxelized parts are the direct result of the decomposition algorithm.
§Returns
A slice of VoxelSet structures, where each set represents one convex part.
The number of parts depends on the shape’s complexity and the parameters used
(especially concavity and max_convex_hulls).
§Usage
You typically don’t use the voxel parts directly for collision detection. Instead:
- Use
compute_convex_hullsfor voxel-based convex hulls - Use
compute_exact_convex_hullsfor mesh-based hulls
However, accessing voxel parts directly is useful for:
- Debugging and visualization of the decomposition
- Custom processing of the voxelized representation
- Understanding how the algorithm divided the shape
§Examples
use parry3d::math::Point;
use parry3d::transformation::vhacd::{VHACD, VHACDParameters};
let decomposition = VHACD::decompose(
&VHACDParameters::default(),
&vertices,
&indices,
false,
);
let parts = decomposition.voxel_parts();
println!("Generated {} convex parts", parts.len());
// Inspect individual parts
for (i, part) in parts.iter().enumerate() {
println!("Part {}: {} voxels", i, part.voxels().len());
}§See Also
VoxelSet: The voxel data structurecompute_convex_hulls: Convert to collision-ready convex hulls
Sourcepub fn compute_primitive_intersections(
&self,
points: &[Point<f32>],
indices: &[[u32; 3]],
) -> Vec<Vec<Point<f32>>>
pub fn compute_primitive_intersections( &self, points: &[Point<f32>], indices: &[[u32; 3]], ) -> Vec<Vec<Point<f32>>>
Compute the intersections between the voxelized convex part of this decomposition, and all the primitives from the original decomposed polyline/trimesh,
This will panic if keep_voxel_to_primitives_map was set to false when initializing
self.
Sourcepub fn compute_exact_convex_hulls(
&self,
points: &[Point<f32>],
indices: &[[u32; 3]],
) -> Vec<(Vec<Point<f32>>, Vec<[u32; 3]>)>
pub fn compute_exact_convex_hulls( &self, points: &[Point<f32>], indices: &[[u32; 3]], ) -> Vec<(Vec<Point<f32>>, Vec<[u32; 3]>)>
Compute exact convex hulls using the original mesh geometry (3D version).
This method generates convex hulls for each decomposed part by computing the convex hull of the intersection between the voxelized part and the original triangle mesh primitives. This produces more accurate hulls than the voxel-based method, preserving the original geometry’s detail.
§Requirements
This method requires that keep_voxel_to_primitives_map was set to true when calling
VHACD::decompose. If it was false, this method will panic.
§Parameters
points- The same vertex buffer used when callingVHACD::decomposeindices- The same index buffer (triangle indices[u32; 3]) used when callingVHACD::decompose
§Returns
A vector of convex hulls (one per decomposed part), where each hull is represented as
a tuple (vertices, indices):
vertices:Vec<Point<Real>>- The hull verticesindices:Vec<[u32; 3]>- Triangle indices defining the hull surface
§Performance
This is more expensive than compute_convex_hulls because
it needs to compute intersections with the original primitives and then compute convex hulls.
However, it produces more accurate results that better match the original mesh.
§Examples
use parry3d::math::Point;
use parry3d::transformation::vhacd::{VHACD, VHACDParameters};
// IMPORTANT: Set keep_voxel_to_primitives_map to true
let decomposition = VHACD::decompose(
&VHACDParameters::default(),
&vertices,
&indices,
true, // <-- Required for exact hulls
);
// Compute exact convex hulls using original geometry
let exact_hulls = decomposition.compute_exact_convex_hulls(&vertices, &indices);
for (i, (verts, tris)) in exact_hulls.iter().enumerate() {
println!("Hull {}: {} vertices, {} triangles", i, verts.len(), tris.len());
}§Panics
Panics if keep_voxel_to_primitives_map was false during decomposition.
§See Also
compute_convex_hulls: Faster voxel-based hullscompute_primitive_intersections: Get raw intersection points
Sourcepub fn compute_convex_hulls(
&self,
downsampling: u32,
) -> Vec<(Vec<Point<f32>>, Vec<[u32; 3]>)>
pub fn compute_convex_hulls( &self, downsampling: u32, ) -> Vec<(Vec<Point<f32>>, Vec<[u32; 3]>)>
Compute convex hulls from the voxelized parts (3D version).
This method generates convex meshes for each decomposed part by computing the convex
hull of the voxel vertices. This is faster than compute_exact_convex_hulls
but the hulls are based on the voxelized representation rather than the original geometry.
§Parameters
-
downsampling- Controls how many voxels to skip when generating the hull. Higher values = fewer points = simpler hulls = faster computation.1: Use all voxel vertices (highest quality, slowest)4: Use every 4th voxel (good balance, recommended)8+: Use fewer voxels (fastest, simpler hulls)
Values less than 1 are clamped to 1.
§Returns
A vector of convex hulls (one per decomposed part), where each hull is represented as
a tuple (vertices, indices):
vertices:Vec<Point<Real>>- The hull verticesindices:Vec<[u32; 3]>- Triangle indices defining the hull surface
§Performance
This method is faster than compute_exact_convex_hulls
because it works directly with voxel data without needing to intersect with original
mesh primitives. The performance scales with the number of voxels and the downsampling factor.
§When to Use
Use this method when:
- You don’t need the highest accuracy
- Performance is important
- You didn’t enable
keep_voxel_to_primitives_mapduring decomposition - The voxel resolution is high enough for your needs
- You’re using this for real-time collision detection
Use compute_exact_convex_hulls when:
- You need the most accurate representation of the original geometry
- You have enabled
keep_voxel_to_primitives_map - Quality is more important than speed
§Examples
use parry3d::math::Point;
use parry3d::transformation::vhacd::{VHACD, VHACDParameters};
let decomposition = VHACD::decompose(
&VHACDParameters::default(),
&vertices,
&indices,
false, // voxel-to-primitive mapping not needed
);
// Compute voxel-based convex hulls with moderate downsampling
let hulls = decomposition.compute_convex_hulls(4);
for (i, (verts, tris)) in hulls.iter().enumerate() {
println!("Hull {}: {} vertices, {} triangles", i, verts.len(), tris.len());
}§Creating a Compound Shape for Collision Detection
use parry3d::math::Point;
use parry3d::shape::{SharedShape, Compound};
use parry3d::transformation::vhacd::{VHACD, VHACDParameters};
use parry3d::na::Isometry3;
let decomposition = VHACD::decompose(
&VHACDParameters::default(),
&vertices,
&indices,
false,
);
let hulls = decomposition.compute_convex_hulls(4);§See Also
compute_exact_convex_hulls: More accurate mesh-based hullsvoxel_parts: Access the raw voxel dataSharedShape::convex_decomposition: High-level API
Auto Trait Implementations§
impl Freeze for VHACD
impl RefUnwindSafe for VHACD
impl Send for VHACD
impl Sync for VHACD
impl Unpin for VHACD
impl UnwindSafe for VHACD
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.