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
extern crate vecmath;
extern crate xml;

#[macro_use]
extern crate log;

pub use obj::*;
pub use vecmath::Matrix4;

pub mod document;
mod obj;
mod utils;

#[derive(Debug, Clone)]
pub struct Skeleton {
    ///
    /// All joints in the skeleton
    ///
    pub joints: Vec<Joint>,

    ///
    /// Default parent-relative transforms for each joint (at time of vertex binding)
    /// Column-major.
    ///
    pub bind_poses: Vec<Matrix4<f32>>,
}

#[derive(Debug, Clone)]
pub struct Joint {
    ///
    /// Name of joint
    ///
    pub name: String,

    ///
    /// Index of parent joint in Skeleton's 'joints' vector
    ///
    pub parent_index: JointIndex,

    ///
    /// Matrix transforming vertex coordinates from model-space to joint-space
    /// Column-major.
    ///
    pub inverse_bind_pose: Matrix4<f32>,
}

impl Joint {
    pub fn is_root(&self) -> bool {
        self.parent_index == ROOT_JOINT_PARENT_INDEX
    }
}

///
/// A COLLADA animation consists of mapping of sample times to pose transforms
/// for a single node in the scene (usually a skeleton joint)
///
/// Note - COLLADA supports animating arbitrary 'outputs', not just pose transforms,
/// (eg colors, texture offsets, etc), but we'll leave those unsupported for now.
///
#[derive(Debug)]
pub struct Animation {
    ///
    /// The node (joint) this animation is targeting
    ///
    pub target: String,

    ///
    /// Times for each sample (in seconds)
    ///
    pub sample_times: Vec<f32>,

    ///
    /// Node pose transforms for each sample.
    /// Column-major.
    ///
    pub sample_poses: Vec<Matrix4<f32>>,
}

///
/// Skeleton-Mesh Binding Data
///

#[derive(Debug)]
pub struct BindDataSet {
    pub bind_data: Vec<BindData>,
}

#[derive(Debug)]
pub struct BindData {
    pub object_name: String,
    pub skeleton_name: Option<String>,
    pub joint_names: Vec<String>,

    /// Vertex weights, for vertex by index in mesh and joint by index in 'joint_names'
    /// and weight by index in 'weights'
    pub vertex_weights: Vec<VertexWeight>,

    /// Weight values that are indexed by VertexWeights
    pub weights: Vec<f32>,

    /// Inverse bind pose matrices listed in order of joint_names
    /// Column-major
    pub inverse_bind_poses: Vec<Matrix4<f32>>,
}

#[derive(Debug, Copy, Clone)]
pub struct VertexWeight {
    pub vertex: VertexIndex,
    pub joint: JointIndex,
    pub weight: WeightIndex,
}

pub type WeightIndex = usize;

pub type JointIndex = u8;
pub const ROOT_JOINT_PARENT_INDEX: JointIndex = 255u8;