Starting to work on frustums
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
//! 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
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
pub mod vector;
|
||||
pub mod bounding_box;
|
||||
pub mod plane;
|
||||
pub mod frustum;
|
||||
|
||||
use std::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign, Div, DivAssign};
|
||||
use num::{Zero, One};
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
//! Module containing the plane struct.
|
||||
|
||||
use math::vector::Vector3;
|
||||
|
||||
/// A 3D plane.
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Plane {
|
||||
/// The normal of the plane.
|
||||
normal: Vector3<f32>,
|
||||
|
||||
/// The constant, offset of the plane from the origin.
|
||||
constant: f32,
|
||||
}
|
||||
|
||||
impl Plane {
|
||||
/// Creates a new plane from its normal and its constant.
|
||||
pub fn from_coordinates(a: f32, b: f32, c: f32, w: f32) -> Plane {
|
||||
let mut p = Plane {
|
||||
normal: Vector3::new(a, b, c),
|
||||
constant: w,
|
||||
};
|
||||
p.normalize();
|
||||
p
|
||||
}
|
||||
|
||||
/// Creates a new plane from its normal and its constant.
|
||||
pub fn from_normal_and_constant(normal: Vector3<f32>, constant: f32) -> Plane {
|
||||
Plane::from_coordinates(normal.x(), normal.y(), normal.z(), constant)
|
||||
}
|
||||
|
||||
/// Creates a new plane from its normal and a point of the plane.
|
||||
pub fn from_normal_and_point(normal: Vector3<f32>, point: Vector3<f32>) -> Plane {
|
||||
Plane::from_normal_and_constant(normal, - point.dot(normal))
|
||||
}
|
||||
|
||||
|
||||
/// Creates a new plane from three points.
|
||||
pub fn from_points(p1: Vector3<f32>, p2: Vector3<f32>, p3: Vector3<f32>) -> Plane {
|
||||
let p1p2 = p2 - p1;
|
||||
let p1p3 = p3 - p1;
|
||||
Plane::from_normal_and_point(p1p2.cross_product(p1p3), p1)
|
||||
}
|
||||
|
||||
/// Normalizes the plane.
|
||||
pub fn normalize(&mut self) {
|
||||
let normal_inverse = 1.0 / self.normal.norm();
|
||||
self.normal *= normal_inverse;
|
||||
self.constant *= normal_inverse;
|
||||
}
|
||||
|
||||
/// Returns the normal of the plane.
|
||||
pub fn normal(&self) -> Vector3<f32> {
|
||||
self.normal
|
||||
}
|
||||
|
||||
/// Returns the constant of the plane.
|
||||
pub fn constant(&self) -> f32 {
|
||||
self.constant
|
||||
}
|
||||
|
||||
/// Returns the distance between the plane and the point.
|
||||
pub fn distance_to_point(&self, point: Vector3<f32>) -> f32 {
|
||||
self.normal.dot(point) + self.constant
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user