fix normals
This commit is contained in:
parent
49cfc215a4
commit
5c6ef7c758
|
|
@ -7,73 +7,77 @@ 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);
|
||||||
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;
|
||||||
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 * desc.pitch_radius)
|
||||||
vec3(-2.0 * PI * y, -dy_dt, 2.0 * PI * self.pitch_radius)
|
};
|
||||||
};
|
|
||||||
|
|
||||||
let vertex = |x, z, n| Vertex {
|
let vertex = |x, z, n| Vertex {
|
||||||
position: rot * vec3(x, 0.0, z),
|
position: rot * vec3(x, 0.0, z),
|
||||||
color,
|
color,
|
||||||
normal: n,
|
normal: n,
|
||||||
};
|
};
|
||||||
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;
|
||||||
let base2 = 8 * ((k + 1) % sides);
|
let base2 = 8 * ((k + 1) % sides);
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
21
src/lib.rs
21
src/lib.rs
|
|
@ -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(
|
||||||
profile: Default::default(),
|
&crown_gear::CrownGearDesc {
|
||||||
pitch_radius: 24.0,
|
profile: Default::default(),
|
||||||
inner_radius: 16.0,
|
pitch_radius: 24.0,
|
||||||
outer_radius: 30.0,
|
},
|
||||||
base_thickness: 2.0,
|
&crown_gear::CrownGearVisual {
|
||||||
}
|
inner_radius: 16.0,
|
||||||
.make_mesh(600, vec3(0.5, 0.5, 0.5));
|
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);
|
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);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user