ifc_lite_geometry/csg/
normals.rs1use crate::mesh::Mesh;
6use nalgebra::{Point3, Vector3};
7
8#[inline]
17pub fn calculate_normals(mesh: &mut Mesh) {
18 let vertex_count = mesh.vertex_count();
19 if vertex_count == 0 {
20 return;
21 }
22
23 let positions_len = mesh.positions.len();
24
25 let mut normals = vec![Vector3::zeros(); vertex_count];
27
28 for i in (0..mesh.indices.len()).step_by(3) {
30 if i + 2 >= mesh.indices.len() {
32 break;
33 }
34
35 let i0 = mesh.indices[i] as usize;
36 let i1 = mesh.indices[i + 1] as usize;
37 let i2 = mesh.indices[i + 2] as usize;
38
39 if i0 >= vertex_count || i1 >= vertex_count || i2 >= vertex_count {
41 continue;
42 }
43 if i0 * 3 + 2 >= positions_len || i1 * 3 + 2 >= positions_len || i2 * 3 + 2 >= positions_len
44 {
45 continue;
46 }
47
48 let v0 = Point3::new(
50 mesh.positions[i0 * 3] as f64,
51 mesh.positions[i0 * 3 + 1] as f64,
52 mesh.positions[i0 * 3 + 2] as f64,
53 );
54 let v1 = Point3::new(
55 mesh.positions[i1 * 3] as f64,
56 mesh.positions[i1 * 3 + 1] as f64,
57 mesh.positions[i1 * 3 + 2] as f64,
58 );
59 let v2 = Point3::new(
60 mesh.positions[i2 * 3] as f64,
61 mesh.positions[i2 * 3 + 1] as f64,
62 mesh.positions[i2 * 3 + 2] as f64,
63 );
64
65 let edge1 = v1 - v0;
67 let edge2 = v2 - v0;
68 let normal = edge1.cross(&edge2);
69
70 normals[i0] += normal;
72 normals[i1] += normal;
73 normals[i2] += normal;
74 }
75
76 mesh.normals.clear();
78 mesh.normals.reserve(vertex_count * 3);
79
80 for normal in normals {
81 let normalized = normal
82 .try_normalize(1e-6)
83 .unwrap_or_else(|| Vector3::new(0.0, 0.0, 1.0));
84 mesh.normals.push(normalized.x as f32);
85 mesh.normals.push(normalized.y as f32);
86 mesh.normals.push(normalized.z as f32);
87 }
88}
89