mirror of
https://github.com/griffi-gh/kubi.git
synced 2024-12-22 11:58:21 -06:00
Wip frustum code port
This commit is contained in:
parent
783b6a1f84
commit
19fa7e67bc
|
@ -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<Camera>,
|
||||
v_transform: View<Transform>
|
||||
) {
|
||||
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<Camera>,
|
||||
resize: View<WindowResizedEvent>,
|
||||
) {
|
||||
//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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
66
src/camera/frustum.rs
Normal file
66
src/camera/frustum.rs
Normal file
|
@ -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 }
|
||||
}
|
||||
}
|
42
src/camera/matrices.rs
Normal file
42
src/camera/matrices.rs
Normal file
|
@ -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<Camera>,
|
||||
v_transform: View<Transform>
|
||||
) {
|
||||
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<Camera>,
|
||||
resize: View<WindowResizedEvent>,
|
||||
) {
|
||||
//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()
|
||||
}
|
Loading…
Reference in a new issue