#[repr(C, align(16))]pub struct BvhNode { /* private fields */ }Expand description
A single node (internal or leaf) of a BVH.
Each node stores an axis-aligned bounding box (AABB) that encompasses all geometry contained within its subtree. A node is either:
- Leaf: Contains a single piece of geometry (leaf_count == 1)
- Internal: Contains two child nodes (leaf_count > 1)
§Structure
- AABB: Stored as separate
minsandmaxspoints for efficiency - Children: For internal nodes, index to a
BvhNodeWidecontaining two child nodes. For leaf nodes, this is the user-provided leaf data (typically an index). - Leaf Count: Number of leaves in the subtree (1 for leaves, sum of children for internal)
§Memory Layout
The structure is carefully laid out for optimal performance:
- In 3D with f32: 32 bytes, 16-byte aligned (for SIMD operations)
- Fields ordered to enable efficient SIMD AABB tests
- The
#[repr(C)]ensures predictable layout for unsafe optimizations
§Example
use parry3d::partitioning::BvhNode;
use parry3d::bounding_volume::Aabb;
use nalgebra::Point3;
// Create a leaf node
let aabb = Aabb::new(Point3::origin(), Point3::new(1.0, 1.0, 1.0));
let leaf = BvhNode::leaf(aabb, 42);
assert!(leaf.is_leaf());
assert_eq!(leaf.leaf_data(), Some(42));
assert_eq!(leaf.aabb(), aabb);§See Also
BvhNodeWide- Pair of nodes stored togetherBvh- The main BVH structure
Implementations§
Source§impl BvhNode
impl BvhNode
Sourcepub fn leaf(aabb: Aabb, leaf_data: u32) -> BvhNode
pub fn leaf(aabb: Aabb, leaf_data: u32) -> BvhNode
Creates a new leaf node with the given AABB and user data.
Leaf nodes represent actual geometry in the scene. Each leaf stores:
- The AABB of the geometry it represents
- A user-provided
leaf_datavalue (typically an index into your geometry array)
§Arguments
aabb- The axis-aligned bounding box for this leaf’s geometryleaf_data- User data associated with this leaf (typically an index or ID)
§Returns
A new BvhNode representing a leaf with the given properties.
§Example
use parry3d::partitioning::BvhNode;
use parry3d::bounding_volume::Aabb;
use nalgebra::Point3;
// Create an AABB for a unit cube
let aabb = Aabb::new(Point3::origin(), Point3::new(1.0, 1.0, 1.0));
// Create a leaf node with index 0
let leaf = BvhNode::leaf(aabb, 0);
assert!(leaf.is_leaf());
assert_eq!(leaf.leaf_data(), Some(0));
assert_eq!(leaf.aabb(), aabb);§See Also
Sourcepub fn leaf_data(&self) -> Option<u32>
pub fn leaf_data(&self) -> Option<u32>
Returns the user data associated with this leaf node, if it is a leaf.
For leaf nodes, this returns the leaf_data value that was provided when the
leaf was created (typically an index into your geometry array). For internal
nodes, this returns None.
§Returns
Some(leaf_data)if this is a leaf nodeNoneif this is an internal node
§Example
use parry3d::partitioning::BvhNode;
use parry3d::bounding_volume::Aabb;
use nalgebra::Point3;
let aabb = Aabb::new(Point3::origin(), Point3::new(1.0, 1.0, 1.0));
let leaf = BvhNode::leaf(aabb, 42);
assert_eq!(leaf.leaf_data(), Some(42));§See Also
Sourcepub fn is_leaf(&self) -> bool
pub fn is_leaf(&self) -> bool
Returns true if this node is a leaf.
A node is a leaf if its leaf count is exactly 1, meaning it represents a single piece of geometry rather than a subtree of nodes.
§Returns
true if this is a leaf node, false if it’s an internal node.
§Example
use parry3d::partitioning::BvhNode;
use parry3d::bounding_volume::Aabb;
use nalgebra::Point3;
let aabb = Aabb::new(Point3::origin(), Point3::new(1.0, 1.0, 1.0));
let leaf = BvhNode::leaf(aabb, 0);
assert!(leaf.is_leaf());§See Also
leaf_data- Get the leaf’s user data
Sourcepub fn mins(&self) -> Point<f32>
pub fn mins(&self) -> Point<f32>
Returns the minimum corner of this node’s AABB.
The AABB (axis-aligned bounding box) is defined by two corners: the minimum corner (with the smallest coordinates on all axes) and the maximum corner.
§Returns
A point representing the minimum corner of the AABB.
§Example
use parry3d::partitioning::BvhNode;
use parry3d::bounding_volume::Aabb;
use nalgebra::Point3;
let aabb = Aabb::new(Point3::new(1.0, 2.0, 3.0), Point3::new(4.0, 5.0, 6.0));
let node = BvhNode::leaf(aabb, 0);
assert_eq!(node.mins(), Point3::new(1.0, 2.0, 3.0));§See Also
Sourcepub fn maxs(&self) -> Point<f32>
pub fn maxs(&self) -> Point<f32>
Returns the maximum corner of this node’s AABB.
The AABB (axis-aligned bounding box) is defined by two corners: the minimum corner and the maximum corner (with the largest coordinates on all axes).
§Returns
A point representing the maximum corner of the AABB.
§Example
use parry3d::partitioning::BvhNode;
use parry3d::bounding_volume::Aabb;
use nalgebra::Point3;
let aabb = Aabb::new(Point3::new(1.0, 2.0, 3.0), Point3::new(4.0, 5.0, 6.0));
let node = BvhNode::leaf(aabb, 0);
assert_eq!(node.maxs(), Point3::new(4.0, 5.0, 6.0));§See Also
Sourcepub fn aabb(&self) -> Aabb
pub fn aabb(&self) -> Aabb
Returns this node’s AABB as an Aabb struct.
Nodes store their AABBs as separate mins and maxs points for efficiency.
This method reconstructs the full Aabb structure.
§Returns
An Aabb representing this node’s bounding box.
§Example
use parry3d::partitioning::BvhNode;
use parry3d::bounding_volume::Aabb;
use nalgebra::Point3;
let original_aabb = Aabb::new(Point3::origin(), Point3::new(1.0, 1.0, 1.0));
let node = BvhNode::leaf(original_aabb, 0);
assert_eq!(node.aabb(), original_aabb);§See Also
Sourcepub fn center(&self) -> Point<f32>
pub fn center(&self) -> Point<f32>
Returns the center point of this node’s AABB.
The center is calculated as the midpoint between the minimum and maximum corners
on all axes: (mins + maxs) / 2.
§Returns
A point representing the center of the AABB.
§Example
use parry3d::partitioning::BvhNode;
use parry3d::bounding_volume::Aabb;
use nalgebra::Point3;
let aabb = Aabb::new(Point3::origin(), Point3::new(2.0, 4.0, 6.0));
let node = BvhNode::leaf(aabb, 0);
assert_eq!(node.center(), Point3::new(1.0, 2.0, 3.0));Sourcepub fn is_changed(&self) -> bool
pub fn is_changed(&self) -> bool
Returns true if this node has been marked as changed.
The BVH uses change tracking during incremental updates to identify which parts of the tree need refitting or optimization. This flag is set when a node or its descendants have been modified.
§Returns
true if the node is marked as changed, false otherwise.
§Example
use parry3d::partitioning::BvhNode;
use parry3d::bounding_volume::Aabb;
use nalgebra::Point3;
let aabb = Aabb::new(Point3::origin(), Point3::new(1.0, 1.0, 1.0));
let node = BvhNode::leaf(aabb, 0);
// New leaf nodes are marked as changed (pending change)
// This is used internally for tracking modifications§See Also
Bvh::refit- Uses change tracking to update the tree
Sourcepub fn scale(&mut self, scale: &Vector<f32>)
pub fn scale(&mut self, scale: &Vector<f32>)
Scales this node’s AABB by the given factor.
Each coordinate of both the minimum and maximum corners is multiplied by the corresponding component of the scale vector. This is useful when scaling an entire scene or object.
§Arguments
scale- The scale factor to apply (per-axis)
§Example
use parry3d::partitioning::BvhNode;
use parry3d::bounding_volume::Aabb;
use nalgebra::{Point3, Vector3};
let aabb = Aabb::new(Point3::new(1.0, 1.0, 1.0), Point3::new(2.0, 2.0, 2.0));
let mut node = BvhNode::leaf(aabb, 0);
node.scale(&Vector3::new(2.0, 2.0, 2.0));
assert_eq!(node.mins(), Point3::new(2.0, 2.0, 2.0));
assert_eq!(node.maxs(), Point3::new(4.0, 4.0, 4.0));§See Also
Bvh::scale- Scale an entire BVH tree
Sourcepub fn volume(&self) -> f32
pub fn volume(&self) -> f32
Calculates the volume of this node’s AABB.
The volume is the product of the extents on all axes:
- In 2D: width × height (returns area)
- In 3D: width × height × depth (returns volume)
§Returns
The volume (or area in 2D) of the AABB.
§Example
use parry3d::partitioning::BvhNode;
use parry3d::bounding_volume::Aabb;
use nalgebra::Point3;
// Create a 2×3×4 box
let aabb = Aabb::new(Point3::origin(), Point3::new(2.0, 3.0, 4.0));
let node = BvhNode::leaf(aabb, 0);
assert_eq!(node.volume(), 24.0); // 2 * 3 * 4 = 24§See Also
merged_volume- Volume of merged AABBs
Sourcepub fn merged_volume(&self, other: &Self) -> f32
pub fn merged_volume(&self, other: &Self) -> f32
Calculates the volume of the AABB that would result from merging this node with another.
This computes the volume of the smallest AABB that would contain both this node’s AABB and the other node’s AABB, without actually creating the merged AABB. This is useful during BVH construction for evaluating different tree configurations.
§Arguments
other- The other node to merge with
§Returns
The volume (or area in 2D) of the merged AABB.
§Performance
This is more efficient than creating the merged AABB and then computing its volume.
§Example
use parry3d::partitioning::BvhNode;
use parry3d::bounding_volume::Aabb;
use nalgebra::Point3;
let aabb1 = Aabb::new(Point3::origin(), Point3::new(1.0, 1.0, 1.0));
let aabb2 = Aabb::new(Point3::new(2.0, 0.0, 0.0), Point3::new(3.0, 1.0, 1.0));
let node1 = BvhNode::leaf(aabb1, 0);
let node2 = BvhNode::leaf(aabb2, 1);
// Merged AABB spans from (0,0,0) to (3,1,1) = 3×1×1 = 3
assert_eq!(node1.merged_volume(&node2), 3.0);§See Also
volume- Volume of a single node
Sourcepub fn intersects(&self, other: &Self) -> bool
pub fn intersects(&self, other: &Self) -> bool
Tests if this node’s AABB intersects another node’s AABB.
Two AABBs intersect if they overlap on all axes. This includes cases where they only touch at their boundaries.
§Arguments
other- The other node to test intersection with
§Returns
true if the AABBs intersect, false otherwise.
§Performance
When SIMD is enabled (3D, f32, simd-is-enabled feature), this uses vectorized comparisons for improved performance.
§Example
use parry3d::partitioning::BvhNode;
use parry3d::bounding_volume::Aabb;
use nalgebra::Point3;
let aabb1 = Aabb::new(Point3::origin(), Point3::new(2.0, 2.0, 2.0));
let aabb2 = Aabb::new(Point3::new(1.0, 1.0, 1.0), Point3::new(3.0, 3.0, 3.0));
let aabb3 = Aabb::new(Point3::new(5.0, 5.0, 5.0), Point3::new(6.0, 6.0, 6.0));
let node1 = BvhNode::leaf(aabb1, 0);
let node2 = BvhNode::leaf(aabb2, 1);
let node3 = BvhNode::leaf(aabb3, 2);
assert!(node1.intersects(&node2)); // Overlapping
assert!(!node1.intersects(&node3)); // Separated§See Also
contains- Check full containment
Sourcepub fn contains(&self, other: &Self) -> bool
pub fn contains(&self, other: &Self) -> bool
Tests if this node’s AABB fully contains another node’s AABB.
One AABB contains another if the other AABB is completely inside or on the boundary of this AABB on all axes.
§Arguments
other- The other node to test containment of
§Returns
true if this AABB fully contains the other AABB, false otherwise.
§Performance
When SIMD is enabled (3D, f32, simd-is-enabled feature), this uses vectorized comparisons for improved performance.
§Example
use parry3d::partitioning::BvhNode;
use parry3d::bounding_volume::Aabb;
use nalgebra::Point3;
let large = Aabb::new(Point3::origin(), Point3::new(10.0, 10.0, 10.0));
let small = Aabb::new(Point3::new(2.0, 2.0, 2.0), Point3::new(5.0, 5.0, 5.0));
let node_large = BvhNode::leaf(large, 0);
let node_small = BvhNode::leaf(small, 1);
assert!(node_large.contains(&node_small)); // Large contains small
assert!(!node_small.contains(&node_large)); // Small doesn't contain large§See Also
intersects- Check any overlapcontains_aabb- Contains anAabbdirectly
Sourcepub fn contains_aabb(&self, other: &Aabb) -> bool
pub fn contains_aabb(&self, other: &Aabb) -> bool
Tests if this node’s AABB fully contains the given AABB.
This is similar to contains but takes an Aabb directly
instead of another BvhNode.
§Arguments
other- The AABB to test containment of
§Returns
true if this node’s AABB fully contains the other AABB, false otherwise.
§Example
use parry3d::partitioning::BvhNode;
use parry3d::bounding_volume::Aabb;
use nalgebra::Point3;
let large = Aabb::new(Point3::origin(), Point3::new(10.0, 10.0, 10.0));
let small = Aabb::new(Point3::new(2.0, 2.0, 2.0), Point3::new(5.0, 5.0, 5.0));
let node = BvhNode::leaf(large, 0);
assert!(node.contains_aabb(&small));§See Also
contains- Contains anotherBvhNode
Sourcepub fn cast_ray(&self, ray: &Ray, max_toi: f32) -> f32
pub fn cast_ray(&self, ray: &Ray, max_toi: f32) -> f32
Casts a ray against this node’s AABB.
Computes the time of impact (parameter t) where the ray first intersects
the AABB. The actual hit point is ray.origin + ray.dir * t.
§Arguments
ray- The ray to castmax_toi- Maximum time of impact to consider (typically usef32::MAXorf64::MAX)
§Returns
- The time of impact if the ray hits the AABB within
max_toi Real::MAXif there is no hit or the hit is beyondmax_toi
§Example
use parry3d::partitioning::BvhNode;
use parry3d::bounding_volume::Aabb;
use parry3d::query::Ray;
use nalgebra::{Point3, Vector3};
let aabb = Aabb::new(Point3::new(5.0, -1.0, -1.0), Point3::new(6.0, 1.0, 1.0));
let node = BvhNode::leaf(aabb, 0);
// Ray from origin along X axis
let ray = Ray::new(Point3::origin(), Vector3::new(1.0, 0.0, 0.0));
let toi = node.cast_ray(&ray, f32::MAX);
assert_eq!(toi, 5.0); // Ray hits at x=5.0§See Also
Ray- Ray structureBvh::traverse- For traversing the full BVH with ray casts
Trait Implementations§
Auto Trait Implementations§
impl Freeze for BvhNode
impl RefUnwindSafe for BvhNode
impl Send for BvhNode
impl Sync for BvhNode
impl Unpin for BvhNode
impl UnwindSafe for BvhNode
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> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
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.