use std::{collections::HashMap, hash::Hash};
use fj_math::Point;
use crate::Color;
#[derive(Clone, Debug)]
pub struct Mesh<V> {
vertices: Vec<V>,
indices: Vec<Index>,
indices_by_vertex: HashMap<V, Index>,
triangles: Vec<Triangle>,
}
impl<V> Mesh<V>
where
V: Copy + Eq + Hash,
{
pub fn new() -> Self {
Self::default()
}
pub fn push_vertex(&mut self, vertex: V) {
let index =
*self.indices_by_vertex.entry(vertex).or_insert_with(|| {
let index = self.vertices.len();
self.vertices.push(vertex);
index as u32
});
self.indices.push(index);
}
pub fn contains_triangle(
&self,
triangle: impl Into<fj_math::Triangle<3>>,
) -> bool {
let triangle = triangle.into().normalize();
for t in &self.triangles {
let t = t.inner.normalize();
if triangle == t {
return true;
}
}
false
}
pub fn vertices(&self) -> impl Iterator<Item = V> + '_ {
self.vertices.iter().copied()
}
pub fn indices(&self) -> impl Iterator<Item = Index> + '_ {
self.indices.iter().copied()
}
pub fn triangles(&self) -> impl Iterator<Item = Triangle> + '_ {
self.triangles.iter().copied()
}
}
impl Mesh<Point<3>> {
pub fn push_triangle(
&mut self,
triangle: impl Into<fj_math::Triangle<3>>,
color: Color,
) {
let triangle = triangle.into();
for point in triangle.points() {
self.push_vertex(point);
}
self.triangles.push(Triangle {
inner: triangle,
color,
});
}
}
impl<V> Default for Mesh<V> {
fn default() -> Self {
Self {
vertices: Vec::default(),
indices: Vec::default(),
indices_by_vertex: HashMap::default(),
triangles: Vec::default(),
}
}
}
pub type Index = u32;
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct Triangle {
pub inner: fj_math::Triangle<3>,
pub color: Color,
}