1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
use glam::{Mat3A, Vec3A};

use super::geometry::Tri;

use crate::linear_algebra::math::dot;

#[derive(Clone, Debug, Default)]
pub struct Mesh {
    pub ids: Vec<i32>,
    pub vertices: Vec<f32>,
}

impl Mesh {
    pub fn from(other_meshes: Vec<&Self>) -> Self {
        let mut id_offset = 0;

        let mut n_ids = 0;
        let mut n_vertices = 0;

        for m in &other_meshes {
            n_ids += m.ids.len();
            n_vertices += m.vertices.len();
        }

        let mut ids: Vec<i32> = Vec::with_capacity(n_ids);
        let mut vertices: Vec<f32> = Vec::with_capacity(n_vertices);

        for m in other_meshes {
            for id in &m.ids {
                ids.push(id + id_offset);
            }

            for vertex in &m.vertices {
                vertices.push(*vertex);
            }

            id_offset += (m.vertices.len() / 3) as i32;
        }

        Self {
            ids,
            vertices,
        }
    }

    pub fn transform(&self, a: Mat3A) -> Self {
        debug_assert_eq!(self.vertices.len() % 3, 0);
        debug_assert_eq!(self.ids.len() % 3, 0);

        let vertices = self
            .vertices
            .chunks(3)
            .flat_map(|vertex| {
                let v = dot(a, Vec3A::from_slice(vertex));
                v.to_array()
            })
            .collect();

        // for transformations that flip things
        // inside-out, change triangle winding
        let ids = if a.determinant() < 0. {
            self.ids.chunks(3).flat_map(|ids| [ids[1], ids[0], ids[2]]).collect()
        } else {
            self.ids.clone()
        };

        Mesh {
            ids,
            vertices,
        }
    }

    pub fn translate(&self, p: Vec3A) -> Self {
        debug_assert_eq!(self.vertices.len() % 3, 0);

        let vertices = self.vertices.chunks(3).flat_map(|vertex| (Vec3A::from_slice(vertex) + p).to_array()).collect();

        Self {
            ids: self.ids.clone(),
            vertices,
        }
    }

    #[rustfmt::skip]
    pub fn to_triangles(&self) -> Vec<Tri> {
        let n = self.ids.len() / 3;
        let mut triangles: Vec<Tri> = Vec::with_capacity(n);

        for i in 0..n {
            triangles.push(Tri::default());
            for j in 0..3 {
                let id = (self.ids[i * 3 + j] * 3) as usize;
                triangles[i].p[j].x = self.vertices[id    ] as f32;
                triangles[i].p[j].y = self.vertices[id + 1] as f32;
                triangles[i].p[j].z = self.vertices[id + 2] as f32;
            }
        }

        triangles
    }
}