use gfx;
use gfx_debug_draw;
use collada;
use math::*;
use transform::{Transform, FromTransform};
pub type JointIndex = u8;
pub const ROOT_JOINT_PARENT_INDEX: JointIndex = 255u8;
#[derive(Debug, Clone)]
pub struct Skeleton {
pub joints: Vec<Joint>,
}
impl Skeleton {
pub fn from_collada(skeleton: &collada::Skeleton) -> Skeleton {
Skeleton {
joints: skeleton.joints.iter().map(|j| {
Joint {
name: j.name.clone(),
parent_index: j.parent_index,
inverse_bind_pose: j.inverse_bind_pose,
}
}).collect()
}
}
pub fn calculate_global_poses<T: Transform, TOutput: Transform + FromTransform<T>>(
&self,
local_poses: &[T],
global_poses: &mut [TOutput],
) {
for (joint_index, joint) in self.joints.iter().enumerate() {
let parent_pose = if !joint.is_root() {
global_poses[joint.parent_index as usize]
} else {
TOutput::identity()
};
let local_pose = local_poses[joint_index];
global_poses[joint_index] = parent_pose.concat(TOutput::from_transform(local_pose));
}
}
pub fn get_joint_index(&self, joint_name: &str) -> Option<JointIndex> {
for (index, joint) in self.joints.iter().enumerate() {
if joint.name == joint_name {
return Some(index as JointIndex);
}
}
None
}
pub fn draw<R: gfx::Resources, F: gfx::Factory<R>, T: Transform> (
&self,
global_poses: &[T],
debug_renderer: &mut gfx_debug_draw::DebugRenderer<R, F>,
draw_labels: bool)
{
for (joint_index, joint) in self.joints.iter().enumerate() {
let joint_position = global_poses[joint_index].transform_vector([0.0, 0.0, 0.0]);
let leaf_end = global_poses[joint_index].transform_vector([0.0, 1.0, 0.0]);
if !joint.is_root() {
let parent_position = global_poses[joint.parent_index as usize].transform_vector([0.0, 0.0, 0.0]);
debug_renderer.draw_line(
[parent_position[0], parent_position[1], parent_position[2]],
[joint_position[0], joint_position[1], joint_position[2]],
[0.2, 0.2, 0.2, 1.0]
);
if !self.joints.iter().any(|j| j.parent_index as usize == joint_index) {
debug_renderer.draw_line(
[joint_position[0], joint_position[1], joint_position[2]],
[leaf_end[0], leaf_end[1], leaf_end[2]],
[0.2, 0.2, 0.2, 1.0]
);
}
}
if draw_labels {
debug_renderer.draw_text_at_position(
&joint.name[..],
[leaf_end[0], leaf_end[1], leaf_end[2]],
[1.0, 1.0, 1.0, 1.0]
);
}
let p_x_axis = global_poses[joint_index].transform_vector([1.0, 0.0, 0.0]);
let p_y_axis = global_poses[joint_index].transform_vector([0.0, 1.0, 0.0]);
let p_z_axis = global_poses[joint_index].transform_vector([0.0, 0.0, 1.0]);
debug_renderer.draw_line(
[joint_position[0], joint_position[1], joint_position[2]],
[p_x_axis[0], p_x_axis[1], p_x_axis[2]],
[1.0, 0.2, 0.2, 1.0]
);
debug_renderer.draw_line(
[joint_position[0], joint_position[1], joint_position[2]],
[p_y_axis[0], p_y_axis[1], p_y_axis[2]],
[0.2, 1.0, 0.2, 1.0]
);
debug_renderer.draw_line(
[joint_position[0], joint_position[1], joint_position[2]],
[p_z_axis[0], p_z_axis[1], p_z_axis[2]],
[0.2, 0.2, 1.0, 1.0]
);
}
}
}
#[derive(Debug, Clone)]
pub struct Joint {
pub name: String,
pub parent_index: JointIndex,
pub inverse_bind_pose: Matrix4<f32>,
}
impl Joint {
pub fn is_root(&self) -> bool {
self.parent_index == ROOT_JOINT_PARENT_INDEX
}
}