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
// 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 gfx_core::handle;
use gfx_core::{Primitive, Resources, VertexCount};
use gfx_core::draw::InstanceOption;
use gfx_core::factory::{BufferRole, Factory};

/// 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 `primitive` 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,
    /// Instancing configuration.
    pub instances: InstanceOption,
    /// 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, prim: Primitive) -> u32 {
        use gfx_core::Primitive::*;
        let nv = (self.end - self.start) as u32;
        match prim {
            PointList => nv,
            LineList => 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::Buffer<R, u8>, VertexCount),
    /// As `Index8` but with `u16` indices
    Index16(handle::Buffer<R, u16>, VertexCount),
    /// As `Index8` but with `u32` indices
    Index32(handle::Buffer<R, u32>, VertexCount),
}

/// A helper trait to build index slices from data.
pub trait ToIndexSlice<R: Resources> { //TODO: remove/refactor it
    /// Make an index slice.
    fn to_slice<F: Factory<R>>(self, factory: &mut F) -> Slice<R>;
}

macro_rules! impl_slice {
    ($ty:ty, $index:ident) => (
        impl<R: Resources> From<handle::Buffer<R, $ty>> for Slice<R> {
            fn from(buf: handle::Buffer<R, $ty>) -> Slice<R> {
                Slice {
                    start: 0,
                    end: buf.len() as VertexCount,
                    instances: None,
                    kind: SliceKind::$index(buf, 0)
                }
            }
        }
        impl<'a, R: Resources> ToIndexSlice<R> for &'a [$ty] {
            fn to_slice<F: Factory<R>>(self, factory: &mut F) -> Slice<R> {
                //debug_assert!(self.len() <= factory.get_capabilities().max_index_count);
                factory.create_buffer_static(self, BufferRole::Index).into()
            }
        }
    )
}

impl_slice!(u8, Index8);
impl_slice!(u16, Index16);
impl_slice!(u32, Index32);