use alloc::vec::Vec;
use crate::math::{
Affine, Lerp, Linear, Parametric, Point2, Point3, Vec2, Vec3,
};
use crate::render::Model;
pub use mesh::Mesh;
pub mod mesh;
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Vertex<P, A> {
pub pos: P,
pub attrib: A,
}
pub type Vertex2<A, B = Model> = Vertex<Point2<B>, A>;
pub type Vertex3<A, B = Model> = Vertex<Point3<B>, A>;
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[repr(transparent)]
pub struct Tri<V>(pub [V; 3]);
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[repr(transparent)]
pub struct Plane<V>(pub(crate) V);
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Ray<T: Affine>(pub T, pub T::Diff);
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Polyline<T>(pub Vec<T>);
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Edge<T>(pub T, pub T);
pub type Normal3 = Vec3;
pub type Normal2 = Vec2;
pub const fn vertex<P, A>(pos: P, attrib: A) -> Vertex<P, A> {
Vertex { pos, attrib }
}
impl<T> Polyline<T> {
pub fn new(verts: impl IntoIterator<Item = T>) -> Self {
Self(verts.into_iter().collect())
}
pub fn edges(&self) -> impl Iterator<Item = Edge<T>> + '_
where
T: Clone,
{
self.0
.windows(2)
.map(|e| Edge(e[0].clone(), e[1].clone()))
}
}
impl<T> Parametric<T> for Ray<T>
where
T: Affine<Diff: Linear<Scalar = f32>>,
{
fn eval(&self, t: f32) -> T {
self.0.add(&self.1.mul(t))
}
}
impl<T: Lerp + Clone> Parametric<T> for Polyline<T> {
fn eval(&self, t: f32) -> T {
assert!(self.0.len() > 0, "cannot eval an empty polyline");
let max = self.0.len() as f32 - 1.0;
let i = 0.0.lerp(&max, t.clamp(0.0, 1.0));
let t_rem = i % 1.0;
let i = i as usize;
if i == max as usize {
self.0[i].clone()
} else {
let p0 = &self.0[i];
let p1 = &self.0[i + 1];
p0.lerp(p1, t_rem)
}
}
}
impl<P: Lerp, A: Lerp> Lerp for Vertex<P, A> {
fn lerp(&self, other: &Self, t: f32) -> Self {
vertex(
self.pos.lerp(&other.pos, t),
self.attrib.lerp(&other.attrib, t),
)
}
}
#[cfg(test)]
mod tests {
use alloc::vec;
use super::*;
use crate::math::Parametric;
#[test]
fn polyline_eval_f32() {
let pl = Polyline(vec![0.0, 1.0, -0.5]);
assert_eq!(pl.eval(-5.0), 0.0);
assert_eq!(pl.eval(0.00), 0.0);
assert_eq!(pl.eval(0.25), 0.5);
assert_eq!(pl.eval(0.50), 1.0);
assert_eq!(pl.eval(0.75), 0.25);
assert_eq!(pl.eval(1.00), -0.5);
assert_eq!(pl.eval(5.00), -0.5);
}
#[test]
#[should_panic]
fn empty_polyline_eval() {
Polyline::<f32>(vec![]).eval(0.5);
}
#[test]
fn singleton_polyline_eval() {
let pl = Polyline(vec![3.14]);
assert_eq!(pl.eval(0.0), 3.14);
assert_eq!(pl.eval(1.0), 3.14);
}
}