use crate::Scalar;
pub type Vec2 = glam::DVec2;
pub type Vec3 = glam::DVec3;
pub type Point2 = Vec2;
pub type Point3 = Vec3;
pub type Mat3 = glam::DMat3;
pub type Transform2 = glam::DAffine2;
pub type Transform3 = glam::DAffine3;
pub type Mat4 = glam::DMat4;
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Frame2 {
pub origin: Point2,
pub x: Vec2,
pub y: Vec2,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Frame3 {
pub origin: Point3,
pub x: Vec3,
pub y: Vec3,
pub z: Vec3,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Interval {
pub start: Scalar,
pub end: Scalar,
}
impl Interval {
pub const UNIT: Self = Self {
start: 0.0,
end: 1.0,
};
pub const fn new(start: Scalar, end: Scalar) -> Self {
Self { start, end }
}
pub fn length(self) -> Scalar {
(self.end - self.start).abs()
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Plane3 {
pub origin: Point3,
pub normal: Vec3,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Ray3 {
pub origin: Point3,
pub direction: Vec3,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn projective_matrix_divides_by_w_and_affine_cannot() {
let projection = Mat4::perspective_rh(std::f64::consts::FRAC_PI_2, 1.0, 1.0, 100.0);
let near = projection.project_point3(Point3::new(0.0, 1.0, -2.0));
let far = projection.project_point3(Point3::new(0.0, 1.0, -4.0));
assert!(
(near.y / far.y - 2.0).abs() < 1e-12,
"near {near:?} far {far:?}"
);
let affine = Transform3::IDENTITY;
let near_affine = affine.transform_point3(Point3::new(0.0, 1.0, -2.0));
let far_affine = affine.transform_point3(Point3::new(0.0, 1.0, -4.0));
assert_eq!(near_affine.y, far_affine.y);
}
#[test]
fn a_projective_matrix_round_trips_through_its_affine_subset() {
let affine = Transform3::from_translation(Vec3::new(1.0, 2.0, 3.0));
let promoted = Mat4::from(affine);
let point = Point3::new(0.5, -0.5, 2.0);
assert_eq!(
promoted.project_point3(point),
affine.transform_point3(point)
);
}
}