use crate::mesh_frame::MeshCoordinateSpace;
use crate::types::mesh::MeshData;
pub(super) use crate::mesh_frame::rotation_is_identity;
#[inline]
pub(crate) fn site_local_rotation_invalidates_captured_transforms(
site_local_rotation: Option<&Vec<f64>>,
) -> bool {
site_local_rotation.is_some_and(|m| !rotation_is_identity(m))
}
pub fn native_to_baked(
mesh_coordinate_space: MeshCoordinateSpace,
site_transform: Option<&[f64]>,
origin_shift: [f64; 3],
) -> [f64; 16] {
let rot = site_transform
.filter(|_| mesh_coordinate_space == MeshCoordinateSpace::SiteLocal)
.filter(|m| m.len() >= 16 && !rotation_is_identity(m))
.map(|m| [m[0], m[1], m[2], m[4], m[5], m[6], m[8], m[9], m[10]])
.unwrap_or([1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]);
let t = [-origin_shift[0], -origin_shift[1], -origin_shift[2]];
#[rustfmt::skip]
let m = [
rot[0], rot[1], rot[2], rot[0] * t[0] + rot[1] * t[1] + rot[2] * t[2],
rot[3], rot[4], rot[5], rot[3] * t[0] + rot[4] * t[1] + rot[5] * t[2],
rot[6], rot[7], rot[8], rot[6] * t[0] + rot[7] * t[1] + rot[8] * t[2],
0.0, 0.0, 0.0, 1.0,
];
m
}
fn apply_inverse_rotation_in_place(values: &mut [f32], column_major_matrix: &[f64]) {
if values.len() < 3 || column_major_matrix.len() < 16 {
return;
}
if rotation_is_identity(column_major_matrix) {
return;
}
let r00 = column_major_matrix[0];
let r10 = column_major_matrix[1];
let r20 = column_major_matrix[2];
let r01 = column_major_matrix[4];
let r11 = column_major_matrix[5];
let r21 = column_major_matrix[6];
let r02 = column_major_matrix[8];
let r12 = column_major_matrix[9];
let r22 = column_major_matrix[10];
for chunk in values.chunks_exact_mut(3) {
let x = chunk[0] as f64;
let y = chunk[1] as f64;
let z = chunk[2] as f64;
chunk[0] = (r00 * x + r10 * y + r20 * z) as f32;
chunk[1] = (r01 * x + r11 * y + r21 * z) as f32;
chunk[2] = (r02 * x + r12 * y + r22 * z) as f32;
}
}
pub fn convert_mesh_to_site_local(mesh: &mut MeshData, site_transform: Option<&Vec<f64>>) {
let Some(site_transform) = site_transform else {
return;
};
apply_inverse_rotation_in_place(&mut mesh.positions, site_transform);
apply_inverse_rotation_in_place(&mut mesh.normals, site_transform);
apply_inverse_rotation_point_f64(&mut mesh.origin, site_transform);
}
fn apply_inverse_rotation_point_f64(p: &mut [f64; 3], column_major_matrix: &[f64]) {
if column_major_matrix.len() < 16
|| rotation_is_identity(column_major_matrix)
|| (p[0] == 0.0 && p[1] == 0.0 && p[2] == 0.0)
{
return;
}
let (r00, r10, r20) = (
column_major_matrix[0],
column_major_matrix[1],
column_major_matrix[2],
);
let (r01, r11, r21) = (
column_major_matrix[4],
column_major_matrix[5],
column_major_matrix[6],
);
let (r02, r12, r22) = (
column_major_matrix[8],
column_major_matrix[9],
column_major_matrix[10],
);
let (x, y, z) = (p[0], p[1], p[2]);
p[0] = r00 * x + r10 * y + r20 * z;
p[1] = r01 * x + r11 * y + r21 * z;
p[2] = r02 * x + r12 * y + r22 * z;
}
#[cfg(test)]
#[path = "site_local_tests.rs"]
mod tests;