use std::io::Read;
use anyhow::{Result, bail};
use crate::resource::prp::PlasmaRead;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum KeyType {
Unknown = 0,
Point3 = 1,
BezPoint3 = 2,
Scalar = 3,
BezScalar = 4,
Scale = 5,
BezScale = 6,
Quat = 7,
CompressedQuat32 = 8,
CompressedQuat64 = 9,
MaxKey = 10,
Matrix33 = 11,
Matrix44 = 12,
}
impl KeyType {
pub fn from_u8(v: u8) -> Result<Self> {
match v {
0 => Ok(Self::Unknown),
1 => Ok(Self::Point3),
2 => Ok(Self::BezPoint3),
3 => Ok(Self::Scalar),
4 => Ok(Self::BezScalar),
5 => Ok(Self::Scale),
6 => Ok(Self::BezScale),
7 => Ok(Self::Quat),
8 => Ok(Self::CompressedQuat32),
9 => Ok(Self::CompressedQuat64),
10 => Ok(Self::MaxKey),
11 => Ok(Self::Matrix33),
12 => Ok(Self::Matrix44),
_ => bail!("Unknown key type: {}", v),
}
}
}
#[derive(Debug, Clone)]
pub enum KeyFrame {
Scalar {
frame: u16,
value: f32,
},
BezScalar {
frame: u16,
in_tan: f32,
out_tan: f32,
value: f32,
},
Point3 {
frame: u16,
value: [f32; 3],
},
BezPoint3 {
frame: u16,
in_tan: [f32; 3],
out_tan: [f32; 3],
value: [f32; 3],
},
Quat {
frame: u16,
value: [f32; 4], },
CompressedQuat32 {
frame: u16,
data: u32,
},
CompressedQuat64 {
frame: u16,
data: [u32; 2],
},
Scale {
frame: u16,
scale: [f32; 3],
quat: [f32; 4],
},
BezScale {
frame: u16,
in_tan: [f32; 3],
out_tan: [f32; 3],
scale: [f32; 3],
quat: [f32; 4],
},
Matrix44 {
frame: u16,
value: [f32; 16],
},
}
impl KeyFrame {
pub fn frame(&self) -> u16 {
match self {
KeyFrame::Scalar { frame, .. }
| KeyFrame::BezScalar { frame, .. }
| KeyFrame::Point3 { frame, .. }
| KeyFrame::BezPoint3 { frame, .. }
| KeyFrame::Quat { frame, .. }
| KeyFrame::CompressedQuat32 { frame, .. }
| KeyFrame::CompressedQuat64 { frame, .. }
| KeyFrame::Scale { frame, .. }
| KeyFrame::BezScale { frame, .. }
| KeyFrame::Matrix44 { frame, .. } => *frame,
}
}
}
pub fn read_keys(reader: &mut impl Read, key_type: KeyType, count: u32) -> Result<Vec<KeyFrame>> {
let mut keys = Vec::with_capacity(count as usize);
for _ in 0..count {
let frame = reader.read_u16()?;
let key = match key_type {
KeyType::Scalar => KeyFrame::Scalar {
frame,
value: reader.read_f32()?,
},
KeyType::BezScalar => KeyFrame::BezScalar {
frame,
in_tan: reader.read_f32()?,
out_tan: reader.read_f32()?,
value: reader.read_f32()?,
},
KeyType::Point3 => KeyFrame::Point3 {
frame,
value: [
reader.read_f32()?,
reader.read_f32()?,
reader.read_f32()?,
],
},
KeyType::BezPoint3 => KeyFrame::BezPoint3 {
frame,
in_tan: [
reader.read_f32()?,
reader.read_f32()?,
reader.read_f32()?,
],
out_tan: [
reader.read_f32()?,
reader.read_f32()?,
reader.read_f32()?,
],
value: [
reader.read_f32()?,
reader.read_f32()?,
reader.read_f32()?,
],
},
KeyType::Quat => KeyFrame::Quat {
frame,
value: [
reader.read_f32()?,
reader.read_f32()?,
reader.read_f32()?,
reader.read_f32()?,
],
},
KeyType::CompressedQuat32 => KeyFrame::CompressedQuat32 {
frame,
data: reader.read_u32()?,
},
KeyType::CompressedQuat64 => KeyFrame::CompressedQuat64 {
frame,
data: [reader.read_u32()?, reader.read_u32()?],
},
KeyType::Scale => {
let scale = [
reader.read_f32()?,
reader.read_f32()?,
reader.read_f32()?,
];
let quat = [
reader.read_f32()?,
reader.read_f32()?,
reader.read_f32()?,
reader.read_f32()?,
];
KeyFrame::Scale { frame, scale, quat }
}
KeyType::BezScale => {
let in_tan = [
reader.read_f32()?,
reader.read_f32()?,
reader.read_f32()?,
];
let out_tan = [
reader.read_f32()?,
reader.read_f32()?,
reader.read_f32()?,
];
let scale = [
reader.read_f32()?,
reader.read_f32()?,
reader.read_f32()?,
];
let quat = [
reader.read_f32()?,
reader.read_f32()?,
reader.read_f32()?,
reader.read_f32()?,
];
KeyFrame::BezScale {
frame,
in_tan,
out_tan,
scale,
quat,
}
}
KeyType::Matrix44 => {
let flag = reader.read_u8()?;
let value = if flag == 0 {
[
1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0,
0.0, 1.0,
]
} else {
let mut m = [0f32; 16];
for val in &mut m {
*val = reader.read_f32()?;
}
m
};
KeyFrame::Matrix44 { frame, value }
}
KeyType::MaxKey => {
for _ in 0..15 {
reader.read_f32()?;
}
KeyFrame::Scale {
frame,
scale: [1.0, 1.0, 1.0],
quat: [0.0, 0.0, 0.0, 1.0],
}
}
KeyType::Unknown => {
bail!("Cannot read unknown key type");
}
_ => {
bail!("Unsupported key type: {:?}", key_type);
}
};
keys.push(key);
}
Ok(keys)
}
pub fn decompress_quat32(data: u32) -> [f32; 4] {
let comp = (data >> 30) as usize;
let scale = 0.707107f32 * 2.0 / 1023.0;
let a = ((data >> 20) & 0x3FF) as f32 * scale - 0.707107;
let b = ((data >> 10) & 0x3FF) as f32 * scale - 0.707107;
let c = (data & 0x3FF) as f32 * scale - 0.707107;
let d = (1.0 - a * a - b * b - c * c).max(0.0).sqrt();
match comp {
0 => [d, a, b, c],
1 => [a, d, b, c],
2 => [a, b, d, c],
_ => [a, b, c, d],
}
}
pub fn decompress_quat64(data: [u32; 2]) -> [f32; 4] {
let comp = (data[0] >> 30) as usize;
let scale20 = 0.707107f32 * 2.0 / 1048575.0;
let scale21 = 0.707107f32 * 2.0 / 2097151.0;
let a = ((data[0] >> 10) & 0xFFFFF) as f32 * scale20 - 0.707107;
let b_hi = (data[0] & 0x3FF) as u32;
let b_lo = (data[1] >> 21) as u32;
let b = ((b_hi << 11) | b_lo) as f32 * scale21 - 0.707107;
let c = (data[1] & 0x1FFFFF) as f32 * scale21 - 0.707107;
let d = (1.0 - a * a - b * b - c * c).max(0.0).sqrt();
match comp {
0 => [d, a, b, c],
1 => [a, d, b, c],
2 => [a, b, d, c],
_ => [a, b, c, d],
}
}