use super::collate::{compose_world, mat4_to_row_major_f32, to_post_rtc};
use crate::mesh::{InstanceMeta, Mesh};
use nalgebra::Matrix4;
pub fn compose_instance_world_row_major(meta: &InstanceMeta) -> [f64; 16] {
let m = compose_world(meta);
let mut out = [0.0f64; 16];
for r in 0..4 {
for c in 0..4 {
out[r * 4 + c] = m[(r, c)];
}
}
out
}
pub fn instance_rel_row_major_f32(
m_k: &[f64; 16],
m_ref: &[f64; 16],
rtc: [f64; 3],
) -> Option<[f32; 16]> {
let mk = to_post_rtc(Matrix4::from_row_slice(m_k), rtc);
let mref = to_post_rtc(Matrix4::from_row_slice(m_ref), rtc);
let mref_inv = mref.try_inverse()?;
Some(mat4_to_row_major_f32(&(mk * mref_inv)))
}
pub fn bake_source_at_world(
source: &Mesh,
world_row_major: &[f64; 16],
rtc: [f64; 3],
) -> (Vec<f32>, Vec<f32>, Vec<u32>) {
let m = to_post_rtc(Matrix4::from_row_slice(world_row_major), rtc);
let vcount = source.positions.len() / 3;
let mut positions = Vec::with_capacity(source.positions.len());
for v in 0..vcount {
let p = m * nalgebra::Vector4::new(
source.positions[v * 3] as f64,
source.positions[v * 3 + 1] as f64,
source.positions[v * 3 + 2] as f64,
1.0,
);
positions.push((p.x / p.w) as f32);
positions.push((p.y / p.w) as f32);
positions.push((p.z / p.w) as f32);
}
let linear = m.fixed_view::<3, 3>(0, 0).into_owned();
let nmat = linear
.try_inverse()
.map(|inv| inv.transpose())
.unwrap_or(linear);
let ncount = source.normals.len() / 3;
let mut normals = Vec::with_capacity(source.normals.len());
for v in 0..ncount {
let nv = nmat
* nalgebra::Vector3::new(
source.normals[v * 3] as f64,
source.normals[v * 3 + 1] as f64,
source.normals[v * 3 + 2] as f64,
);
let nv = nv.try_normalize(0.0).unwrap_or(nv);
normals.push(nv.x as f32);
normals.push(nv.y as f32);
normals.push(nv.z as f32);
}
(positions, normals, source.indices.clone())
}