2022-07-05 06:13:39 +00:00
|
|
|
use bevy_math::{Mat4, Vec4};
|
|
|
|
|
|
|
|
/// A distance calculator for the draw order of [`PhaseItem`](crate::render_phase::PhaseItem)s.
|
|
|
|
pub struct ViewRangefinder3d {
|
|
|
|
inverse_view_row_2: Vec4,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ViewRangefinder3d {
|
|
|
|
/// Creates a 3D rangefinder for a view matrix
|
|
|
|
pub fn from_view_matrix(view_matrix: &Mat4) -> ViewRangefinder3d {
|
|
|
|
let inverse_view_matrix = view_matrix.inverse();
|
|
|
|
ViewRangefinder3d {
|
|
|
|
inverse_view_row_2: inverse_view_matrix.row(2),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-12 13:06:16 +00:00
|
|
|
/// Calculates the distance, or view-space `Z` value, for a transform
|
2022-07-05 06:13:39 +00:00
|
|
|
#[inline]
|
|
|
|
pub fn distance(&self, transform: &Mat4) -> f32 {
|
|
|
|
// NOTE: row 2 of the inverse view matrix dotted with column 3 of the model matrix
|
|
|
|
// gives the z component of translation of the mesh in view-space
|
|
|
|
self.inverse_view_row_2.dot(transform.col(3))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::ViewRangefinder3d;
|
|
|
|
use bevy_math::{Mat4, Vec3};
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn distance() {
|
|
|
|
let view_matrix = Mat4::from_translation(Vec3::new(0.0, 0.0, -1.0));
|
|
|
|
let rangefinder = ViewRangefinder3d::from_view_matrix(&view_matrix);
|
|
|
|
assert_eq!(rangefinder.distance(&Mat4::IDENTITY), 1.0);
|
|
|
|
assert_eq!(
|
|
|
|
rangefinder.distance(&Mat4::from_translation(Vec3::new(0.0, 0.0, 1.0))),
|
|
|
|
2.0
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|