From 19fa7e67bc7e3557899bcab47b64045ba49ca4a7 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Fri, 27 Jan 2023 04:02:27 +0100 Subject: [PATCH] Wip frustum code port --- src/camera.rs | 40 +++++-------------------- src/camera/frustum.rs | 66 ++++++++++++++++++++++++++++++++++++++++++ src/camera/matrices.rs | 42 +++++++++++++++++++++++++++ 3 files changed, 115 insertions(+), 33 deletions(-) create mode 100644 src/camera/frustum.rs create mode 100644 src/camera/matrices.rs diff --git a/src/camera.rs b/src/camera.rs index 7551dea..7f6c83b 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -1,7 +1,11 @@ use glam::{Mat4, Vec3}; -use shipyard::{Component, ViewMut, View, IntoIter, Workload, IntoWorkload}; +use shipyard::{Component, Workload, IntoWorkload}; use std::f32::consts::PI; -use crate::{transform::Transform, events::WindowResizedEvent}; + +mod matrices; +mod frustum; + +use matrices::update_matrices; #[derive(Component)] pub struct Camera { @@ -29,36 +33,6 @@ impl Default for Camera { pub fn compute_cameras() -> Workload { ( - update_perspective_matrix, - update_view_matrix, + update_matrices, ).into_workload() } - -fn update_view_matrix( - mut vm_camera: ViewMut, - v_transform: View -) { - for (camera, transform) in (&mut vm_camera, v_transform.inserted_or_modified()).iter() { - let (_, rotation, translation) = transform.0.to_scale_rotation_translation(); - let direction = rotation * Vec3::NEG_Z; - camera.view_matrix = Mat4::look_to_rh(translation, direction, camera.up); - } -} - -fn update_perspective_matrix( - mut vm_camera: ViewMut, - resize: View, -) { - //TODO update on launch - let Some(&size) = resize.iter().next() else { - return - }; - for camera in (&mut vm_camera).iter() { - camera.perspective_matrix = Mat4::perspective_rh_gl( - camera.fov, - size.0.x as f32 / size.0.y as f32, - camera.z_near, - camera.z_far, - ) - } -} diff --git a/src/camera/frustum.rs b/src/camera/frustum.rs new file mode 100644 index 0000000..fff9511 --- /dev/null +++ b/src/camera/frustum.rs @@ -0,0 +1,66 @@ +// basically ported from c++ +// - used as a reference: +// [ https://github.com/Beastwick18/gltest/blob/main/src/renderer/Frustum.cpp ] +// - original code: +// [ https://gist.github.com/podgorskiy/e698d18879588ada9014768e3e82a644 ] +// - which uses cube vs frustum intersection code from: +// [ http://iquilezles.org/www/articles/frustumcorrect/frustumcorrect.htm ] +// three layers of stolen code, yay! + +use glam::{Vec3, Vec4, Vec4Swizzles}; + +use super::Camera; + + +#[repr(usize)] +enum FrustumPlane { + Left, + Right, + Bottom, + Top, + Near, + Far, +} +const PLANE_COUNT: usize = 6; +const PLANE_COMBINATIONS: usize = PLANE_COUNT * (PLANE_COUNT - 1) / 2; + +struct Frustum { + planes: [Vec4; PLANE_COUNT], + crosses: [Vec3; PLANE_COMBINATIONS], +} +impl Frustum { + pub fn compute(camera: &Camera) -> Self { + //compute transposed view-projection matrix + let mat = (camera.perspective_matrix * camera.view_matrix).transpose(); + + // compute planes + let mut planes = [Vec4::default(); PLANE_COUNT]; + planes[FrustumPlane::Left as usize] = mat.w_axis + mat.x_axis; + planes[FrustumPlane::Right as usize] = mat.w_axis - mat.x_axis; + planes[FrustumPlane::Bottom as usize] = mat.w_axis + mat.y_axis; + planes[FrustumPlane::Top as usize] = mat.w_axis - mat.y_axis; + planes[FrustumPlane::Near as usize] = mat.w_axis + mat.z_axis; + planes[FrustumPlane::Far as usize] = mat.w_axis - mat.z_axis; + + //compute crosses + let crosses = [ + planes[FrustumPlane::Left as usize].xyz().cross(planes[FrustumPlane::Right as usize].xyz()), + planes[FrustumPlane::Left as usize].xyz().cross(planes[FrustumPlane::Bottom as usize].xyz()), + planes[FrustumPlane::Left as usize].xyz().cross(planes[FrustumPlane::Top as usize].xyz()), + planes[FrustumPlane::Left as usize].xyz().cross(planes[FrustumPlane::Near as usize].xyz()), + planes[FrustumPlane::Left as usize].xyz().cross(planes[FrustumPlane::Far as usize].xyz()), + planes[FrustumPlane::Right as usize].xyz().cross(planes[FrustumPlane::Bottom as usize].xyz()), + planes[FrustumPlane::Right as usize].xyz().cross(planes[FrustumPlane::Top as usize].xyz()), + planes[FrustumPlane::Right as usize].xyz().cross(planes[FrustumPlane::Near as usize].xyz()), + planes[FrustumPlane::Right as usize].xyz().cross(planes[FrustumPlane::Far as usize].xyz()), + planes[FrustumPlane::Bottom as usize].xyz().cross(planes[FrustumPlane::Top as usize].xyz()), + planes[FrustumPlane::Bottom as usize].xyz().cross(planes[FrustumPlane::Near as usize].xyz()), + planes[FrustumPlane::Bottom as usize].xyz().cross(planes[FrustumPlane::Far as usize].xyz()), + planes[FrustumPlane::Top as usize].xyz().cross(planes[FrustumPlane::Near as usize].xyz()), + planes[FrustumPlane::Top as usize].xyz().cross(planes[FrustumPlane::Far as usize].xyz()), + planes[FrustumPlane::Near as usize].xyz().cross(planes[FrustumPlane::Far as usize].xyz()), + ]; + + Self { planes, crosses } + } +} diff --git a/src/camera/matrices.rs b/src/camera/matrices.rs new file mode 100644 index 0000000..b2086f6 --- /dev/null +++ b/src/camera/matrices.rs @@ -0,0 +1,42 @@ +use glam::{Vec3, Mat4}; +use shipyard::{ViewMut, View, IntoIter, Workload, IntoWorkload}; +use crate::{transform::Transform, events::WindowResizedEvent}; +use super::Camera; + +//maybe parallelize these two? + +fn update_view_matrix( + mut vm_camera: ViewMut, + v_transform: View +) { + for (camera, transform) in (&mut vm_camera, v_transform.inserted_or_modified()).iter() { + let (_, rotation, translation) = transform.0.to_scale_rotation_translation(); + let direction = rotation * Vec3::NEG_Z; + camera.view_matrix = Mat4::look_to_rh(translation, direction, camera.up); + } +} + +fn update_perspective_matrix( + mut vm_camera: ViewMut, + resize: View, +) { + //TODO update on launch + let Some(&size) = resize.iter().next() else { + return + }; + for camera in (&mut vm_camera).iter() { + camera.perspective_matrix = Mat4::perspective_rh_gl( + camera.fov, + size.0.x as f32 / size.0.y as f32, + camera.z_near, + camera.z_far, + ) + } +} + +pub fn update_matrices() -> Workload { + ( + update_view_matrix, + update_perspective_matrix, + ).into_workload() +}