enigma-3d 0.2.15

A 3D Rendering Engine with a focus on simplicity and ease of use. Far from feature complete and not recommended for production use.
Documentation
use std::vec::Vec;
use nalgebra::{Matrix4, Quaternion, UnitQuaternion, Vector3};
use serde::{Deserialize, Serialize};
use crate::logging::EnigmaError;
use crate::smart_format;

pub(crate) const MAX_BONES: usize = 128;

#[derive(Clone)]
pub struct Bone {
    pub name: String,
    pub id: usize,
    pub node_index: usize,
    pub parent_id: Option<usize>,
    pub inverse_bind_pose: Matrix4<f32>
}

#[derive(Serialize, Deserialize, Clone)]
pub struct BoneSerializer {
    pub name: String,
    pub id: usize,
    pub node_index: usize,
    pub parent_id: Option<usize>,
    pub inverse_bind_pose: [[f32;4];4]
}

impl Bone {
    pub fn to_serializer(&self) -> BoneSerializer {
        BoneSerializer {
            name: self.name.clone(),
            id: self.id,
            node_index: self.node_index,
            parent_id: self.parent_id,
            inverse_bind_pose: self.inverse_bind_pose.into()
        }
    }

    pub fn from_serializer(serializer: BoneSerializer) -> Self{
        Self {
            name: serializer.name,
            id: serializer.id,
            node_index: serializer.node_index,
            parent_id: serializer.parent_id,
            inverse_bind_pose: Matrix4::from(serializer.inverse_bind_pose)
        }
    }
}

#[derive(Clone)]
pub struct Skeleton {
    pub bones: Vec<Bone>,
    /// World-space transform of the node that is the parent of the root joint(s).
    /// Applied as the base transform for root bones during skinning.
    pub root_transform: Matrix4<f32>,
}
#[derive(Serialize, Deserialize, Clone)]
pub struct SkeletonSerializer {
    pub bones: Vec<BoneSerializer>,
    pub root_transform: [[f32; 4]; 4],
}

impl Skeleton {
    pub fn to_serializer(&self) -> SkeletonSerializer {
        SkeletonSerializer {
            bones: self.bones.iter().map(|x| x.to_serializer()).collect(),
            root_transform: self.root_transform.into(),
        }
    }

    pub fn from_serializer(serializer: SkeletonSerializer) -> Self {
        let mut bones = Vec::new();
        for s in serializer.bones {
            let bone = Bone::from_serializer(s);
            bones.push(bone);
        }
        Self {
            bones,
            root_transform: Matrix4::from(serializer.root_transform),
        }
    }
    pub fn validate(&self) -> Result<(), EnigmaError> {
        for bone in self.bones.iter() {
            if let Some(parent_id) = bone.parent_id {
                if parent_id >= self.bones.len() {
                    return Err(EnigmaError::new(Some(smart_format!("Invalid parent ID {} for bone {} with id {}. There are only {} bones in the skeleton.", parent_id, bone.name, bone.id, self.bones.len()).as_str()), true))
                }
            }
        }
        Ok(())
    }

    pub fn try_fix(&mut self) -> Result<(), EnigmaError> {
        let len = self.bones.len();
        for bone in self.bones.iter_mut() {
            if let Some(parent_id) = bone.parent_id {
                if parent_id >= len {
                    bone.parent_id = None;
                }
            }
        }
        Ok(())
    }
}

#[derive(Serialize, Deserialize, Clone)]
pub enum AnimationTransform {
    Translation([f32; 3]),
    Rotation([f32;4]),
    Scale([f32;3]),
}

#[derive(Clone)]
pub struct AnimationKeyframe{
    pub time: f32,
    pub transform: AnimationTransform,
}

impl AnimationKeyframe {

    pub fn to_serializer(&self) -> AnimationKeyframeSerializer {
        AnimationKeyframeSerializer {
            time: self.time.clone(),
            transform: self.transform.clone()
        }
    }

    pub fn from_serializer(serializer: AnimationKeyframeSerializer) -> Self {
        Self {
            time: serializer.time,
            transform: serializer.transform
        }
    }

    pub fn get_matrix(&self) -> Matrix4<f32> {
        match &self.transform {
            AnimationTransform::Translation(translation) => {
                Matrix4::new_translation(&Vector3::new(translation[0], translation[1], translation[2]))
            },
            AnimationTransform::Rotation(quaternion) => {
                let quat = UnitQuaternion::new_normalize(
                    Quaternion::new(quaternion[3], quaternion[0], quaternion[1], quaternion[2])
                );
                quat.to_homogeneous()
            },
            AnimationTransform::Scale(scale) => {
                Matrix4::new_nonuniform_scaling(&Vector3::new(scale[0], scale[1], scale[2]))
            }
        }
    }
}

#[derive(Serialize, Deserialize, Clone)]
pub struct AnimationKeyframeSerializer {
    pub time: f32,
    pub transform: AnimationTransform,
}

#[derive(Clone)]
pub struct AnimationChannel {
    pub bone_id: usize,
    pub keyframes: Vec<AnimationKeyframe>,
}
#[derive(Serialize, Deserialize, Clone)]
pub struct AnimationState {
    pub name: String,
    pub time: f32,
    pub speed: f32,
    pub looping: bool,
}

impl AnimationChannel {
    pub fn to_serializer(&self) -> AnimationChannelSerializer {
        AnimationChannelSerializer {
            bone_id: self.bone_id.clone(),
            keyframes: self.keyframes.iter().map(|x| x.to_serializer()).collect()
        }
    }

    pub fn from_serializer(serializer: AnimationChannelSerializer) -> Self {
        let mut keyframes = Vec::new();
        for s in serializer.keyframes {
            let keyframe = AnimationKeyframe::from_serializer(s);
            keyframes.push(keyframe);
        }
        Self {
            bone_id: serializer.bone_id,
            keyframes
        }
    }
}

#[derive(Serialize, Deserialize, Clone)]
pub struct AnimationChannelSerializer {
    pub bone_id: usize,
    pub keyframes: Vec<AnimationKeyframeSerializer>,
}

#[derive(Clone)]
pub struct Animation {
    pub name: String,
    pub duration: f32,
    pub channels: Vec<AnimationChannel>,
}

impl Animation {
    pub fn to_serializer(&self) -> AnimationSerializer {
        AnimationSerializer {
            name: self.name.clone(),
            duration: self.duration.clone(),
            channels: self.channels.iter().map(|x| x.to_serializer()).collect()
        }
    }

    pub fn from_serializer(serializer: AnimationSerializer) -> Self {
        let mut channels = Vec::new();
        for s in serializer.channels {
            let channel = AnimationChannel::from_serializer(s);
            channels.push(channel);
        }
        Self {
            name: serializer.name,
            duration: serializer.duration,
            channels
        }
    }
}

#[derive(Serialize, Deserialize, Clone)]
pub struct AnimationSerializer {
    pub name: String,
    pub duration: f32,
    pub channels: Vec<AnimationChannelSerializer>,
}