diff --git a/src/crown_gear.rs b/src/crown_gear.rs index 1cfe93a..364adc1 100644 --- a/src/crown_gear.rs +++ b/src/crown_gear.rs @@ -7,73 +7,77 @@ use crate::{ render::mesh::{CpuMeshIndexed, Vertex}, }; -pub struct CrownGear { +#[derive(Debug, Clone, Copy)] +pub struct CrownGearDesc { pub profile: Profile, pub pitch_radius: f32, +} +#[derive(Debug, Clone, Copy)] +pub struct CrownGearVisual { pub inner_radius: f32, pub outer_radius: f32, pub base_thickness: f32, } -impl CrownGear { - pub fn make_mesh(&self, sides: usize, color: Vec3) -> CpuMeshIndexed { - let teeth = 2.0 * self.pitch_radius; - let inner_scale = self.inner_radius / self.pitch_radius; - let outer_scale = self.outer_radius / self.pitch_radius; +pub fn make_mesh( + desc: &CrownGearDesc, + visual: &CrownGearVisual, + sides: usize, + 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(); - mesh.vertices.reserve_exact(8 * sides); - mesh.faces.reserve_exact(8 * sides); - for k in 0..sides { - let t = k as f32 / sides as f32; - let rot = Mat3A::from_rotation_z(2.0 * PI * t); + let mut mesh = CpuMeshIndexed::new(); + mesh.vertices.reserve_exact(8 * sides); + mesh.faces.reserve_exact(8 * sides); + for k in 0..sides { + let t = k as f32 / sides as f32; + let rot = Mat3A::from_rotation_z(2.0 * PI * t); - let tooth = t * teeth; - let y = self.profile.y_from_tooth(tooth); + let tooth = t * teeth; + let y = desc.profile.y_from_tooth(tooth); - let n_top = { - let eps = 1e-3; - let dy_dt = teeth - * (self.profile.y_from_tooth(tooth + eps) - - self.profile.y_from_tooth(tooth - eps)) - / (2.0 * eps); - vec3(-2.0 * PI * y, -dy_dt, 2.0 * PI * self.pitch_radius) - }; + let n_top = { + let eps = 1e-3; + let dy_dt = teeth + * (desc.profile.y_from_tooth(tooth + eps) - desc.profile.y_from_tooth(tooth - eps)) + / (2.0 * eps); + vec3(-2.0 * PI * y, -dy_dt, 2.0 * PI * desc.pitch_radius) + }; - let vertex = |x, z, n| Vertex { - position: rot * vec3(x, 0.0, z), - color, - normal: n, - }; - mesh.vertices.extend([ - // top - vertex(self.outer_radius, outer_scale * y, n_top), - vertex(self.inner_radius, inner_scale * y, n_top), - // bottom - vertex(self.inner_radius, -self.base_thickness, -Vec3::Z), - vertex(self.outer_radius, -self.base_thickness, -Vec3::Z), - // inner - vertex(self.inner_radius, inner_scale * y, -Vec3::X), - vertex(self.inner_radius, -self.base_thickness, -Vec3::X), - // outer - vertex(self.outer_radius, -self.base_thickness, Vec3::X), - vertex(self.outer_radius, outer_scale * y, Vec3::X), - ]); + let vertex = |x, z, n| Vertex { + position: rot * vec3(x, 0.0, z), + color, + normal: n, + }; + mesh.vertices.extend([ + // top + vertex(visual.outer_radius, outer_scale * y, n_top), + vertex(visual.inner_radius, inner_scale * y, n_top), + // bottom + vertex(visual.inner_radius, -visual.base_thickness, -Vec3::Z), + vertex(visual.outer_radius, -visual.base_thickness, -Vec3::Z), + // inner + vertex(visual.inner_radius, inner_scale * y, -Vec3::X), + vertex(visual.inner_radius, -visual.base_thickness, -Vec3::X), + // outer + vertex(visual.outer_radius, -visual.base_thickness, Vec3::X), + vertex(visual.outer_radius, outer_scale * y, Vec3::X), + ]); - 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( - [base1 + j1, base2 + j1, base1 + j2].map(|index| index.try_into().unwrap()), - ); - mesh.faces.push( - [base2 + j2, base1 + j2, base2 + j1].map(|index| index.try_into().unwrap()), - ); - } + 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([base1 + j1, base2 + j1, base1 + j2].map(|index| index.try_into().unwrap())); + mesh.faces + .push([base2 + j2, base1 + j2, base2 + j1].map(|index| index.try_into().unwrap())); } - mesh } + mesh } diff --git a/src/lib.rs b/src/lib.rs index 100daa0..1eae7df 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -80,14 +80,19 @@ impl Core { let depth = Self::create_depth_buffer(&device, pixel_size); let mesh_pipeline = render::mesh::Pipeline::new(&device); - let crown_gear_mesh = crown_gear::CrownGear { - profile: Default::default(), - pitch_radius: 24.0, - inner_radius: 16.0, - outer_radius: 30.0, - base_thickness: 2.0, - } - .make_mesh(600, vec3(0.5, 0.5, 0.5)); + let crown_gear_mesh = crown_gear::make_mesh( + &crown_gear::CrownGearDesc { + profile: Default::default(), + pitch_radius: 24.0, + }, + &crown_gear::CrownGearVisual { + inner_radius: 16.0, + outer_radius: 30.0, + base_thickness: 2.0, + }, + 600, + vec3(0.5, 0.5, 0.5), + ); let mesh_gray = render::mesh::GpuMeshIndexed::new(&device, &crown_gear_mesh); Self::configure_surface(&surface, &device, pixel_size);