magical transform functions
This commit is contained in:
parent
801c0b4495
commit
f8b8ff2258
|
|
@ -1,4 +1,6 @@
|
|||
use glam::{Vec3, vec3};
|
||||
use std::f32::consts::PI;
|
||||
|
||||
use glam::{Mat4, Vec3, vec3};
|
||||
|
||||
/// A camera always directed at the origin.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
|
|
@ -19,24 +21,38 @@ impl OrbitalCamera {
|
|||
let (z, xy) = self.position_pitch.sin_cos();
|
||||
self.distance * vec3(xy * x, xy * y, z)
|
||||
}
|
||||
|
||||
pub fn transform(&self) -> Mat4 {
|
||||
Mat4::from_translation(vec3(0., 0., self.distance))
|
||||
* Mat4::from_euler(glam::EulerRot::ZXZ, 0., PI / 2., -PI / 2.)
|
||||
* Mat4::from_euler(
|
||||
glam::EulerRot::ZYZ,
|
||||
0.,
|
||||
self.position_pitch,
|
||||
-self.position_yaw,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use approx::assert_ulps_eq;
|
||||
use approx::{abs_diff_eq, assert_ulps_eq};
|
||||
use glam::vec3;
|
||||
|
||||
use super::*;
|
||||
|
||||
fn camera_deg(yaw: f32, pitch: f32) -> OrbitalCamera {
|
||||
OrbitalCamera {
|
||||
position_yaw: yaw.to_radians(),
|
||||
position_pitch: pitch.to_radians(),
|
||||
distance: 1.0,
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_orbital_camera_position() {
|
||||
fn camera_pos_deg(yaw: f32, pitch: f32) -> Vec3 {
|
||||
OrbitalCamera {
|
||||
position_yaw: yaw.to_radians(),
|
||||
position_pitch: pitch.to_radians(),
|
||||
distance: 1.0,
|
||||
}
|
||||
.position()
|
||||
camera_deg(yaw, pitch).position()
|
||||
}
|
||||
assert_ulps_eq!(camera_pos_deg(0., 0.), vec3(1., 0., 0.), max_ulps = 3);
|
||||
assert_ulps_eq!(camera_pos_deg(90., 0.), vec3(0., 1., 0.), max_ulps = 3);
|
||||
|
|
@ -48,4 +64,34 @@ mod tests {
|
|||
assert_ulps_eq!(camera_pos_deg(0., 45.), vec3(s2, 0., s2), max_ulps = 3);
|
||||
assert_ulps_eq!(camera_pos_deg(45., 45.), vec3(0.5, 0.5, s2), max_ulps = 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_orbital_camera_forward() {
|
||||
const EPSILON: f32 = 1e-5;
|
||||
for pitch in [0., 30., 45., 89., 90.] {
|
||||
for yaw in [0., 30., 45., 89., 90.] {
|
||||
let camera = camera_deg(yaw, pitch);
|
||||
let pos = camera.position();
|
||||
let tfm = camera.transform();
|
||||
|
||||
let mapped = tfm.transform_vector3(-pos);
|
||||
assert!(
|
||||
abs_diff_eq!(mapped, vec3(0., 0., 1.), epsilon = EPSILON),
|
||||
"direction not mapped to +Z: yaw={yaw:?}°, pitch={pitch:?}°, pos={pos:?}, mapped={mapped:?}"
|
||||
);
|
||||
|
||||
let mapped = tfm.transform_point3(pos);
|
||||
assert!(
|
||||
abs_diff_eq!(mapped, Vec3::ZERO, epsilon = EPSILON),
|
||||
"pos not mapped to origin: yaw={yaw:?}°, pitch={pitch:?}°, pos={pos:?}, mapped={mapped:?}"
|
||||
);
|
||||
|
||||
let mapped = tfm.transform_point3(Vec3::ZERO);
|
||||
assert!(
|
||||
abs_diff_eq!(mapped, vec3(0., 0., 1.), epsilon = EPSILON),
|
||||
"origin not mapped to (0, 0, 1): yaw={yaw:?}°, pitch={pitch:?}°, pos={pos:?}, mapped={mapped:?}"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user