mirror of
https://github.com/griffi-gh/kubi.git
synced 2024-12-22 20:08:20 -06:00
Wip frustum code port
This commit is contained in:
parent
783b6a1f84
commit
19fa7e67bc
|
@ -1,7 +1,11 @@
|
||||||
use glam::{Mat4, Vec3};
|
use glam::{Mat4, Vec3};
|
||||||
use shipyard::{Component, ViewMut, View, IntoIter, Workload, IntoWorkload};
|
use shipyard::{Component, Workload, IntoWorkload};
|
||||||
use std::f32::consts::PI;
|
use std::f32::consts::PI;
|
||||||
use crate::{transform::Transform, events::WindowResizedEvent};
|
|
||||||
|
mod matrices;
|
||||||
|
mod frustum;
|
||||||
|
|
||||||
|
use matrices::update_matrices;
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub struct Camera {
|
pub struct Camera {
|
||||||
|
@ -29,36 +33,6 @@ impl Default for Camera {
|
||||||
|
|
||||||
pub fn compute_cameras() -> Workload {
|
pub fn compute_cameras() -> Workload {
|
||||||
(
|
(
|
||||||
update_perspective_matrix,
|
update_matrices,
|
||||||
update_view_matrix,
|
|
||||||
).into_workload()
|
).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