use crate::mesh::Mesh;
use nalgebra::{Point3, Vector3};
#[inline]
pub fn calculate_normals(mesh: &mut Mesh) {
let vertex_count = mesh.vertex_count();
if vertex_count == 0 {
return;
}
let positions_len = mesh.positions.len();
let mut normals = vec![Vector3::zeros(); vertex_count];
for i in (0..mesh.indices.len()).step_by(3) {
if i + 2 >= mesh.indices.len() {
break;
}
let i0 = mesh.indices[i] as usize;
let i1 = mesh.indices[i + 1] as usize;
let i2 = mesh.indices[i + 2] as usize;
if i0 >= vertex_count || i1 >= vertex_count || i2 >= vertex_count {
continue;
}
if i0 * 3 + 2 >= positions_len || i1 * 3 + 2 >= positions_len || i2 * 3 + 2 >= positions_len
{
continue;
}
let v0 = Point3::new(
mesh.positions[i0 * 3] as f64,
mesh.positions[i0 * 3 + 1] as f64,
mesh.positions[i0 * 3 + 2] as f64,
);
let v1 = Point3::new(
mesh.positions[i1 * 3] as f64,
mesh.positions[i1 * 3 + 1] as f64,
mesh.positions[i1 * 3 + 2] as f64,
);
let v2 = Point3::new(
mesh.positions[i2 * 3] as f64,
mesh.positions[i2 * 3 + 1] as f64,
mesh.positions[i2 * 3 + 2] as f64,
);
let edge1 = v1 - v0;
let edge2 = v2 - v0;
let normal = edge1.cross(&edge2);
normals[i0] += normal;
normals[i1] += normal;
normals[i2] += normal;
}
mesh.normals.clear();
mesh.normals.reserve(vertex_count * 3);
for normal in normals {
let normalized = normal
.try_normalize(1e-6)
.unwrap_or_else(|| Vector3::new(0.0, 0.0, 1.0));
mesh.normals.push(normalized.x as f32);
mesh.normals.push(normalized.y as f32);
mesh.normals.push(normalized.z as f32);
}
}