frustum culling impl

This commit is contained in:
griffi-gh 2023-01-27 21:50:33 +01:00
parent a29f6c65fd
commit 1f1b337988
2 changed files with 69 additions and 5 deletions

View file

@ -6,11 +6,13 @@ mod matrices;
mod frustum;
use matrices::update_matrices;
use frustum::{Frustum, update_frustum};
#[derive(Component)]
pub struct Camera {
pub view_matrix: Mat4,
pub perspective_matrix: Mat4,
pub frustum: Frustum,
pub up: Vec3,
pub fov: f32,
pub z_near: f32,
@ -20,8 +22,10 @@ impl Camera {
pub fn new(fov: f32, z_near: f32, z_far: f32, up: Vec3) -> Self {
Self {
fov, z_near, z_far, up,
//TODO maybe separate this?
perspective_matrix: Mat4::default(),
view_matrix: Mat4::default(),
frustum: Frustum::default(),
}
}
}
@ -34,5 +38,6 @@ impl Default for Camera {
pub fn compute_cameras() -> Workload {
(
update_matrices,
update_frustum,
).into_workload()
}

View file

@ -7,11 +7,10 @@
// [ http://iquilezles.org/www/articles/frustumcorrect/frustumcorrect.htm ]
// three layers of stolen code, yay!
use glam::{Vec3A, Vec4, Mat3A, vec3a};
use glam::{Vec3A, Vec4, Mat3A, vec3a, Vec3, vec4};
use shipyard::{ViewMut, IntoIter};
use super::Camera;
#[repr(usize)]
enum FrustumPlane {
Left,
@ -26,7 +25,8 @@ const PLANE_COUNT: usize = 6;
const PLANE_COMBINATIONS: usize = PLANE_COUNT * (PLANE_COUNT - 1) / 2;
const POINT_COUNT: usize = 8;
struct Frustum {
#[derive(Default)]
pub struct Frustum {
planes: [Vec4; PLANE_COUNT],
points: [Vec3A; POINT_COUNT]
}
@ -77,8 +77,59 @@ impl Frustum {
Self { planes, points }
}
}
//this may be broken
pub fn intersect_box(&self, minp: Vec3, maxp: Vec3) -> bool {
// check box outside/inside of frustum
for i in 0..PLANE_COUNT {
if self.planes[i].dot(vec4(minp.x, minp.y, minp.z, 1.)) < 0. &&
self.planes[i].dot(vec4(maxp.x, minp.y, minp.z, 1.)) < 0. &&
self.planes[i].dot(vec4(minp.x, maxp.y, minp.z, 1.)) < 0. &&
self.planes[i].dot(vec4(maxp.x, maxp.y, minp.z, 1.)) < 0. &&
self.planes[i].dot(vec4(minp.x, minp.y, maxp.z, 1.)) < 0. &&
self.planes[i].dot(vec4(maxp.x, minp.y, maxp.z, 1.)) < 0. &&
self.planes[i].dot(vec4(minp.x, maxp.y, maxp.z, 1.)) < 0. &&
self.planes[i].dot(vec4(maxp.x, maxp.y, maxp.z, 1.)) < 0.
{
return false
}
}
// check frustum outside/inside box
let mut out: u8 = 0;
for i in 0..POINT_COUNT {
out += (self.points[i].x > maxp.x) as u8;
if out == 8 { return false }
}
let mut out: u8 = 0;
for i in 0..POINT_COUNT {
out += (self.points[i].x < minp.x) as u8;
if out == 8 { return false }
}
let mut out: u8 = 0;
for i in 0..POINT_COUNT {
out += (self.points[i].y > maxp.y) as u8;
if out == 8 { return false }
}
let mut out: u8 = 0;
for i in 0..POINT_COUNT {
out += (self.points[i].y < minp.y) as u8;
if out == 8 { return false }
}
let mut out: u8 = 0;
for i in 0..POINT_COUNT {
out += (self.points[i].z > maxp.z) as u8;
if out == 8 { return false }
}
let mut out: u8 = 0;
for i in 0..POINT_COUNT {
out += (self.points[i].z < minp.z) as u8;
if out == 8 { return false }
}
true
}
}
const fn ij2k<const I: usize, const J: usize>() -> usize {
I * (9 - I) / 2 + J - 1
@ -92,3 +143,11 @@ fn intersection<const A: usize, const B: usize, const C: usize>(planes: &[Vec4;
) * vec3a(planes[A].w, planes[B].w, planes[C].w);
res * (-1. / d)
}
pub fn update_frustum(
mut cameras: ViewMut<Camera>,
) {
for camera in (&mut cameras).iter() {
camera.frustum = Frustum::compute(camera);
}
}