|
|
|
@ -6,7 +6,6 @@ use glam::{Mat4, Quat, Vec3, Vec3A, Vec4};
|
|
|
|
|
use smol_str::SmolStr; |
|
|
|
|
use std::{ |
|
|
|
|
collections::HashMap, |
|
|
|
|
convert::TryInto, |
|
|
|
|
io::{self, Read, Seek, SeekFrom}, |
|
|
|
|
ops::Range, |
|
|
|
|
str::Utf8Error, |
|
|
|
@ -22,10 +21,16 @@ pub enum Err {
|
|
|
|
|
NumPoses, |
|
|
|
|
#[error("Bad text offset")] |
|
|
|
|
TextOffset, |
|
|
|
|
#[error("Unknown vertex array type")] |
|
|
|
|
UnknownType, |
|
|
|
|
#[error(transparent)] |
|
|
|
|
Utf8(#[from] Utf8Error), |
|
|
|
|
#[error("Bad parent joint")] |
|
|
|
|
Parent, |
|
|
|
|
#[error("Bad frame count")] |
|
|
|
|
FrameCount, |
|
|
|
|
#[error("Unknown vertex array type")] |
|
|
|
|
VaType, |
|
|
|
|
#[error("Unsupported vertex array format")] |
|
|
|
|
VaFormat, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct VertexZipper { |
|
|
|
@ -33,6 +38,7 @@ struct VertexZipper {
|
|
|
|
|
pos_v: std::vec::IntoIter<Vec3A>, |
|
|
|
|
tex_v: std::vec::IntoIter<Vec3A>, |
|
|
|
|
nrm_v: std::vec::IntoIter<Vec3A>, |
|
|
|
|
tan_v: std::vec::IntoIter<Vec4>, |
|
|
|
|
idx_v: std::vec::IntoIter<Vec4>, |
|
|
|
|
wgt_v: std::vec::IntoIter<Vec4>, |
|
|
|
|
clr_v: std::vec::IntoIter<Vec4>, |
|
|
|
@ -45,16 +51,9 @@ pub struct Mesh {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub struct Joint { |
|
|
|
|
//nam: SmolStr,
|
|
|
|
|
par: Option<usize>, |
|
|
|
|
nam: SmolStr, |
|
|
|
|
mat: Mat4, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub struct Pose { |
|
|
|
|
par: Option<usize>, |
|
|
|
|
msk: u32, |
|
|
|
|
ofs: [f32; 10], |
|
|
|
|
scl: [f32; 10], |
|
|
|
|
inv: Mat4, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Data to be uploaded to the GPU. Separate from Model so that it may
|
|
|
|
@ -68,10 +67,8 @@ pub struct ModelData {
|
|
|
|
|
/// the GPU.
|
|
|
|
|
pub struct Model { |
|
|
|
|
meshes: HashMap<SmolStr, Mesh>, |
|
|
|
|
num_frmc: usize, |
|
|
|
|
frames: Vec<u16>, |
|
|
|
|
joints: Vec<Joint>, |
|
|
|
|
poses: Vec<Pose>, |
|
|
|
|
frames: Vec<Vec<Mat4>>, |
|
|
|
|
num_frms: usize, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl Iterator for VertexZipper { |
|
|
|
@ -82,6 +79,7 @@ impl Iterator for VertexZipper {
|
|
|
|
|
Option<Vec4>, |
|
|
|
|
Option<Vec4>, |
|
|
|
|
Option<Vec4>, |
|
|
|
|
Option<Vec4>, |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> { |
|
|
|
@ -89,16 +87,74 @@ impl Iterator for VertexZipper {
|
|
|
|
|
self.pos_v.next(), |
|
|
|
|
self.tex_v.next(), |
|
|
|
|
self.nrm_v.next(), |
|
|
|
|
self.tan_v.next(), |
|
|
|
|
self.idx_v.next(), |
|
|
|
|
self.wgt_v.next(), |
|
|
|
|
self.clr_v.next(), |
|
|
|
|
) { |
|
|
|
|
| (None, None, None, None, None, None) => None, |
|
|
|
|
| (None, None, None, None, None, None, None) => None, |
|
|
|
|
| tuple => Some(tuple), |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const FMT_I8: u32 = 0; |
|
|
|
|
const FMT_U8: u32 = 1; |
|
|
|
|
const FMT_I16: u32 = 2; |
|
|
|
|
const FMT_U16: u32 = 3; |
|
|
|
|
const FMT_I32: u32 = 4; |
|
|
|
|
const FMT_U32: u32 = 5; |
|
|
|
|
const FMT_F32: u32 = 7; |
|
|
|
|
const FMT_F64: u32 = 8; |
|
|
|
|
|
|
|
|
|
fn fmt_check(fm: u32) -> Result<(), Err> { |
|
|
|
|
match fm { |
|
|
|
|
FMT_I8 | FMT_U8 | |
|
|
|
|
FMT_I16 | FMT_U16 | |
|
|
|
|
FMT_I32 | FMT_U32 | FMT_F32 | |
|
|
|
|
FMT_F64 => Ok(()), |
|
|
|
|
_ => Err(Err::VaFormat), |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn fmt_size(fm: u32) -> usize { |
|
|
|
|
match fm { |
|
|
|
|
FMT_I8 | FMT_U8 => 1, |
|
|
|
|
FMT_I16 | FMT_U16 => 2, |
|
|
|
|
FMT_I32 | FMT_U32 | FMT_F32 => 4, |
|
|
|
|
FMT_F64 => 8, |
|
|
|
|
_ => unsafe { std::hint::unreachable_unchecked() }, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn fmt_read_abs(fm: u32, vec: &[u8], pos: usize) -> f32 { |
|
|
|
|
match fm { |
|
|
|
|
FMT_I8 => f32::from(vec[pos] as i8), |
|
|
|
|
FMT_U8 => f32::from(vec[pos]), |
|
|
|
|
FMT_I16 => f32::from(read::i16le_16(vec, pos)), |
|
|
|
|
FMT_U16 => f32::from(read::u16le_16(vec, pos)), |
|
|
|
|
FMT_I32 => read::i32le_32(vec, pos) as f32, |
|
|
|
|
FMT_U32 => read::u32le_32(vec, pos) as f32, |
|
|
|
|
FMT_F32 => read::f32le_32(vec, pos), |
|
|
|
|
FMT_F64 => read::f64le_64(vec, pos) as f32, |
|
|
|
|
_ => unsafe { std::hint::unreachable_unchecked() }, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn fmt_read_nrm(fm: u32, vec: &[u8], pos: usize) -> f32 { |
|
|
|
|
match fm { |
|
|
|
|
FMT_I8 => f32::abs(f32::from(vec[pos] as i8) / 128.0), |
|
|
|
|
FMT_U8 => f32::from(vec[pos]) / 255.0, |
|
|
|
|
FMT_I16 => f32::abs(f32::from(read::i16le_16(vec, pos)) / 32768.0), |
|
|
|
|
FMT_U16 => f32::from(read::u16le_16(vec, pos)) / 65535.0, |
|
|
|
|
FMT_I32 => (read::i32le_32(vec, pos) as f64 / 2147483648.0) as f32, |
|
|
|
|
FMT_U32 => (read::u32le_32(vec, pos) as f64 / 4294967295.0) as f32, |
|
|
|
|
FMT_F32 => f32::clamp(read::f32le_32(vec, pos), 0.0, 1.0), |
|
|
|
|
FMT_F64 => f32::clamp(read::f64le_64(vec, pos) as f32, 0.0, 1.0), |
|
|
|
|
_ => unsafe { std::hint::unreachable_unchecked() }, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl Mesh { |
|
|
|
|
pub fn get_mat(&self) -> &str { |
|
|
|
|
&self.mat |
|
|
|
@ -159,12 +215,12 @@ impl Model {
|
|
|
|
|
let ofs_join = read::u32le_64(&head, 72); |
|
|
|
|
let num_pose = read::u32le_sz(&head, 76); |
|
|
|
|
let ofs_pose = read::u32le_64(&head, 80); |
|
|
|
|
//let num_anim = read::u32le_sz(&head, 84);
|
|
|
|
|
//let ofs_anim = read::u32le_64(&head, 88);
|
|
|
|
|
let num_anim = read::u32le_sz(&head, 84); |
|
|
|
|
let ofs_anim = read::u32le_64(&head, 88); |
|
|
|
|
let num_frms = read::u32le_sz(&head, 92); |
|
|
|
|
let num_frmc = read::u32le_sz(&head, 96); |
|
|
|
|
let ofs_frms = read::u32le_64(&head, 100); |
|
|
|
|
//let ofs_bnds = read::u32le_64(&head, 104);
|
|
|
|
|
let ofs_bnds = read::u32le_64(&head, 104); |
|
|
|
|
|
|
|
|
|
if num_join != 0 && num_pose != 0 && num_pose != num_join { |
|
|
|
|
return Err(Err::NumPoses); |
|
|
|
@ -174,6 +230,7 @@ impl Model {
|
|
|
|
|
let mut pos_v = Vec::with_capacity(num_vert); |
|
|
|
|
let mut tex_v = Vec::with_capacity(num_vert); |
|
|
|
|
let mut nrm_v = Vec::with_capacity(num_vert); |
|
|
|
|
let mut tan_v = Vec::with_capacity(num_vert); |
|
|
|
|
let mut idx_v = Vec::with_capacity(num_vert); |
|
|
|
|
let mut wgt_v = Vec::with_capacity(num_vert); |
|
|
|
|
let mut clr_v = Vec::with_capacity(num_vert); |
|
|
|
@ -182,65 +239,72 @@ impl Model {
|
|
|
|
|
|
|
|
|
|
for array_def in read::hunk(rd, num_vinf * 20)?.chunks(20) { |
|
|
|
|
let ty = read::u32le_32(array_def, 0); |
|
|
|
|
let fl = read::u32le_32(array_def, 4); |
|
|
|
|
let fm = read::u32le_32(array_def, 8); |
|
|
|
|
let sz = read::u32le_32(array_def, 12); |
|
|
|
|
let of = read::u32le_64(array_def, 16); |
|
|
|
|
|
|
|
|
|
fmt_check(fm)?; |
|
|
|
|
|
|
|
|
|
rd.seek(SeekFrom::Start(of))?; |
|
|
|
|
|
|
|
|
|
match ty { |
|
|
|
|
| 0 => { |
|
|
|
|
for pos in read::hunk(rd, 4 * 3 * num_vert)?.chunks(4 * 3) { |
|
|
|
|
let x = read::f32le_32(pos, 0); |
|
|
|
|
let y = read::f32le_32(pos, 4); |
|
|
|
|
let z = read::f32le_32(pos, 8); |
|
|
|
|
pos_v.push(Vec3A::new(x, y, z)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
| 1 => { |
|
|
|
|
for tex in read::hunk(rd, 4 * 2 * num_vert)?.chunks(4 * 2) { |
|
|
|
|
let u = read::f32le_32(tex, 0); |
|
|
|
|
let v = read::f32le_32(tex, 4); |
|
|
|
|
tex_v.push(Vec3A::new(u, v, 0.0)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
| 2 => { |
|
|
|
|
for nrm in read::hunk(rd, 4 * 3 * num_vert)?.chunks(4 * 3) { |
|
|
|
|
let x = read::f32le_32(nrm, 0); |
|
|
|
|
let y = read::f32le_32(nrm, 4); |
|
|
|
|
let z = read::f32le_32(nrm, 8); |
|
|
|
|
nrm_v.push(Vec3A::new(x, y, z)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
| 3 => { |
|
|
|
|
// ignore tangents for now
|
|
|
|
|
} |
|
|
|
|
| 4 => { |
|
|
|
|
for idx in read::hunk(rd, 4 * num_vert)?.chunks(4) { |
|
|
|
|
let idx0 = f32::from(idx[0]); |
|
|
|
|
let idx1 = f32::from(idx[1]); |
|
|
|
|
let idx2 = f32::from(idx[2]); |
|
|
|
|
let idx3 = f32::from(idx[3]); |
|
|
|
|
idx_v.push(Vec4::new(idx0, idx1, idx2, idx3)); |
|
|
|
|
let obj_size = fmt_size(fm); |
|
|
|
|
let obj_amnt = sz as usize; |
|
|
|
|
let obj_blks = obj_size * obj_amnt; |
|
|
|
|
|
|
|
|
|
let hunk = read::hunk(rd, obj_blks * num_vert)?; |
|
|
|
|
|
|
|
|
|
let v2 = |v: &mut Vec<Vec3A>, rd: fn(u32, &[u8], usize) -> f32| { |
|
|
|
|
if obj_amnt != 2 { |
|
|
|
|
Err(Err::VaFormat) |
|
|
|
|
} else { |
|
|
|
|
for vec in hunk.chunks(obj_blks) { |
|
|
|
|
let x = rd(fm, vec, obj_size * 0); |
|
|
|
|
let y = rd(fm, vec, obj_size * 1); |
|
|
|
|
v.push(Vec3A::new(x, y, 0.0)); |
|
|
|
|
} |
|
|
|
|
Ok(()) |
|
|
|
|
} |
|
|
|
|
| 5 => { |
|
|
|
|
for wgt in read::hunk(rd, 4 * num_vert)?.chunks(4) { |
|
|
|
|
let wgt0 = f32::from(wgt[0]) / 255.0; |
|
|
|
|
let wgt1 = f32::from(wgt[1]) / 255.0; |
|
|
|
|
let wgt2 = f32::from(wgt[2]) / 255.0; |
|
|
|
|
let wgt3 = f32::from(wgt[3]) / 255.0; |
|
|
|
|
wgt_v.push(Vec4::new(wgt0, wgt1, wgt2, wgt3)); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
let v3 = |v: &mut Vec<Vec3A>, rd: fn(u32, &[u8], usize) -> f32| { |
|
|
|
|
if obj_amnt != 3 { |
|
|
|
|
Err(Err::VaFormat) |
|
|
|
|
} else { |
|
|
|
|
for vec in hunk.chunks(obj_blks) { |
|
|
|
|
let x = rd(fm, vec, obj_size * 0); |
|
|
|
|
let y = rd(fm, vec, obj_size * 1); |
|
|
|
|
let z = rd(fm, vec, obj_size * 2); |
|
|
|
|
v.push(Vec3A::new(x, y, z)); |
|
|
|
|
} |
|
|
|
|
Ok(()) |
|
|
|
|
} |
|
|
|
|
| 6 => { |
|
|
|
|
for clr in read::hunk(rd, 4 * num_vert)?.chunks(4) { |
|
|
|
|
let r = f32::from(clr[0]) / 255.0; |
|
|
|
|
let g = f32::from(clr[1]) / 255.0; |
|
|
|
|
let b = f32::from(clr[2]) / 255.0; |
|
|
|
|
let a = f32::from(clr[3]) / 255.0; |
|
|
|
|
clr_v.push(Vec4::new(r, g, b, a)); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
let v4 = |v: &mut Vec<Vec4>, rd: fn(u32, &[u8], usize) -> f32| { |
|
|
|
|
if obj_amnt != 4 { |
|
|
|
|
Err(Err::VaFormat) |
|
|
|
|
} else { |
|
|
|
|
for vec in hunk.chunks(obj_blks) { |
|
|
|
|
let x = rd(fm, vec, obj_size * 0); |
|
|
|
|
let y = rd(fm, vec, obj_size * 1); |
|
|
|
|
let z = rd(fm, vec, obj_size * 2); |
|
|
|
|
let w = rd(fm, vec, obj_size * 3); |
|
|
|
|
v.push(Vec4::new(x, y, z, w)); |
|
|
|
|
} |
|
|
|
|
Ok(()) |
|
|
|
|
} |
|
|
|
|
| _ => return Err(Err::UnknownType), |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
match ty { |
|
|
|
|
| 0 => v3(&mut pos_v, fmt_read_abs)?, |
|
|
|
|
| 1 => v2(&mut tex_v, fmt_read_abs)?, |
|
|
|
|
| 2 => v3(&mut nrm_v, fmt_read_abs)?, |
|
|
|
|
| 3 => v4(&mut tan_v, fmt_read_abs)?, |
|
|
|
|
| 4 => v4(&mut idx_v, fmt_read_abs)?, |
|
|
|
|
| 5 => v4(&mut wgt_v, fmt_read_nrm)?, |
|
|
|
|
| 6 => v4(&mut clr_v, fmt_read_nrm)?, |
|
|
|
|
| _ => return Err(Err::VaType), |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -249,6 +313,7 @@ impl Model {
|
|
|
|
|
pos_v: pos_v.into_iter(), |
|
|
|
|
tex_v: tex_v.into_iter(), |
|
|
|
|
nrm_v: nrm_v.into_iter(), |
|
|
|
|
tan_v: tan_v.into_iter(), |
|
|
|
|
idx_v: idx_v.into_iter(), |
|
|
|
|
wgt_v: wgt_v.into_iter(), |
|
|
|
|
clr_v: clr_v.into_iter(), |
|
|
|
@ -256,14 +321,15 @@ impl Model {
|
|
|
|
|
|
|
|
|
|
let mut vert_dat = Vec::with_capacity(num_vert); |
|
|
|
|
|
|
|
|
|
for (pos, tex, nrm, idx, wgt, clr) in zipper { |
|
|
|
|
let pos = pos.unwrap_or_else(|| Vec3A::new(0.0, 0.0, 0.0)); |
|
|
|
|
let tex = tex.unwrap_or_else(|| Vec3A::new(0.0, 0.0, 0.0)); |
|
|
|
|
let nrm = nrm.unwrap_or_else(|| Vec3A::new(0.0, 0.0, 0.0)); |
|
|
|
|
let idx = idx.unwrap_or_else(|| Vec4::new(0.0, 0.0, 0.0, 0.0)); |
|
|
|
|
let wgt = wgt.unwrap_or_else(|| Vec4::new(0.0, 0.0, 0.0, 0.0)); |
|
|
|
|
let clr = clr.unwrap_or_else(|| Vec4::new(1.0, 1.0, 1.0, 1.0)); |
|
|
|
|
vert_dat.push(Vertex { pos, tex, nrm, idx, wgt, clr }); |
|
|
|
|
for (pos, tex, nrm, tan, idx, wgt, clr) in zipper { |
|
|
|
|
let pos = pos.unwrap_or_else(|| Vec3A::ZERO); |
|
|
|
|
let tex = tex.unwrap_or_else(|| Vec3A::ZERO); |
|
|
|
|
let nrm = nrm.unwrap_or_else(|| Vec3A::ZERO); |
|
|
|
|
let tan = tan.unwrap_or_else(|| Vec4::ZERO); |
|
|
|
|
let idx = idx.unwrap_or_else(|| Vec4::ZERO); |
|
|
|
|
let wgt = wgt.unwrap_or_else(|| Vec4::ZERO); |
|
|
|
|
let clr = clr.unwrap_or_else(|| Vec4::ONE); |
|
|
|
|
vert_dat.push(Vertex { pos, tex, nrm, tan, idx, wgt, clr }); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// collect index info
|
|
|
|
@ -305,25 +371,32 @@ impl Model {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// collect joint info
|
|
|
|
|
let mut joints = Vec::with_capacity(num_join); |
|
|
|
|
let mut joints: Vec<Joint> = Vec::with_capacity(num_join); |
|
|
|
|
|
|
|
|
|
rd.seek(SeekFrom::Start(ofs_join))?; |
|
|
|
|
|
|
|
|
|
for join in read::hunk(rd, num_join * 4 * 12)?.chunks(4 * 12) { |
|
|
|
|
let trs = &mut [0.0; 10]; |
|
|
|
|
//let nam = read::u32le_sz(join, 0);
|
|
|
|
|
let mut trs = [0.0; 10]; |
|
|
|
|
let nam = read::u32le_sz(join, 0); |
|
|
|
|
let par = read::u32le_sz(join, 4); |
|
|
|
|
let trs = read::array(read::f32le_32, join, trs, 4, 8); |
|
|
|
|
read::array(read::f32le_32, join, &mut trs, 4, 8); |
|
|
|
|
|
|
|
|
|
//let nam = SmolStr::new(from_stab(&stab, nam)?);
|
|
|
|
|
let par = if par & 0x8000_0000 != 0 { None } else { Some(par) }; |
|
|
|
|
let mat = Mat4::from_scale_rotation_translation( |
|
|
|
|
Vec3::new(trs[0], trs[1], trs[2]), |
|
|
|
|
Quat::from_xyzw(trs[3], trs[4], trs[5], trs[6]), |
|
|
|
|
let nam = SmolStr::new(from_stab(&stab, nam)?); |
|
|
|
|
|
|
|
|
|
let mut mat = Mat4::from_scale_rotation_translation( |
|
|
|
|
Vec3::new(trs[7], trs[8], trs[9]), |
|
|
|
|
Quat::from_xyzw(trs[3], trs[4], trs[5], trs[6]).normalize(), |
|
|
|
|
Vec3::new(trs[0], trs[1], trs[2]), |
|
|
|
|
); |
|
|
|
|
let mut inv = mat.inverse(); |
|
|
|
|
|
|
|
|
|
if par & 0x8000_0000 == 0 { |
|
|
|
|
let parent = joints.get(par).ok_or(Err::Parent)?; |
|
|
|
|
mat = parent.mat * mat; |
|
|
|
|
inv = inv * parent.inv; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
joints.push(Joint { /*nam,*/ par, mat }); |
|
|
|
|
joints.push(Joint { nam, mat, inv }); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// collect frames
|
|
|
|
@ -336,77 +409,63 @@ impl Model {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// collect pose info
|
|
|
|
|
let mut poses = Vec::with_capacity(num_pose); |
|
|
|
|
let mut frame = frames.iter(); |
|
|
|
|
let mut frames = Vec::with_capacity(num_pose); |
|
|
|
|
|
|
|
|
|
rd.seek(SeekFrom::Start(ofs_pose))?; |
|
|
|
|
|
|
|
|
|
for pose in read::hunk(rd, num_pose * 4 * 22)?.chunks(4 * 22) { |
|
|
|
|
let ofs = &mut [0.0; 10]; |
|
|
|
|
let scl = &mut [0.0; 10]; |
|
|
|
|
for (pose, pose_n) in |
|
|
|
|
read::hunk(rd, num_pose * 4 * 22)?.chunks(4 * 22).zip(0..num_pose) |
|
|
|
|
{ |
|
|
|
|
let par = read::u32le_sz(pose, 0); |
|
|
|
|
let msk = read::u32le_32(pose, 4); |
|
|
|
|
let ofs = read::array(read::f32le_32, pose, ofs, 4, 8); |
|
|
|
|
let scl = read::array(read::f32le_32, pose, scl, 4, 48); |
|
|
|
|
let par = if par & 0x8000_0000 != 0 { None } else { Some(par) }; |
|
|
|
|
|
|
|
|
|
poses.push(Pose { |
|
|
|
|
par, |
|
|
|
|
msk, |
|
|
|
|
ofs: ofs.try_into().unwrap(), |
|
|
|
|
scl: scl.try_into().unwrap(), |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
let mut ofs = [0.0; 10]; |
|
|
|
|
let mut scl = [0.0; 10]; |
|
|
|
|
read::array(read::f32le_32, pose, &mut ofs, 4, 8); |
|
|
|
|
read::array(read::f32le_32, pose, &mut scl, 4, 48); |
|
|
|
|
|
|
|
|
|
Ok(( |
|
|
|
|
Self { meshes, num_frmc, frames, joints, poses }, |
|
|
|
|
ModelData { vtx: vert_dat, idx: indx_dat }, |
|
|
|
|
)) |
|
|
|
|
} |
|
|
|
|
let mut pose_mats = Vec::with_capacity(num_frms); |
|
|
|
|
|
|
|
|
|
pub fn num_frames(&self) -> usize { |
|
|
|
|
self.frames.len() / self.num_frmc |
|
|
|
|
} |
|
|
|
|
for _frame_num in 0..num_frms { |
|
|
|
|
let mut ofs = ofs; |
|
|
|
|
|
|
|
|
|
pub fn frame(&self, joint: usize, frame: usize) -> Option<Mat4> { |
|
|
|
|
Some(self.joint_mat(joint)? * self.pose_mat(joint, frame)?) |
|
|
|
|
} |
|
|
|
|
for i in 0..10 { |
|
|
|
|
if msk & 1 << i != 0 { |
|
|
|
|
ofs[i] += |
|
|
|
|
f32::from(*frame.next().ok_or(Err::FrameCount)?) * scl[i]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub fn pose_mat(&self, joint: usize, frame: usize) -> Option<Mat4> { |
|
|
|
|
let pose = self.poses.get(joint)?; |
|
|
|
|
let mut mat = Mat4::from_scale_rotation_translation( |
|
|
|
|
Vec3::new(ofs[7], ofs[8], ofs[9]), |
|
|
|
|
Quat::from_xyzw(ofs[3], ofs[4], ofs[5], ofs[6]).normalize(), |
|
|
|
|
Vec3::new(ofs[0], ofs[1], ofs[2]), |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
let mut trs = [0.0; 10]; |
|
|
|
|
let joint = &joints[pose_n]; |
|
|
|
|
|
|
|
|
|
let mut frames = self.frames.iter().skip(frame * self.num_frmc); |
|
|
|
|
if par & 0x8000_0000 == 0 { |
|
|
|
|
let parent = joints.get(par).ok_or(Err::Parent)?; |
|
|
|
|
mat = parent.mat * mat * joint.inv; |
|
|
|
|
} else { |
|
|
|
|
mat = mat * joint.inv; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for i in 0..10 { |
|
|
|
|
if pose.msk & 1 << i != 0 { |
|
|
|
|
let frame = f32::from(*frames.next()?); |
|
|
|
|
trs[i] = frame.mul_add(pose.scl[i], pose.ofs[i]); |
|
|
|
|
pose_mats.push(mat); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let mut mat = Mat4::from_scale_rotation_translation( |
|
|
|
|
Vec3::new(trs[0], trs[1], trs[2]), |
|
|
|
|
Quat::from_xyzw(trs[3], trs[4], trs[5], trs[6]), |
|
|
|
|
Vec3::new(trs[7], trs[8], trs[9]), |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
if let Some(parent) = pose.par { |
|
|
|
|
mat = self.pose_mat(parent, frame)? * mat; |
|
|
|
|
frames.push(pose_mats); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Some(mat) |
|
|
|
|
Ok((Self { meshes, frames, num_frms }, ModelData { vtx: vert_dat, idx: indx_dat })) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn joint_mat(&self, joint: usize) -> Option<Mat4> { |
|
|
|
|
let jnt = self.joints.get(joint)?; |
|
|
|
|
let mut mat = jnt.mat; |
|
|
|
|
|
|
|
|
|
if let Some(parent) = jnt.par { |
|
|
|
|
mat = self.joint_mat(parent)? * mat; |
|
|
|
|
} |
|
|
|
|
pub fn frame(&self, joint: usize, frame: usize) -> Option<Mat4> { |
|
|
|
|
Some(*self.frames.get(joint)?.get(frame)?) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Some(mat) |
|
|
|
|
pub const fn num_frames(&self) -> usize { |
|
|
|
|
self.num_frms |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|