Struct BvhNode

Source
#[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 mins and maxs points for efficiency
  • Children: For internal nodes, index to a BvhNodeWide containing 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 together
  • Bvh - The main BVH structure

Implementations§

Source§

impl BvhNode

Source

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_data value (typically an index into your geometry array)
§Arguments
  • aabb - The axis-aligned bounding box for this leaf’s geometry
  • leaf_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
Source

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 node
  • None if 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
  • leaf - Create a leaf node
  • is_leaf - Check if a node is a leaf
Source

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
Source

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
  • maxs - Get the maximum corner
  • aabb - Get the full AABB
Source

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
  • mins - Get the minimum corner
  • aabb - Get the full AABB
Source

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
  • mins - Get just the minimum corner
  • maxs - Get just the maximum corner
Source

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));
Source

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
Source

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
Source

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
Source

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
Source

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
Source

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
Source

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
Source

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 cast
  • max_toi - Maximum time of impact to consider (typically use f32::MAX or f64::MAX)
§Returns
  • The time of impact if the ray hits the AABB within max_toi
  • Real::MAX if there is no hit or the hit is beyond max_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 structure
  • Bvh::traverse - For traversing the full BVH with ray casts

Trait Implementations§

Source§

impl Clone for BvhNode

Source§

fn clone(&self) -> BvhNode

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for BvhNode

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Copy for BvhNode

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Converts 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>

Converts 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)

Converts &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)

Converts &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
where T: Any + Send,

Source§

fn into_any_send(self: Box<T>) -> Box<dyn Any + Send>

Converts Box<Trait> (where Trait: DowncastSend) to Box<dyn Any + Send>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_sync(self: Box<T>) -> Box<dyn Any + Sync + Send>

Converts Box<Trait> (where Trait: DowncastSync) to Box<dyn Any + Send + Sync>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Converts Arc<Trait> (where Trait: DowncastSync) to Arc<Any>, which can then be downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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 more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<SS, SP> SupersetOf<SS> for SP
where SS: SubsetOf<SP>,

Source§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
Source§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
Source§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
Source§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.