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
use std::result::Result as StdResult;

use amethyst_assets::{PrefabData, PrefabError};
use amethyst_core::specs::prelude::{
    Component, DenseVecStorage, Entity, FlaggedStorage, WriteStorage,
};
use gfx::format::{ChannelType, Format, SurfaceType};

use error::Result;
use formats::MeshCreator;
use mesh::{Mesh, MeshBuilder};
use renderer::Renderer;
use vertex::{Attribute, Color, Normal, Position, Separate, Tangent, TexCoord};

/// Type for joint weights attribute of vertex
#[derive(Clone, Debug)]
pub enum JointWeights {}
impl Attribute for JointWeights {
    const NAME: &'static str = "joint_weights";
    const FORMAT: Format = Format(SurfaceType::R32_G32_B32_A32, ChannelType::Unorm);
    const SIZE: u32 = 16;
    type Repr = [f32; 4];
}

/// Type for joint ids attribute of vertex
#[derive(Clone, Debug)]
pub enum JointIds {}
impl Attribute for JointIds {
    const NAME: &'static str = "joint_ids";
    const FORMAT: Format = Format(SurfaceType::R16_G16_B16_A16, ChannelType::Uint);
    const SIZE: u32 = 8;
    type Repr = [u16; 4];
}

/// Transform storage for the skin, should be attached to all mesh entities that use a skin
#[derive(Debug, Clone)]
pub struct JointTransforms {
    /// Skin entity
    pub skin: Entity,
    /// The current joint matrices
    pub matrices: Vec<[[f32; 4]; 4]>,
}

impl Component for JointTransforms {
    type Storage = FlaggedStorage<Self, DenseVecStorage<Self>>;
}

/// Animation vertex combo
pub type AnimatedVertexBufferCombination = (
    Vec<Separate<Position>>,
    Option<Vec<Separate<Color>>>,
    Option<Vec<Separate<TexCoord>>>,
    Option<Vec<Separate<Normal>>>,
    Option<Vec<Separate<Tangent>>>,
    Option<Vec<Separate<JointIds>>>,
    Option<Vec<Separate<JointWeights>>>,
);

/// Build Mesh with vertex buffer combination
fn build_mesh_with_combo(
    combo: AnimatedVertexBufferCombination,
    renderer: &mut Renderer,
) -> Result<Mesh> {
    build_mesh_with_some!(
        MeshBuilder::new(combo.0),
        renderer,
        combo.1,
        combo.2,
        combo.3,
        combo.4,
        combo.5,
        combo.6
    )
}

/// Mesh creator for `VertexBufferCombination`.
#[derive(Debug, Clone)]
pub struct AnimatedComboMeshCreator {
    combo: AnimatedVertexBufferCombination,
}

impl AnimatedComboMeshCreator {
    /// Create a new combo mesh creator with the given combo
    pub fn new(combo: AnimatedVertexBufferCombination) -> Self {
        AnimatedComboMeshCreator { combo }
    }
}

impl MeshCreator for AnimatedComboMeshCreator {
    fn build(self: Box<Self>, renderer: &mut Renderer) -> Result<Mesh> {
        build_mesh_with_combo(self.combo, renderer)
    }

    fn box_clone(&self) -> Box<MeshCreator> {
        Box::new((*self).clone())
    }
}

impl From<AnimatedVertexBufferCombination> for AnimatedComboMeshCreator {
    fn from(combo: AnimatedVertexBufferCombination) -> Self {
        Self::new(combo)
    }
}

/// Prefab for `JointTransforms`
#[derive(Default, Clone, Debug, Deserialize, Serialize)]
pub struct JointTransformsPrefab {
    /// Index of skin `Entity`
    pub skin: usize,
    /// Number of joints in the skin
    pub size: usize,
}

impl<'a> PrefabData<'a> for JointTransformsPrefab {
    type SystemData = WriteStorage<'a, JointTransforms>;
    type Result = ();

    fn load_prefab(
        &self,
        entity: Entity,
        storage: &mut Self::SystemData,
        entities: &[Entity],
    ) -> StdResult<(), PrefabError> {
        storage
            .insert(
                entity,
                JointTransforms {
                    skin: entities[self.skin],
                    matrices: vec![[[0.; 4]; 4]; self.size],
                },
            )
            .map(|_| ())
    }
}