fix normals for the gear teeth

This commit is contained in:
numzero 2026-10-17 22:55:45 +03:00
parent 232720a78a
commit 4fad56a7d1

View File

@ -23,7 +23,7 @@ impl CrownGear {
let outer_scale = self.outer_radius / self.pitch_radius; let outer_scale = self.outer_radius / self.pitch_radius;
let mut mesh = CpuMeshIndexed::new(); let mut mesh = CpuMeshIndexed::new();
mesh.vertices.reserve_exact(4 * sides); mesh.vertices.reserve_exact(8 * sides);
mesh.faces.reserve_exact(8 * sides); mesh.faces.reserve_exact(8 * sides);
for k in 0..sides { for k in 0..sides {
let t = k as f32 / sides as f32; let t = k as f32 / sides as f32;
@ -31,24 +31,22 @@ impl CrownGear {
let (s, c) = phi.sin_cos(); let (s, c) = phi.sin_cos();
let tooth = t * teeth; let tooth = t * teeth;
let y = self.profile.y_from_tooth(tooth); let y = self.profile.y_from_tooth(tooth);
mesh.vertices.push(Vertex { let eps = 1e-3;
position: vec3( let dy_dt = teeth
c * self.inner_radius, * (self.profile.y_from_tooth(tooth + eps) - self.profile.y_from_tooth(tooth - eps))
s * self.inner_radius, / (2.0 * eps);
-self.base_thickness,
), let v_radial = vec3(c * self.pitch_radius, s * self.pitch_radius, y);
color, let v_tan = vec3(-2.0 * PI * s, 2.0 * PI * c, dy_dt / self.pitch_radius);
normal: Vec3::ZERO, // FIXME calculate the normal let n_top = v_radial.cross(v_tan).normalize();
});
mesh.vertices.push(Vertex { let n_top = vec3(
position: vec3( s * dy_dt - 2.0 * PI * c * y,
c * self.outer_radius, -c * dy_dt - 2.0 * PI * s * y,
s * self.outer_radius, 2.0 * PI * self.pitch_radius,
-self.base_thickness, );
),
color, // top
normal: Vec3::ZERO, // FIXME calculate the normal
});
mesh.vertices.push(Vertex { mesh.vertices.push(Vertex {
position: vec3( position: vec3(
c * self.outer_radius, c * self.outer_radius,
@ -56,7 +54,7 @@ impl CrownGear {
outer_scale * y, outer_scale * y,
), ),
color, color,
normal: Vec3::ZERO, // FIXME calculate the normal normal: n_top,
}); });
mesh.vertices.push(Vertex { mesh.vertices.push(Vertex {
position: vec3( position: vec3(
@ -65,12 +63,74 @@ impl CrownGear {
inner_scale * y, inner_scale * y,
), ),
color, color,
normal: Vec3::ZERO, // FIXME calculate the normal normal: n_top,
}); });
let base1 = 4 * k;
let base2 = 4 * ((k + 1) % sides); // bottom
for j1 in 0..4 { mesh.vertices.push(Vertex {
let j2 = (j1 + 1) % 4; position: vec3(
c * self.inner_radius,
s * self.inner_radius,
-self.base_thickness,
),
color,
normal: vec3(0.0, 0.0, -1.0),
});
mesh.vertices.push(Vertex {
position: vec3(
c * self.outer_radius,
s * self.outer_radius,
-self.base_thickness,
),
color,
normal: vec3(0.0, 0.0, -1.0),
});
// inner
mesh.vertices.push(Vertex {
position: vec3(
c * self.inner_radius,
s * self.inner_radius,
inner_scale * y,
),
color,
normal: vec3(-c, -s, 0.0),
});
mesh.vertices.push(Vertex {
position: vec3(
c * self.inner_radius,
s * self.inner_radius,
-self.base_thickness,
),
color,
normal: vec3(-c, -s, 0.0),
});
// outer
mesh.vertices.push(Vertex {
position: vec3(
c * self.outer_radius,
s * self.outer_radius,
-self.base_thickness,
),
color,
normal: vec3(c, s, 0.0),
});
mesh.vertices.push(Vertex {
position: vec3(
c * self.outer_radius,
s * self.outer_radius,
outer_scale * y,
),
color,
normal: vec3(c, s, 0.0),
});
let base1 = 8 * k;
let base2 = 8 * ((k + 1) % sides);
for j in 0..4 {
let j1 = 2 * j;
let j2 = 2 * j + 1;
mesh.faces.push( mesh.faces.push(
[base1 + j1, base2 + j1, base1 + j2].map(|index| index.try_into().unwrap()), [base1 + j1, base2 + j1, base1 + j2].map(|index| index.try_into().unwrap()),
); );