Planes and Culling Frustums
- Dominant language
- Rust
- Stars
- 4.8k
- Forks
- 565
- PR merge metrics
- No merged PRs in 30d
Description
Any thoughts about adding in planes and culling frustums (or just frustums with the right functions.) I'm using nalgebra for a game I'm working on and planes + frustums are nice for optimizations, so others might desire them.
I basically made my own and if you think this is something useful, feel free to use my code if it's up to your standards, at least as a start. Otherwise, it's not hard to create, just something that could get wrapped into your lib and be one less piece of code I'm maintaining.
If you already have this and I somehow missed it, I apologize for the issue!
Plane:
`
use num_traits::real::Real;
use nalgebra::*;
pub struct Plane {
pub a: T,
pub b: T,
pub c: T,
pub d: T
}
impl Plane {
pub fn new(
a: T,
b: T,
c: T,
d: T
) -> Self {
Self {
a,
b,
c,
d
}
}
pub fn normalize(
&mut self
) {
let f = ((self.a * self.a) + (self.b * self.b) + (self.c * self.c)).sqrt();
if f != num_traits::zero() {
self.a = self.a / f;
self.b = self.b / f;
self.c = self.c / f;
self.d = self.d / f;
}
}
pub fn bound_box_outside_plane(
&mut self,
min: &Point3,
max: &Point3
) -> bool {
if (self.a * min.x) + (self.b * min.y) + (self.c * min.z) + self.d > num_traits::zero() {
return true;
}
if (self.a * max.x) + (self.b * min.y) + (self.c * min.z) + self.d > num_traits::zero() {
return true;
}
if (self.a * min.x) + (self.b * max.y) + (self.c * min.z) + self.d > num_traits::zero() {
return true;
}
if (self.a * max.x) + (self.b * max.y) + (self.c * min.z) + self.d > num_traits::zero() {
return true;
}
if (self.a * min.x) + (self.b * min.y) + (self.c * max.z) + self.d > num_traits::zero() {
return true;
}
if (self.a * max.x) + (self.b * min.y) + (self.c * max.z) + self.d > num_traits::zero() {
return true;
}
if (self.a * min.x) + (self.b * max.y) + (self.c * max.z) + self.d > num_traits::zero() {
return true;
}
(self.a * max.x) + (self.b * max.y) + (self.c * max.z) + self.d > num_traits::zero()
}
}
impl Default for Plane {
fn default() -> Self {
Self {
a: num_traits::zero(),
b: num_traits::zero(),
c: num_traits::zero(),
d: num_traits::zero()
}
}
}
`
Culling Frustum:
`
use num_traits::real::Real;
use nalgebra::*;
use crate::game::view_plane::Plane;
pub struct CullingFrustum {
pub left: Plane,
pub right: Plane,
pub top: Plane,
pub bottom: Plane,
pub near: Plane,
pub far: Plane,
}
impl CullingFrustum {
pub fn new(
perspective_matrix: &Matrix4,
view_matrix: &Matrix4
) -> Self {
let mut clip_plane: [T; 16] = [num_traits::zero(); 16];
clip_plane[0]=(view_matrix[(0,0)]*perspective_matrix[(0,0)])+(view_matrix[(1,0)]*perspective_matrix[(0,1)])+(view_matrix[(2,0)]*perspective_matrix[(0,2)])+(view_matrix[(3,0)]*perspective_matrix[(0,3)]);
clip_plane[1]=(view_matrix[(0,0)]*perspective_matrix[(1,0)])+(view_matrix[(1,0)]*perspective_matrix[(1,1)])+(view_matrix[(2,0)]*perspective_matrix[(1,2)])+(view_matrix[(3,0)]*perspective_matrix[(1,3)]);
clip_plane[2]=(view_matrix[(0,0)]*perspective_matrix[(2,0)])+(view_matrix[(1,0)]*perspective_matrix[(2,1)])+(view_matrix[(2,0)]*perspective_matrix[(2,2)])+(view_matrix[(3,0)]*perspective_matrix[(2,3)]);
clip_plane[3]=(view_matrix[(0,0)]*perspective_matrix[(3,0)])+(view_matrix[(1,0)]*perspective_matrix[(3,1)])+(view_matrix[(2,0)]*perspective_matrix[(3,2)])+(view_matrix[(3,0)]*perspective_matrix[(3,3)]);
clip_plane[4]=(view_matrix[(0,1)]*perspective_matrix[(0,0)])+(view_matrix[(1,1)]*perspective_matrix[(0,1)])+(view_matrix[(2,1)]*perspective_matrix[(0,2)])+(view_matrix[(3,1)]*perspective_matrix[(0,3)]);
clip_plane[5]=(view_matrix[(0,1)]*perspective_matrix[(1,0)])+(view_matrix[(1,1)]*perspective_matrix[(1,1)])+(view_matrix[(2,1)]*perspective_matrix[(1,2)])+(view_matrix[(3,1)]*perspective_matrix[(1,3)]);
clip_plane[6]=(view_matrix[(0,1)]*perspective_matrix[(2,0)])+(view_matrix[(1,1)]*perspective_matrix[(2,1)])+(view_matrix[(2,1)]*perspective_matrix[(2,2)])+(view_matrix[(3,1)]*perspective_matrix[(2,3)]);
clip_plane[7]=(view_matrix[(0,1)]*perspective_matrix[(3,0)])+(view_matrix[(1,1)]*perspective_matrix[(3,1)])+(view_matrix[(2,1)]*perspective_matrix[(3,2)])+(view_matrix[(3,1)]*perspective_matrix[(3,3)]);
clip_plane[8]=(view_matrix[(0,2)]*perspective_matrix[(0,0)])+(view_matrix[(1,2)]*perspective_matrix[(0,1)])+(view_matrix[(2,2)]*perspective_matrix[(0,2)])+(view_matrix[(3,2)]*perspective_matrix[(0,3)]);
clip_plane[9]=(view_matrix[(0,2)]*perspective_matrix[(1,0)])+(view_matrix[(1,2)]*perspective_matrix[(1,1)])+(view_matrix[(2,2)]*perspective_matrix[(1,2)])+(view_matrix[(3,2)]*perspective_matrix[(1,3)]);
clip_plane[10]=(view_matrix[(0,2)]*perspective_matrix[(2,0)])+(view_matrix[(1,2)]*perspective_matrix[(2,1)])+(view_matrix[(2,2)]*perspective_matrix[(2,2)])+(view_matrix[(3,2)]*perspective_matrix[(2,3)]);
clip_plane[11]=(view_matrix[(0,2)]*perspective_matrix[(3,0)])+(view_matrix[(1,2)]*perspective_matrix[(3,1)])+(view_matrix[(2,2)]*perspective_matrix[(3,2)])+(view_matrix[(3,2)]*perspective_matrix[(3,3)]);
clip_plane[12]=(view_matrix[(0,3)]*perspective_matrix[(0,0)])+(view_matrix[(1,3)]*perspective_matrix[(0,1)])+(view_matrix[(2,3)]*perspective_matrix[(0,2)])+(view_matrix[(3,3)]*perspective_matrix[(0,3)]);
clip_plane[13]=(view_matrix[(0,3)]*perspective_matrix[(1,0)])+(view_matrix[(1,3)]*perspective_matrix[(1,1)])+(view_matrix[(2,3)]*perspective_matrix[(1,2)])+(view_matrix[(3,3)]*perspective_matrix[(1,3)]);
clip_plane[14]=(view_matrix[(0,3)]*perspective_matrix[(2,0)])+(view_matrix[(1,3)]*perspective_matrix[(2,1)])+(view_matrix[(2,3)]*perspective_matrix[(2,2)])+(view_matrix[(3,3)]*perspective_matrix[(2,3)]);
clip_plane[15]=(view_matrix[(0,3)]*perspective_matrix[(3,0)])+(view_matrix[(1,3)]*perspective_matrix[(3,1)])+(view_matrix[(2,3)]*perspective_matrix[(3,2)])+(view_matrix[(3,3)]*perspective_matrix[(3,3)]);
// left plane
let mut left: Plane = Plane::new(
clip_plane[3]+clip_plane[0],
clip_plane[7]+clip_plane[4],
clip_plane[11]+clip_plane[8],
clip_plane[15]+clip_plane[12]
);
left.normalize();
// right plane
let mut right: Plane = Plane::new(
clip_plane[3]-clip_plane[0],
clip_plane[7]-clip_plane[4],
clip_plane[11]-clip_plane[8],
clip_plane[15]-clip_plane[12]
);
right.normalize();
// top plane
let mut top: Plane = Plane::new(
clip_plane[3]-clip_plane[1],
clip_plane[7]-clip_plane[5],
clip_plane[11]-clip_plane[9],
clip_plane[15]-clip_plane[13]
);
top.normalize();
// bottom plane
let mut bottom: Plane = Plane::new(
clip_plane[3]+clip_plane[1],
clip_plane[7]+clip_plane[5],
clip_plane[11]+clip_plane[9],
clip_plane[15]+clip_plane[13]
);
bottom.normalize();
// near plane
let mut near: Plane = Plane::new(
clip_plane[3]+clip_plane[2],
clip_plane[7]+clip_plane[6],
clip_plane[11]+clip_plane[10],
clip_plane[15]+clip_plane[14]
);
near.normalize();
// far plane
let mut far: Plane = Plane::new(
clip_plane[3]-clip_plane[2],
clip_plane[7]-clip_plane[6],
clip_plane[11]-clip_plane[10],
clip_plane[15]-clip_plane[14]
);
far.normalize();
Self {
left,
right,
top,
bottom,
near,
far
}
}
pub fn bound_box_in_frustum(
&mut self,
min: &Point3,
max: &Point3
) -> bool {
// check if outside the plane, if it is,
// then it's considered outside the bounds
if !self.left.bound_box_outside_plane(min, max) {
return false;
}
if !self.right.bound_box_outside_plane(min, max) {
return false;
}
if !self.top.bound_box_outside_plane(min, max) {
return false;
}
if !self.bottom.bound_box_outside_plane(min, max) {
return false;
}
if !self.near.bound_box_outside_plane(min, max) {
return false;
}
self.far.bound_box_outside_plane(min, max)
}
}
impl Default for CullingFrustum {
fn default() -> Self {
Self {
left: Plane::default(),
right: Plane::default(),
top: Plane::default(),
bottom: Plane::default(),
near: Plane::default(),
far: Plane::default(),
}
}
}
`
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.