fix normals
This commit is contained in:
parent
49cfc215a4
commit
5c6ef7c758
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
21
src/lib.rs
21
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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user