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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
// Copyright 2014 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Mesh loading.
//!
//! A `Mesh` describes the geometry of an object. All or part of a `Mesh` can be drawn with a
//! single draw call. A `Mesh` consists of a series of vertices, each with a certain amount of
//! user-specified attributes. These attributes are fed into shader programs. The easiest way to
//! create a mesh is to use the `#[vertex_format]` attribute on a struct, upload them into a
//! `Buffer`, and then use `Mesh::from`.

use device::{PrimitiveType, Resources, VertexCount};
use device::{attrib, handle, shade};

/// Describes a single attribute of a vertex buffer, including its type, name, etc.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct Attribute<R: Resources> {
    /// A name to match the shader input
    pub name: String,
    /// Vertex buffer to contain the data
    pub buffer: handle::RawBuffer<R>,
    /// Format of the attribute
    pub format: attrib::Format,
}

/// A trait implemented automatically for user vertex structure by
/// `#[vertex_format] attribute
#[allow(missing_docs)]
pub trait VertexFormat {
    /// Create the attributes for this type, using the given buffer.
    fn generate<R: Resources>(buffer: &handle::Buffer<R, Self>) -> Vec<Attribute<R>>;
}

/// Describes geometry to render.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct Mesh<R: Resources> {
    /// Number of vertices in the mesh.
    pub num_vertices: VertexCount,
    /// Vertex attributes to use.
    pub attributes: Vec<Attribute<R>>,
}

impl<R: Resources> Mesh<R> {
    /// Create a new mesh, which is a `TriangleList` with no attributes and `nv` vertices.
    pub fn new(nv: VertexCount) -> Mesh<R> {
        Mesh {
            num_vertices: nv,
            attributes: Vec::new(),
        }
    }

    /// Create a new `Mesh` from a struct that implements `VertexFormat` and a buffer.
    pub fn from_format<V: VertexFormat>(buf: handle::Buffer<R, V>, nv: VertexCount)
                       -> Mesh<R> {
        Mesh {
            num_vertices: nv,
            attributes: V::generate(&buf),
        }
    }

    /// Create a new intanced `Mesh` given a vertex buffer and an instance buffer.
    pub fn from_format_instanced<V: VertexFormat, U: VertexFormat>(
                                 buf: handle::Buffer<R, V>,
                                 nv: VertexCount,
                                 inst: handle::Buffer<R, U>) -> Mesh<R> {
        let per_vertex   = V::generate(&buf);
        let per_instance = U::generate(&inst);

        let mut attributes = per_vertex;
        attributes.extend(per_instance.into_iter().map(|mut a| {
            a.format.instance_rate = 1;
            a
        }));

        Mesh {
            num_vertices: nv,
            attributes: attributes,
        }
    }
}

/// Description of a subset of `Mesh` data to render.
///
/// Only vertices between `start` and `end` are rendered. The
/// source of the vertex data is dependent on the `kind` value.
///
/// The `prim_type` defines how the mesh contents are interpreted.
/// For example,  `Point` typed vertex slice can be used to do shape
/// blending, while still rendereing it as an indexed `TriangleList`.
#[derive(Clone, Debug, PartialEq)]
pub struct Slice<R: Resources> {
    /// Start index of vertices to draw.
    pub start: VertexCount,
    /// End index of vertices to draw.
    pub end: VertexCount,
    /// Primitive type to render collections of vertices as.
    pub prim_type: PrimitiveType,
    /// Source of the vertex ordering when drawing.
    pub kind: SliceKind<R>,
}

impl<R: Resources> Slice<R> {
    /// Get the number of primitives in this slice.
    pub fn get_prim_count(&self) -> u32 {
        use device::PrimitiveType::*;
        let nv = (self.end - self.start) as u32;
        match self.prim_type {
            Point => nv,
            Line => nv / 2,
            LineStrip => (nv-1),
            TriangleList => nv / 3,
            TriangleStrip | TriangleFan => (nv-2) / 3,
        }
    }
}

/// Source of vertex ordering for a slice
#[derive(Clone, Debug, PartialEq)]
pub enum SliceKind<R: Resources> {
    /// Render vertex data directly from the `Mesh`'s buffer.
    Vertex,
    /// The `Index*` buffer contains a list of indices into the `Mesh`
    /// data, so every vertex attribute does not need to be duplicated, only
    /// its position in the `Mesh`. The base index is added to this index
    /// before fetching the vertex from the buffer.  For example, when drawing
    /// a square, two triangles are needed.  Using only `Vertex`, one
    /// would need 6 separate vertices, 3 for each triangle. However, two of
    /// the vertices will be identical, wasting space for the duplicated
    /// attributes.  Instead, the `Mesh` can store 4 vertices and an
    /// `Index8` can be used instead.
    Index8(handle::IndexBuffer<R, u8>, VertexCount),
    /// As `Index8` but with `u16` indices
    Index16(handle::IndexBuffer<R, u16>, VertexCount),
    /// As `Index8` but with `u32` indices
    Index32(handle::IndexBuffer<R, u32>, VertexCount),
}

/// Helper methods for cleanly getting the slice of a type.
pub trait ToSlice<R: Resources> {
    /// Get the slice of a type.
    fn to_slice(&self, pt: PrimitiveType) -> Slice<R>;
}

impl<R: Resources> ToSlice<R> for Mesh<R> {
    /// Return a vertex slice of the whole mesh.
    fn to_slice(&self, ty: PrimitiveType) -> Slice<R> {
        Slice {
            start: 0,
            end: self.num_vertices,
            prim_type: ty,
            kind: SliceKind::Vertex
        }
    }
}

impl<R: Resources> ToSlice<R> for handle::IndexBuffer<R, u8> {
    /// Return an index slice of the whole buffer.
    fn to_slice(&self, ty: PrimitiveType) -> Slice<R> {
        Slice {
            start: 0,
            end: self.len() as VertexCount,
            prim_type: ty,
            kind: SliceKind::Index8(self.clone(), 0)
        }
    }
}

impl<R: Resources> ToSlice<R> for handle::IndexBuffer<R, u16> {
    /// Return an index slice of the whole buffer.
    fn to_slice(&self, ty: PrimitiveType) -> Slice<R> {
        Slice {
            start: 0,
            end: self.len() as VertexCount,
            prim_type: ty,
            kind: SliceKind::Index16(self.clone(), 0)
        }
    }
}

impl<R: Resources> ToSlice<R> for handle::IndexBuffer<R, u32> {
    /// Return an index slice of the whole buffer.
    fn to_slice(&self, ty: PrimitiveType) -> Slice<R> {
        Slice {
            start: 0,
            end: self.len() as VertexCount,
            prim_type: ty,
            kind: SliceKind::Index32(self.clone(), 0)
        }
    }
}

/// Index of a vertex attribute inside the mesh
pub type AttributeIndex = usize;

/// Describes kinds of errors that may occur in the mesh linking
#[derive(Clone, Debug, PartialEq)]
pub enum Error {
    /// A required attribute was missing.
    AttributeMissing(String),
    /// An attribute's type from the vertex format differed from the type used in the shader.
    AttributeType(String, shade::BaseType),
    /// An attribute index is out of supported bounds
    AttributeIndex(AttributeIndex),
    /// An input index is out of supported bounds
    ShaderInputIndex(usize),
}

const BITS_PER_ATTRIBUTE: AttributeIndex = 4;
const MESH_ATTRIBUTE_MASK: AttributeIndex = (1 << BITS_PER_ATTRIBUTE) - 1;
const MAX_SHADER_INPUTS: usize = 64 / BITS_PER_ATTRIBUTE;

/// An iterator over mesh attributes.
#[derive(Clone, Copy)]
pub struct AttributeIter {
    value: u64,
}

impl Iterator for AttributeIter {
    type Item = AttributeIndex;

    fn next(&mut self) -> Option<AttributeIndex> {
        let id = (self.value as AttributeIndex) & MESH_ATTRIBUTE_MASK;
        self.value >>= BITS_PER_ATTRIBUTE;
        Some(id)
    }
}

/// Holds a remapping table from shader inputs to mesh attributes.
#[derive(Clone, Copy)]
pub struct Link {
    table: u64,
}

impl Link {
    /// Match mesh attributes against shader inputs, produce a mesh link.
    /// Exposed to public to allow external `Batch` implementations to use it.
    pub fn new<R: Resources>(mesh: &Mesh<R>, pinfo: &shade::ProgramInfo)
                             -> Result<Link, Error> {
        let mut indices = Vec::new();
        for sat in pinfo.attributes.iter() {
            match mesh.attributes.iter().enumerate()
                      .find(|&(_, a)| a.name == sat.name) {
                Some((attrib_id, vat)) => match vat.format.elem_type.is_compatible(sat.base_type) {
                    Ok(_) => indices.push(attrib_id),
                    Err(_) => return Err(Error::AttributeType(sat.name.clone(), sat.base_type)),
                },
                None => return Err(Error::AttributeMissing(sat.name.clone())),
            }
        }
        Link::from_iter(indices.into_iter())
    }

    /// Construct a new link from an iterator over attribute indices.
    pub fn from_iter<I: Iterator<Item = AttributeIndex>>(iter: I)
                     -> Result<Link, Error> {
        let mut table = 0u64;
        for (input, attrib) in iter.enumerate() {
            if input >= MAX_SHADER_INPUTS {
                return Err(Error::ShaderInputIndex(input))
            } else if attrib > MESH_ATTRIBUTE_MASK {
                return Err(Error::AttributeIndex(attrib))
            } else {
                table |= (attrib as u64) << (input * BITS_PER_ATTRIBUTE);
            }
        }
        Ok(Link {
            table: table,
        })
    }

    /// Convert to an iterator returning attribute indices
    pub fn to_iter(&self) -> AttributeIter {
        AttributeIter {
            value: self.table,
        }
    }
}