Skip to content

Commit 382fd10

Browse files
authored
Merge branch 'main' into render-target-component
2 parents 9af8f19 + 80e17cc commit 382fd10

File tree

1 file changed

+96
-1
lines changed

1 file changed

+96
-1
lines changed

crates/bevy_camera/src/primitives.rs

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,16 @@ impl Aabb {
133133
let signed_distance = p_normal.dot(aabb_center_world) + half_space.d();
134134
signed_distance > r
135135
}
136+
137+
/// Optimized version of [`Self::is_in_half_space`] when the AABB is already in world space.
138+
/// Use this when `world_from_local` would be the identity transform.
139+
#[inline]
140+
pub fn is_in_half_space_identity(&self, half_space: &HalfSpace) -> bool {
141+
let p_normal = half_space.normal();
142+
let r = self.half_extents.abs().dot(p_normal.abs());
143+
let signed_distance = p_normal.dot(self.center) + half_space.d();
144+
signed_distance > r
145+
}
136146
}
137147

138148
impl From<Aabb3d> for Aabb {
@@ -369,7 +379,22 @@ impl Frustum {
369379
true
370380
}
371381

372-
/// Check if the frustum contains the Axis-Aligned Bounding Box (AABB).
382+
/// Optimized version of [`Frustum::intersects_obb`]
383+
/// where the transform is [`Affine3A::IDENTITY`] and both `intersect_near` and `intersect_far` are `true`.
384+
#[inline]
385+
pub fn intersects_obb_identity(&self, aabb: &Aabb) -> bool {
386+
let aabb_center_world = aabb.center.extend(1.0);
387+
for half_space in self.half_spaces.iter() {
388+
let p_normal = half_space.normal();
389+
let relative_radius = aabb.half_extents.abs().dot(p_normal.abs());
390+
if half_space.normal_d().dot(aabb_center_world) + relative_radius <= 0.0 {
391+
return false;
392+
}
393+
}
394+
true
395+
}
396+
397+
/// Check if the frustum contains the entire Axis-Aligned Bounding Box (AABB).
373398
/// Referenced from: [Frustum Culling](https://learnopengl.com/Guest-Articles/2021/Scene/Frustum-Culling)
374399
#[inline]
375400
pub fn contains_aabb(&self, aabb: &Aabb, world_from_local: &Affine3A) -> bool {
@@ -380,6 +405,18 @@ impl Frustum {
380405
}
381406
true
382407
}
408+
409+
/// Optimized version of [`Self::contains_aabb`] when the AABB is already in world space.
410+
/// Use this when `world_from_local` would be [`Affine3A::IDENTITY`].
411+
#[inline]
412+
pub fn contains_aabb_identity(&self, aabb: &Aabb) -> bool {
413+
for half_space in &self.half_spaces {
414+
if !aabb.is_in_half_space_identity(half_space) {
415+
return false;
416+
}
417+
}
418+
true
419+
}
383420
}
384421

385422
pub struct CubeMapFace {
@@ -772,4 +809,62 @@ mod tests {
772809
);
773810
assert!(!frustum.contains_aabb(&aabb, &model));
774811
}
812+
813+
#[test]
814+
fn test_identity_optimized_equivalence() {
815+
let cases = vec![
816+
(
817+
Aabb {
818+
center: Vec3A::ZERO,
819+
half_extents: Vec3A::splat(1.0),
820+
},
821+
HalfSpace::new(Vec4::new(1.0, 0.0, 0.0, -0.5)),
822+
),
823+
(
824+
Aabb {
825+
center: Vec3A::new(2.0, -1.0, 0.5),
826+
half_extents: Vec3A::new(1.0, 2.0, 0.5),
827+
},
828+
HalfSpace::new(Vec4::new(1.0, 1.0, 1.0, -1.0).normalize()),
829+
),
830+
(
831+
Aabb {
832+
center: Vec3A::new(1.0, 1.0, 1.0),
833+
half_extents: Vec3A::ZERO,
834+
},
835+
HalfSpace::new(Vec4::new(0.0, 0.0, 1.0, -2.0)),
836+
),
837+
];
838+
for (aabb, half_space) in cases {
839+
let general = aabb.is_in_half_space(&half_space, &Affine3A::IDENTITY);
840+
let identity = aabb.is_in_half_space_identity(&half_space);
841+
assert_eq!(general, identity,);
842+
}
843+
}
844+
845+
#[test]
846+
fn intersects_obb_identity_matches_standard_true_true() {
847+
let frusta = [frustum(), long_frustum(), big_frustum()];
848+
let aabbs = [
849+
Aabb {
850+
center: Vec3A::ZERO,
851+
half_extents: Vec3A::new(0.5, 0.5, 0.5),
852+
},
853+
Aabb {
854+
center: Vec3A::new(1.0, 0.0, 0.5),
855+
half_extents: Vec3A::new(0.9, 0.9, 0.9),
856+
},
857+
Aabb {
858+
center: Vec3A::new(100.0, 100.0, 100.0),
859+
half_extents: Vec3A::new(1.0, 1.0, 1.0),
860+
},
861+
];
862+
for fr in &frusta {
863+
for aabb in &aabbs {
864+
let standard = fr.intersects_obb(aabb, &Affine3A::IDENTITY, true, true);
865+
let optimized = fr.intersects_obb_identity(aabb);
866+
assert_eq!(standard, optimized);
867+
}
868+
}
869+
}
775870
}

0 commit comments

Comments
 (0)