Skip to content

Commit 5a6c912

Browse files
authored
feat: replace the QBVH by a new BVH implementation (#361)
* feat: add AABB calculation from points iterator yielding values instead of refs * fix: add missing exports * feat: add implementation of a new BVH data-structure * chore: remove the QBVH * feat: integrate the new BVH into all composite shapes and geometric queries * chore: cargo fmt * feat: add nonparallel PLOC bvh builder * chore: remove the incremental binned build optimization strategy * feat: add more comments * chore: add missing deps * chore: rename SimdCompositeShape to CompositeShape * chore: rename remaining occurrences of `qbvh` to `bvh`. * chore: have TypedCompositeShape derive from CompositeShape * chore: cargo fmt * chore: fix cargo doc * chore: fix no-std build * fix: remove rkyv support for TriMesh and Polyline because VecMap doesn’t support it * chore: vendor vec_map for rkyv and no-std support * feat: re-enable rkyv support for polyline and trimesh by vendoring vec_map * chore: misc CI fixes * chore: more CI fixes * fix enhanced-determinism build * fix tests * fix cargo doc * fix broken simd bvh raycast perfs on x86 * feat: switch to static assertions for bvh node simd size/alignment. * chore: update CHANGELOG
1 parent 9e268f8 commit 5a6c912

File tree

81 files changed

+5931
-4869
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+5931
-4869
lines changed

CHANGELOG.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,33 @@
11
# Change Log
22

3+
### Added
4+
5+
- Add a new `Bvh` acceleration data-structure. It replaces `Qbvh` entirely. It supports:
6+
- Traversals (best-first, depth-first, BVTT, leaf iterators, and leaf pairs iterator).
7+
- It can be constructed either incrementally by inserting nodes, or from a set of leaves using either the
8+
binned building strategy or the PLOC (without parallelism) strategy.
9+
- Dynamic leaf insertion, update, removal.
10+
- Incremental tree rebalancing.
11+
312
### Fixed
413

514
- Fix `clip_aabb_line` crashing when given incorrect inputs (zero length direction or NAN).
615
- Fix `Segment::intersects_ray` returning false-positive when the segment is zero-length. ([#31](https://github.com/dimforge/parry/issues/31)).
716
- Expose `utils::sort3` and `utils::sort2`.
817

18+
### Modified
19+
20+
- The `local_point_cloud_aabb`, `point_cloud_aabb`, and `Aabb::from_points` now takes an iterator over point values instead
21+
of an iterator to point references. Variants taking point references still exist and are named `local_point_cloud_aabb_ref`,
22+
`point_cloud_aabb_ref` and `Aabb::from_points_ref`.
23+
- Renamed `SimdCompositeShape` and `TypedSimdCompositeShape` to `CompositeShape` and TypedCompositeShape`.
24+
- The `TypedCompositeShape` trait now derives from `CompositeShape`.
25+
- Removed every `*Visitor` structures. Instead, either call `Bvh::traverse` (or `Bvh::search_best`, or `Bvh::leaves`, or
26+
`bvh::leaf_pairs`), or wrap your composite shape into `CompositeShapeRef` to access some generic implementation of
27+
various geometric queries for any composite shape.
28+
- All composite shapes now rely on the new `Bvh` acceleration structure instead of `Qbvh`.
29+
- The `Qbvh` has been removed. Use `Bvh` instead.
30+
931
## 0.21.1
1032

1133
### Added

crates/parry2d-f64/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ log = "0.4"
8989
ordered-float = { version = "5", default-features = false }
9090
thiserror = { version = "2", default-features = false }
9191
ena = { version = "0.14.3", optional = true, default-features = false }
92+
smallvec = "1"
9293

9394
[dev-dependencies]
9495
simba = { version = "0.9", default-features = false }

crates/parry2d/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ ordered-float = { version = "5", default-features = false }
8989
log = "0.4"
9090
thiserror = { version = "2", default-features = false }
9191
ena = { version = "0.14.3", optional = true, default-features = false }
92+
smallvec = "1"
9293

9394
[dev-dependencies]
9495
simba = { version = "0.9", default-features = false }

crates/parry3d-f64/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ bytemuck = { version = "1", features = ["derive"], optional = true }
8989
rstar = "0.12.0"
9090
obj = { version = "0.10.2", optional = true }
9191
ena = { version = "0.14.3", optional = true, default-features = false }
92+
smallvec = "1"
9293

9394
log = "0.4"
9495
ordered-float = { version = "5", default-features = false }

crates/parry3d/Cargo.toml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ improved_fixed_point_support = []
5959

6060
# Do not enable this feature directly. It is automatically
6161
# enabled with the "simd-stable" or "simd-nightly" feature.
62-
simd-is-enabled = []
62+
simd-is-enabled = [ "glam" ]
6363

6464
[lib]
6565
name = "parry3d"
@@ -92,6 +92,13 @@ thiserror = { version = "2", default-features = false }
9292
rstar = "0.12.0"
9393
obj = { version = "0.10.2", optional = true }
9494
ena = { version = "0.14.3", optional = true, default-features = false }
95+
smallvec = "1"
96+
static_assertions = "1"
97+
98+
# NOTE: needed only for element_min for SIMD BVH ray-casting.
99+
# can be removed once `wide` supports it (and allows filtering-out the
100+
# fourth element).
101+
glam = { version = "0.30.4", optional = true }
95102

96103
[dev-dependencies]
97104
oorandom = "11"

src/bounding_volume/aabb.rs

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ use na;
99
use num::Bounded;
1010

1111
#[cfg(all(feature = "dim3", not(feature = "std")))]
12-
use na::ComplexField; // for .sin_cos()
12+
use na::ComplexField;
13+
// for .sin_cos()
1314

1415
use crate::query::{Ray, RayCast};
1516
#[cfg(feature = "rkyv")]
@@ -143,10 +144,18 @@ impl Aabb {
143144
Self::new(center - half_extents, center + half_extents)
144145
}
145146

146-
/// Creates a new `Aabb` from a set of points.
147-
pub fn from_points<'a, I>(pts: I) -> Self
147+
/// Creates a new `Aabb` from a set of point references.
148+
pub fn from_points_ref<'a, I>(pts: I) -> Self
148149
where
149150
I: IntoIterator<Item = &'a Point<Real>>,
151+
{
152+
super::aabb_utils::local_point_cloud_aabb(pts.into_iter().copied())
153+
}
154+
155+
/// Creates a new `Aabb` from a set of points.
156+
pub fn from_points<I>(pts: I) -> Self
157+
where
158+
I: IntoIterator<Item = Point<Real>>,
150159
{
151160
super::aabb_utils::local_point_cloud_aabb(pts)
152161
}
@@ -174,6 +183,28 @@ impl Aabb {
174183
return extents.x * extents.y * extents.z;
175184
}
176185

186+
/// In 3D, returns the half-area. In 2D returns the half-perimeter of the AABB.
187+
pub fn half_area_or_perimeter(&self) -> Real {
188+
#[cfg(feature = "dim2")]
189+
return self.half_perimeter();
190+
#[cfg(feature = "dim3")]
191+
return self.half_area();
192+
}
193+
194+
/// The half perimeter of this `Aabb`.
195+
#[cfg(feature = "dim2")]
196+
pub fn half_perimeter(&self) -> Real {
197+
let extents = self.extents();
198+
extents.x + extents.y
199+
}
200+
201+
/// The half area of this `Aabb`.
202+
#[cfg(feature = "dim3")]
203+
pub fn half_area(&self) -> Real {
204+
let extents = self.extents();
205+
extents.x * (extents.y + extents.z) + extents.y * extents.z
206+
}
207+
177208
/// The extents of this `Aabb`.
178209
#[inline]
179210
pub fn extents(&self) -> Vector<Real> {
@@ -251,6 +282,15 @@ impl Aabb {
251282
true
252283
}
253284

285+
/// Computes the distance between the origin and this AABB.
286+
pub fn distance_to_origin(&self) -> Real {
287+
self.mins
288+
.coords
289+
.sup(&-self.maxs.coords)
290+
.sup(&Vector::zeros())
291+
.norm()
292+
}
293+
254294
/// Does this AABB intersects an AABB `aabb2` moving at velocity `vel12` relative to `self`?
255295
#[inline]
256296
pub fn intersects_moving_aabb(&self, aabb2: &Self, vel12: Vector<Real>) -> bool {

src/bounding_volume/aabb_convex_polygon.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ impl ConvexPolygon {
66
/// Computes the world-space [`Aabb`] of this convex polygon, transformed by `pos`.
77
#[inline]
88
pub fn aabb(&self, pos: &Isometry<Real>) -> Aabb {
9-
super::details::point_cloud_aabb(pos, self.points())
9+
super::details::point_cloud_aabb_ref(pos, self.points())
1010
}
1111

1212
/// Computes the local-space [`Aabb`] of this convex polygon.
1313
#[inline]
1414
pub fn local_aabb(&self) -> Aabb {
15-
super::details::local_point_cloud_aabb(self.points())
15+
super::details::local_point_cloud_aabb_ref(self.points())
1616
}
1717
}

src/bounding_volume/aabb_convex_polyhedron.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ impl ConvexPolyhedron {
66
/// Computes the world-space [`Aabb`] of this convex polyhedron, transformed by `pos`.
77
#[inline]
88
pub fn aabb(&self, pos: &Isometry<Real>) -> Aabb {
9-
super::details::point_cloud_aabb(pos, self.points())
9+
super::details::point_cloud_aabb_ref(pos, self.points())
1010
}
1111

1212
/// Computes the local-space [`Aabb`] of this convex polyhedron.
1313
#[inline]
1414
pub fn local_aabb(&self) -> Aabb {
15-
super::details::local_point_cloud_aabb(self.points())
15+
super::details::local_point_cloud_aabb_ref(self.points())
1616
}
1717
}

src/bounding_volume/aabb_utils.rs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,17 +54,25 @@ where
5454
Aabb::new(Point::from(min), Point::from(max))
5555
}
5656

57-
/// Computes the [`Aabb`] of a set of points transformed by `m`.
58-
pub fn point_cloud_aabb<'a, I>(m: &Isometry<Real>, pts: I) -> Aabb
57+
/// Computes the [`Aabb`] of a set of point references transformed by `m`.
58+
pub fn point_cloud_aabb_ref<'a, I>(m: &Isometry<Real>, pts: I) -> Aabb
5959
where
6060
I: IntoIterator<Item = &'a Point<Real>>,
61+
{
62+
point_cloud_aabb(m, pts.into_iter().copied())
63+
}
64+
65+
/// Computes the [`Aabb`] of a set of points transformed by `m`.
66+
pub fn point_cloud_aabb<I>(m: &Isometry<Real>, pts: I) -> Aabb
67+
where
68+
I: IntoIterator<Item = Point<Real>>,
6169
{
6270
let mut it = pts.into_iter();
6371

6472
let p0 = it.next().expect(
6573
"Point cloud Aabb construction: the input iterator should yield at least one point.",
6674
);
67-
let wp0 = m.transform_point(p0);
75+
let wp0 = m.transform_point(&p0);
6876
let mut min: Point<Real> = wp0;
6977
let mut max: Point<Real> = wp0;
7078

@@ -78,21 +86,29 @@ where
7886
}
7987

8088
/// Computes the [`Aabb`] of a set of points.
81-
pub fn local_point_cloud_aabb<'a, I>(pts: I) -> Aabb
89+
pub fn local_point_cloud_aabb_ref<'a, I>(pts: I) -> Aabb
8290
where
8391
I: IntoIterator<Item = &'a Point<Real>>,
92+
{
93+
local_point_cloud_aabb(pts.into_iter().copied())
94+
}
95+
96+
/// Computes the [`Aabb`] of a set of points.
97+
pub fn local_point_cloud_aabb<I>(pts: I) -> Aabb
98+
where
99+
I: IntoIterator<Item = Point<Real>>,
84100
{
85101
let mut it = pts.into_iter();
86102

87103
let p0 = it.next().expect(
88104
"Point cloud Aabb construction: the input iterator should yield at least one point.",
89105
);
90-
let mut min: Point<Real> = *p0;
91-
let mut max: Point<Real> = *p0;
106+
let mut min: Point<Real> = p0;
107+
let mut max: Point<Real> = p0;
92108

93109
for pt in it {
94-
min = min.inf(pt);
95-
max = max.sup(pt);
110+
min = min.inf(&pt);
111+
max = max.sup(&pt);
96112
}
97113

98114
Aabb::new(min, max)

src/bounding_volume/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ mod simd_aabb;
6565
pub mod details {
6666
#[cfg(feature = "dim3")]
6767
pub use super::aabb_utils::support_map_aabb;
68-
pub use super::aabb_utils::{local_point_cloud_aabb, local_support_map_aabb, point_cloud_aabb};
68+
pub use super::aabb_utils::{
69+
local_point_cloud_aabb, local_point_cloud_aabb_ref, local_support_map_aabb,
70+
point_cloud_aabb, point_cloud_aabb_ref,
71+
};
6972
pub use super::bounding_sphere_utils::point_cloud_bounding_sphere;
7073
}

0 commit comments

Comments
 (0)