1use std::{collections::HashMap, hash::Hash};
2
3use fj_math::Point;
4
5use crate::Color;
6
7#[derive(Clone, Debug)]
9pub struct Mesh<V> {
10 vertices: Vec<V>,
11 indices: Vec<Index>,
12
13 indices_by_vertex: HashMap<V, Index>,
14 triangles: Vec<Triangle>,
15}
16
17impl<V> Mesh<V>
18where
19 V: Copy + Eq + Hash,
20{
21 pub fn new() -> Self {
23 Self::default()
24 }
25
26 pub fn push_vertex(&mut self, vertex: V) {
28 let index =
29 *self.indices_by_vertex.entry(vertex).or_insert_with(|| {
30 let index = self.vertices.len();
31 self.vertices.push(vertex);
32 index as u32
33 });
34
35 self.indices.push(index);
36 }
37
38 pub fn contains_triangle(
43 &self,
44 triangle: impl Into<fj_math::Triangle<3>>,
45 ) -> bool {
46 let triangle = triangle.into().normalize();
47
48 for t in &self.triangles {
49 let t = t.inner.normalize();
50 if triangle == t {
51 return true;
52 }
53 }
54
55 false
56 }
57
58 pub fn vertices(&self) -> impl Iterator<Item = V> + '_ {
60 self.vertices.iter().copied()
61 }
62
63 pub fn indices(&self) -> impl Iterator<Item = Index> + '_ {
65 self.indices.iter().copied()
66 }
67
68 pub fn triangles(&self) -> impl Iterator<Item = Triangle> + '_ {
70 self.triangles.iter().copied()
71 }
72}
73
74impl Mesh<Point<3>> {
75 pub fn push_triangle(
77 &mut self,
78 triangle: impl Into<fj_math::Triangle<3>>,
79 color: Color,
80 ) {
81 let triangle = triangle.into();
82
83 for point in triangle.points() {
84 self.push_vertex(point);
85 }
86
87 self.triangles.push(Triangle {
88 inner: triangle,
89 color,
90 });
91 }
92}
93
94impl<V> Default for Mesh<V> {
97 fn default() -> Self {
98 Self {
99 vertices: Vec::default(),
100 indices: Vec::default(),
101 indices_by_vertex: HashMap::default(),
102 triangles: Vec::default(),
103 }
104 }
105}
106
107pub type Index = u32;
109
110#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
114pub struct Triangle {
115 pub inner: fj_math::Triangle<3>,
117
118 pub color: Color,
120}