use crate::{
components::Ty,
transformation::{Transformation, Bone, RotMode},
geometry::VertexGroups,
skinning::components::{
AnimatedGeometry, ArmatureCache, DefaultWeight,
},
physics::components::RigidBody,
light::shadow,
};
use rin::graphics::{node, Node};
use na::{Vec4, Vec3, Vec2, one, ToPnt};
use std::mem;
use super::Action;
#[derive(Clone, Copy, Debug, VertexFormat, Serialize, Deserialize)]
#[repr(C)]
pub struct Vertex{
pub position: Vec4,
pub normal: Vec4,
pub texcoord: Vec2,
pub default_weight: f32,
pad: f32,
}
impl Default for Vertex{
fn default() -> Vertex{
Vertex{
position: vec4!(vec3!(0.), 1.),
normal: vec4!(Vec3::y(), 1.),
texcoord: vec2!(0.),
default_weight: 0.,
pad: unsafe{ mem::uninitialized() },
}
}
}
impl rin::graphics::Vertex for Vertex{
type Position = Vec4;
fn position(&self) -> &Vec4 {
&self.position
}
fn position_mut(&mut self) -> &mut Vec4{
&mut self.position
}
}
impl rin::graphics::Normal for Vertex{
fn normal(&self) -> &Vec3 {
unsafe{ mem::transmute( &self.normal ) }
}
fn normal_mut(&mut self) -> &mut Vec3{
unsafe{ mem::transmute( &mut self.normal ) }
}
}
impl DefaultWeight for Vertex{
fn default_weight(&self) -> f32{
self.default_weight
}
fn set_default_weight(&mut self, dw: f32){
self.default_weight = dw;
}
}
#[cfg(feature="meshopt")]
impl meshopt::DecodePosition for Vertex{
fn decode_position(&self) -> [f32;3]{
[self.position.x, self.position.y, self.position.z]
}
}
impl<'a> From<(&'a rinblender::Vertex, f32)> for Vertex{
fn from(v: (&'a rinblender::Vertex, f32)) -> Vertex{
let (v, default_weight) = v;
Vertex{
position: vec4!(v.position, 1.0),
normal: vec4!(v.normal, 1.0),
texcoord: v.texcoord,
default_weight,
pad: unsafe{ mem::uninitialized() },
}
}
}
impl<'a> From<&'a rinblender::Transformations> for Transformation {
fn from(trafo: &'a rinblender::Transformations) -> Transformation {
let node = if let Some(parent_inv) = trafo.parent_inv {
Node::with_preparent(parent_inv, trafo.position, trafo.into_quat(), trafo.scale)
}else{
Node::new(trafo.position, trafo.into_quat(), trafo.scale)
};
if let Some(parent_bone) = trafo.parent_bone.clone(){
Transformation::from_node_parent_bone(node, parent_bone)
}else{
Transformation::from_node(node)
}
}
}
impl<'a> From<&'a rinblender::Bone> for Transformation {
fn from(bone: &'a rinblender::Bone) -> Transformation {
let mut trafo = Transformation::from(bone.transformations());
trafo.is_bone = true;
trafo
}
}
#[derive(Clone, Component, Debug, Serialize, Deserialize)]
pub struct Rotation(pub rinblender::Rotation);
impl<'a> From<(&'a rinblender::Bone, &'a str)> for Bone {
fn from(from: (&'a rinblender::Bone, &'a str)) -> Bone {
let (bone, prefix) = from;
let node = Transformation::from(bone.transformations()).node;
let mut flags = node::Flags::empty();
if bone.flags().contains(rinblender::bones::Flags::HINGE) {
flags |= node::Flags::NO_ROTATION_FROM_PARENT;
}
if bone.flags().contains(rinblender::bones::Flags::NO_SCALE) {
flags |= node::Flags::NO_SCALE_FROM_PARENT;
}
Bone{
original: node,
animated: one(),
rest_mat: bone.rest_mat().clone(),
inv_rest_mat: bone.inv_rest_mat().clone(),
inv_rest_mat3: bone.inv_rest_mat3().clone(),
animated_id: bone.animated_id(),
head: bone.head().to_pnt(),
tail: bone.tail().to_pnt(),
head_radius: bone.head_radius(),
tail_radius: bone.tail_radius(),
name: prefix.to_owned() + "_" + bone.name(),
rot_mode: bone.original_rot_mode().into(),
has_changed: false,
flags,
used: false,
}
}
}
#[derive(Clone,Component, Debug, Serialize, Deserialize)]
pub struct SceneIndex{
pub skeletons: Vec<rinecs::Entity>,
pub poses: Vec<rinecs::Entity>,
pub models: Vec<rinecs::Entity>,
pub lights: Vec<rinecs::Entity>,
pub empties: Vec<rinecs::Entity>,
}
#[derive(Clone, Copy)]
pub struct CharacterEntity{
pub character: rinecs::Entity,
pub skeleton: Option<rinecs::Entity>,
}
impl<'a> From<rinblender::TriModel<'a>> for AnimatedGeometry<Vertex>{
fn from(model: rinblender::TriModel<'a>) -> AnimatedGeometry<Vertex>{
let mut dvert = vec![];
let mut dweight = vec![];
for v in model.original_vertices().iter(){
if model.mesh().dvert.len() > v.original_idx as usize{
let dw = model.mesh().dvert(v.original_idx as usize);
let start = dweight.len();
dweight.extend_from_slice(dw);
let end = dweight.len();
dvert.push(Some(rinblender::mesh::MDeformVert{
dw_start: start,
dw_end: end,
flag: 0,
}));
}else{
dvert.push(None);
}
}
AnimatedGeometry{
geom: model.animated_vertices().iter().map(|v| {
let default_group = model.default_group();
let default_group = default_group.map(|d| d.as_ref()).unwrap_or("");
let default_weight = if model.mesh().dvert.len() > v.original_idx as usize{
model.mesh()
.dvert(v.original_idx as usize)
.iter()
.find(|weight| model.vertex_groups().len() > weight.def_nr as usize &&
model.vertex_groups()[weight.def_nr as usize] == default_group)
.map(|weight| weight.weight)
.unwrap_or(1.0)
}else{
1.0
};
Vertex::from((v,default_weight))
}).collect(),
changed: true,
dvert,
dweight,
}
}
}
impl<'a> From<&'a rinblender::BlenderObject> for Ty{
fn from(ty: &'a rinblender::BlenderObject) -> Ty{
match *ty{
rinblender::BlenderObject::Armature(_) => Ty::Armature,
rinblender::BlenderObject::Model(_) => Ty::Model,
rinblender::BlenderObject::Light(_) => Ty::Light,
rinblender::BlenderObject::Empty(_) => Ty::Empty,
}
}
}
impl<'a> From<&'a rinblender::RigidBody> for RigidBody{
fn from(rigid_body: &'a rinblender::RigidBody) -> RigidBody{
unsafe{ mem::transmute_copy(rigid_body) }
}
}
impl From<rinblender::RotMode> for RotMode{
fn from(rotmode: rinblender::RotMode) -> RotMode{
unsafe{ mem::transmute(rotmode) }
}
}
impl<'a> From<&'a rinblender::Lamp> for shadow::Parameters{
fn from(light: &'a rinblender::Lamp) -> shadow::Parameters{
shadow::Parameters{
map_size: light.shadow_bufsize,
near_clip: light.shadow_near_clip,
far_clip: light.shadow_far_clip,
frustum_size: light.shadow_frustum_size,
bias: light.shadow_bias,
resolution: shadow::Resolution::_32,
}
}
}
impl<'a> From<&'a rinblender::Model> for VertexGroups {
fn from(model: &'a rinblender::Model) -> VertexGroups {
VertexGroups{
index: vec![],
vertex_groups: model.vertex_groups().to_vec(),
default_group: model.vertex_groups().iter()
.position(|group| group == model.default_group().map(|s| s.as_ref()).unwrap_or("")),
}
}
}
impl<'a> From<&'a rinblender::Skeleton> for ArmatureCache{
fn from(skeleton: &'a rinblender::Skeleton) -> ArmatureCache{
let index = skeleton.animated_index().clone();
ArmatureCache{
index,
changed: false,
postmat: one(),
postmat3: one(),
}
}
}
impl RotMode{
pub fn to_rot_order(self) -> rinblender::RotOrder{
match self{
RotMode::EulerXYZ => rinblender::RotOrder::XYZ,
RotMode::EulerXZY => rinblender::RotOrder::XZY,
RotMode::EulerYXZ => rinblender::RotOrder::YXZ,
RotMode::EulerYZX => rinblender::RotOrder::YZX,
RotMode::EulerZXY => rinblender::RotOrder::ZXY,
RotMode::EulerZYX => rinblender::RotOrder::ZYX,
_ => panic!("Not an euler rotation")
}
}
}
#[derive(Component, Debug)]
#[debug_as_string]
pub struct ShapeKey{
pub key: rinblender::TrimeshKey,
pub action: Option<Action>,
}