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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
//! Format-independent mesh representation.
use {Vertex, Index, Triangle, Error};

use std::iter::FromIterator;
use std::fmt;

/// A 3D model.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Model<V: Vertex, I: Index> {
    /// The mesh that makes up the model.
    pub mesh: TriangularMesh<V, I>,
}

/// Something which we can build a model out of.
pub trait BuildModel {
    /// The vertex type that we need to convert from.
    type Vertex;

    fn build_model<V,I>(self) -> Result<Model<V,I>, Error>
        where V: Vertex, I: Index, V: From<Self::Vertex>;
}

/// A triangular mesh.
#[derive(Clone, PartialEq, Eq)]
pub struct TriangularMesh<V: Vertex, I: Index> {
    /// The vertex list.
    pub vertices: Vec<V>,
    /// The index list.
    pub indices: Vec<I>,
}

/// All of the triangles in a mesh.
pub struct Triangles<'a, V: Vertex+'a, I: Index+'a>
{
    mesh: &'a TriangularMesh<V,I>,
    indices: ::std::slice::Iter<'a, I>,
}

impl<V: Vertex, I: Index> Model<V,I> {
    /// Creates an empty mesh.
    pub fn empty() -> Self {
        Model { mesh: TriangularMesh::empty() }
    }

    /// Creates a new model.
    pub fn new<F>(builder: F) -> Result<Self, Error>
        where F: BuildModel, V: From<F::Vertex> {
        builder.build_model()
    }
}

impl<V: Vertex, I: Index> fmt::Debug for TriangularMesh<V,I> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        // Create a trait for debug printing.
        #[derive(Debug)]
        struct TriangularMesh {
            pub vertex_count: usize,
            pub index_count: usize,
        }

        TriangularMesh {
            vertex_count: self.vertices.len(),
            index_count: self.indices.len(),
        }.fmt(fmt)
    }
}

impl<V: Vertex, I: Index> TriangularMesh<V,I> {
    /// Creates an empty triangular mesh.
    pub fn empty() -> Self {
        TriangularMesh { vertices: Vec::new(), indices: Vec::new() }
    }

    /// Gets all of the triangles in a mesh.
    pub fn triangles(&self) -> Triangles<V,I> {
        Triangles { mesh: self, indices: self.indices.iter() }
    }
}

impl<V,I> FromIterator<Triangle<V>> for TriangularMesh<V,I>
    where V: Vertex, I: Index
{
    fn from_iter<T>(iter: T) -> Self
        where T: IntoIterator<Item=Triangle<V>> {
        let triangles: Vec<_> = iter.into_iter().collect();

        let mut vertices: Vec<_> = triangles.iter().flat_map(|tri| tri.vertices.iter().cloned()).collect();
        vertices.sort_by(|a, b| a.partial_cmp(b).unwrap());
        vertices.dedup();

        let indices = triangles.iter().flat_map(|tri| {
            tri.vertices.iter().map(|vert| {
                let index: u64 = vertices.binary_search_by(|a| a.partial_cmp(vert).unwrap()).unwrap() as u64;
                I::from_u64(index).expect("index type too small for mesh")
            })
        }).collect();

        TriangularMesh { vertices: vertices, indices: indices }
    }
}

impl<'a, V: Vertex+'a, I: Index+'a> Iterator for Triangles<'a, V, I> {
    type Item = Triangle<V>;

    fn next(&mut self) -> Option<Triangle<V>> {
        if let Some(i1) = self.indices.next() {
            let i2 = self.indices.next().expect("expected at least two more indices");
            let i3 = self.indices.next().expect("expected at least one more index");

            let vertices: Vec<_> = [i1,i2,i3].iter().map(|&&idx| {
                let idx: u64 = idx.into();
                self.mesh.vertices[idx as usize].clone()
            }).collect();

            Some(Triangle {
                vertices: [vertices[0].clone(), vertices[1].clone(), vertices[2].clone()],
            })
        } else {
            None
        }
    }
}

#[cfg(test)]
mod test {
    use {TriangularMesh, Vector, Triangle};
    use build;

    #[test]
    fn can_enumerate_triangles() {
        let cube: TriangularMesh<Vector,u64> = build::unit_cube();
        assert_eq!(cube.triangles().count(), 12);
    }

    #[test]
    fn can_build_out_of_triangles() {
        let triangles = vec![
            Triangle { vertices: [Vector(1.0, 1.0, 1.0), Vector(2.0, 2.0, 2.0), Vector(3.0,3.0,3.0)] },
            Triangle { vertices: [Vector(5.0, 5.0, 5.0), Vector(6.0, 6.0, 6.0), Vector(7.0,7.0,7.0)] },
        ];

        let mesh: TriangularMesh<_, u16> = triangles.into_iter().collect();
        let processed_triangles: Vec<_> = mesh.triangles().collect();

        assert_eq!(processed_triangles, vec![
            Triangle { vertices: [Vector(1.0, 1.0, 1.0), Vector(2.0, 2.0, 2.0), Vector(3.0,3.0,3.0)] },
            Triangle { vertices: [Vector(5.0, 5.0, 5.0), Vector(6.0, 6.0, 6.0), Vector(7.0,7.0,7.0)] },
        ]);
    }
}