//! 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 nalgebra::Matrix4; 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 its four planes. pub fn new(planes: [Plane; 6]) -> Frustum { Frustum { planes: planes, } } /// Creates a frustum for a camera matrix. pub fn from_matrix(m: &Matrix4) -> 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)]; // Swapped version... let m0 = m[(0, 0)]; let m1 = m[(1, 0)]; let m2 = m[(2, 0)]; let m3 = m[(3, 0)]; let m4 = m[(0, 1)]; let m5 = m[(1, 1)]; let m6 = m[(2, 1)]; let m7 = m[(3, 1)]; let m8 = m[(0, 2)]; let m9 = m[(1, 2)]; let m10 = m[(2, 2)]; let m11 = m[(3, 2)]; let m12 = m[(0, 3)]; let m13 = m[(1, 3)]; let m14 = m[(2, 3)]; 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) -> bool { use num::Zero; let mut p = Vector3::::zero(); for plane in &self.planes { p[0] = if plane.normal().x() > 0.0 { bbox.max().x() } else { bbox.min().x() }; p[1] = if plane.normal().y() > 0.0 { bbox.max().y() } else { bbox.min().y() }; p[2] = if plane.normal().z() > 0.0 { bbox.max().z() } else { bbox.min().z() }; if plane.distance_to_point(p) < 0.0 { return false; } } true } }