From 1f1b3379880a4cb3000eb6906cd69818907f2c0b Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Fri, 27 Jan 2023 21:50:33 +0100 Subject: [PATCH] frustum culling impl --- src/camera.rs | 5 ++++ src/camera/frustum.rs | 69 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 69 insertions(+), 5 deletions(-) diff --git a/src/camera.rs b/src/camera.rs index 7f6c83b..3da67c3 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -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() } diff --git a/src/camera/frustum.rs b/src/camera/frustum.rs index 22708fa..259b211 100644 --- a/src/camera/frustum.rs +++ b/src/camera/frustum.rs @@ -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() -> usize { I * (9 - I) / 2 + J - 1 @@ -92,3 +143,11 @@ fn intersection(planes: &[Vec4; ) * vec3a(planes[A].w, planes[B].w, planes[C].w); res * (-1. / d) } + +pub fn update_frustum( + mut cameras: ViewMut, +) { + for camera in (&mut cameras).iter() { + camera.frustum = Frustum::compute(camera); + } +}