fix normals

This commit is contained in:
numzero 2026-10-18 00:44:42 +03:00
parent 49cfc215a4
commit 5c6ef7c758
2 changed files with 71 additions and 62 deletions

View File

@ -7,20 +7,28 @@ use crate::{
render::mesh::{CpuMeshIndexed, Vertex}, render::mesh::{CpuMeshIndexed, Vertex},
}; };
pub struct CrownGear { #[derive(Debug, Clone, Copy)]
pub struct CrownGearDesc {
pub profile: Profile, pub profile: Profile,
pub pitch_radius: f32, pub pitch_radius: f32,
}
#[derive(Debug, Clone, Copy)]
pub struct CrownGearVisual {
pub inner_radius: f32, pub inner_radius: f32,
pub outer_radius: f32, pub outer_radius: f32,
pub base_thickness: f32, pub base_thickness: f32,
} }
impl CrownGear { pub fn make_mesh(
pub fn make_mesh(&self, sides: usize, color: Vec3) -> CpuMeshIndexed { desc: &CrownGearDesc,
let teeth = 2.0 * self.pitch_radius; visual: &CrownGearVisual,
let inner_scale = self.inner_radius / self.pitch_radius; sides: usize,
let outer_scale = self.outer_radius / self.pitch_radius; color: Vec3,
) -> CpuMeshIndexed {
let teeth = 2.0 * desc.pitch_radius;
let inner_scale = visual.inner_radius / desc.pitch_radius;
let outer_scale = visual.outer_radius / desc.pitch_radius;
let mut mesh = CpuMeshIndexed::new(); let mut mesh = CpuMeshIndexed::new();
mesh.vertices.reserve_exact(8 * sides); mesh.vertices.reserve_exact(8 * sides);
@ -30,15 +38,14 @@ impl CrownGear {
let rot = Mat3A::from_rotation_z(2.0 * PI * t); let rot = Mat3A::from_rotation_z(2.0 * PI * t);
let tooth = t * teeth; let tooth = t * teeth;
let y = self.profile.y_from_tooth(tooth); let y = desc.profile.y_from_tooth(tooth);
let n_top = { let n_top = {
let eps = 1e-3; let eps = 1e-3;
let dy_dt = teeth let dy_dt = teeth
* (self.profile.y_from_tooth(tooth + eps) * (desc.profile.y_from_tooth(tooth + eps) - desc.profile.y_from_tooth(tooth - eps))
- self.profile.y_from_tooth(tooth - eps))
/ (2.0 * eps); / (2.0 * eps);
vec3(-2.0 * PI * y, -dy_dt, 2.0 * PI * self.pitch_radius) vec3(-2.0 * PI * y, -dy_dt, 2.0 * PI * desc.pitch_radius)
}; };
let vertex = |x, z, n| Vertex { let vertex = |x, z, n| Vertex {
@ -48,17 +55,17 @@ impl CrownGear {
}; };
mesh.vertices.extend([ mesh.vertices.extend([
// top // top
vertex(self.outer_radius, outer_scale * y, n_top), vertex(visual.outer_radius, outer_scale * y, n_top),
vertex(self.inner_radius, inner_scale * y, n_top), vertex(visual.inner_radius, inner_scale * y, n_top),
// bottom // bottom
vertex(self.inner_radius, -self.base_thickness, -Vec3::Z), vertex(visual.inner_radius, -visual.base_thickness, -Vec3::Z),
vertex(self.outer_radius, -self.base_thickness, -Vec3::Z), vertex(visual.outer_radius, -visual.base_thickness, -Vec3::Z),
// inner // inner
vertex(self.inner_radius, inner_scale * y, -Vec3::X), vertex(visual.inner_radius, inner_scale * y, -Vec3::X),
vertex(self.inner_radius, -self.base_thickness, -Vec3::X), vertex(visual.inner_radius, -visual.base_thickness, -Vec3::X),
// outer // outer
vertex(self.outer_radius, -self.base_thickness, Vec3::X), vertex(visual.outer_radius, -visual.base_thickness, Vec3::X),
vertex(self.outer_radius, outer_scale * y, Vec3::X), vertex(visual.outer_radius, outer_scale * y, Vec3::X),
]); ]);
let base1 = 8 * k; let base1 = 8 * k;
@ -66,14 +73,11 @@ impl CrownGear {
for j in 0..4 { for j in 0..4 {
let j1 = 2 * j; let j1 = 2 * j;
let j2 = 2 * j + 1; let j2 = 2 * j + 1;
mesh.faces.push( mesh.faces
[base1 + j1, base2 + j1, base1 + j2].map(|index| index.try_into().unwrap()), .push([base1 + j1, base2 + j1, base1 + j2].map(|index| index.try_into().unwrap()));
); mesh.faces
mesh.faces.push( .push([base2 + j2, base1 + j2, base2 + j1].map(|index| index.try_into().unwrap()));
[base2 + j2, base1 + j2, base2 + j1].map(|index| index.try_into().unwrap()),
);
} }
} }
mesh mesh
} }
}

View File

@ -80,14 +80,19 @@ impl Core {
let depth = Self::create_depth_buffer(&device, pixel_size); let depth = Self::create_depth_buffer(&device, pixel_size);
let mesh_pipeline = render::mesh::Pipeline::new(&device); let mesh_pipeline = render::mesh::Pipeline::new(&device);
let crown_gear_mesh = crown_gear::CrownGear { let crown_gear_mesh = crown_gear::make_mesh(
&crown_gear::CrownGearDesc {
profile: Default::default(), profile: Default::default(),
pitch_radius: 24.0, pitch_radius: 24.0,
},
&crown_gear::CrownGearVisual {
inner_radius: 16.0, inner_radius: 16.0,
outer_radius: 30.0, outer_radius: 30.0,
base_thickness: 2.0, base_thickness: 2.0,
} },
.make_mesh(600, vec3(0.5, 0.5, 0.5)); 600,
vec3(0.5, 0.5, 0.5),
);
let mesh_gray = render::mesh::GpuMeshIndexed::new(&device, &crown_gear_mesh); let mesh_gray = render::mesh::GpuMeshIndexed::new(&device, &crown_gear_mesh);
Self::configure_surface(&surface, &device, pixel_size); Self::configure_surface(&surface, &device, pixel_size);