68 lines
2.6 KiB
Rust
68 lines
2.6 KiB
Rust
//! Module containing the frustum struct.
|
|
//!
|
|
//! The frustum is the field of view of a camera. It allows you to make computation to know what is
|
|
//! visible or not in an efficient manner, though it doesn't take occlusions into account.
|
|
|
|
use math::vector::Vector3;
|
|
use math::plane::Plane;
|
|
use math::bounding_box::BoundingBox3;
|
|
|
|
/// Struct containing the 6 planes of a 3D camera.
|
|
#[derive(Copy, Clone)]
|
|
pub struct Frustum {
|
|
/// The planes of the frustum.
|
|
planes: [Plane; 6],
|
|
}
|
|
|
|
impl Frustum {
|
|
/// Creates a frustum from the matrix of a camera.
|
|
///
|
|
/// This is *ahem...* slightly inspired from THREE.js Frustum
|
|
pub fn from_matrix(m: &[[f32; 4]; 4]) -> Frustum {
|
|
|
|
let m0 = m[0][0]; let m1 = m[0][1]; let m2 = m[0][2]; let m3 = m[0][3];
|
|
let m4 = m[1][0]; let m5 = m[1][1]; let m6 = m[1][2]; let m7 = m[1][3];
|
|
let m8 = m[2][0]; let m9 = m[2][1]; let m10 = m[2][2]; let m11 = m[2][3];
|
|
let m12 = m[3][0]; let m13 = m[3][1]; let m14 = m[3][2]; let m15 = m[3][3];
|
|
|
|
Frustum {
|
|
planes: [
|
|
Plane::from_coordinates(m3 - m0, m7 - m4, m11 - m8, m15 - m12),
|
|
Plane::from_coordinates(m3 + m0, m7 + m4, m11 + m8, m15 + m12),
|
|
Plane::from_coordinates(m3 + m1, m7 + m5, m11 + m9, m15 + m13),
|
|
Plane::from_coordinates(m3 - m1, m7 - m5, m11 - m9, m15 - m13),
|
|
Plane::from_coordinates(m3 - m2, m7 - m6, m11 - m10, m15 - m14),
|
|
Plane::from_coordinates(m3 + m2, m7 + m6, m11 + m10, m15 + m14),
|
|
],
|
|
}
|
|
}
|
|
|
|
/// Returns true if the intersection of the frustum and the bounding box is not empty.
|
|
pub fn intersects_box(&self, bbox: BoundingBox3<f32>) -> bool {
|
|
|
|
use num::Zero;
|
|
|
|
let mut p1 = Vector3::<f32>::zero();
|
|
let mut p2 = Vector3::<f32>::zero();
|
|
|
|
for plane in &self.planes {
|
|
|
|
p1[0] = if plane.normal().x() > 0.0 { bbox.min().x() } else { bbox.max().x() };
|
|
p2[0] = if plane.normal().x() > 0.0 { bbox.max().x() } else { bbox.min().x() };
|
|
p1[1] = if plane.normal().y() > 0.0 { bbox.min().y() } else { bbox.max().y() };
|
|
p2[1] = if plane.normal().y() > 0.0 { bbox.max().y() } else { bbox.min().y() };
|
|
p1[2] = if plane.normal().z() > 0.0 { bbox.min().z() } else { bbox.max().z() };
|
|
p2[2] = if plane.normal().z() > 0.0 { bbox.max().z() } else { bbox.min().z() };
|
|
|
|
let d1 = plane.distance_to_point(p1);
|
|
let d2 = plane.distance_to_point(p2);
|
|
|
|
if d1 < 0.0 && d2 < 2.0 {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
true
|
|
}
|
|
}
|