show pre-cut gear, as a reference
This commit is contained in:
parent
f3169f6215
commit
4ee791c356
|
|
@ -1,6 +1,6 @@
|
||||||
use std::f32::consts::PI;
|
use std::f32::consts::PI;
|
||||||
|
|
||||||
use glam::{Affine3A, Vec2, Vec3, Vec3Swizzles, vec3};
|
use glam::{Affine3A, Vec2, Vec3, Vec3Swizzles, vec2, vec3};
|
||||||
|
|
||||||
use crate::{crown_gear::CrownGearDesc, profile::Profile, render::mesh::MeshIndexed};
|
use crate::{crown_gear::CrownGearDesc, profile::Profile, render::mesh::MeshIndexed};
|
||||||
|
|
||||||
|
|
@ -30,6 +30,15 @@ impl BevelGearDesc {
|
||||||
pub fn pitch_distance(&self) -> f32 {
|
pub fn pitch_distance(&self) -> f32 {
|
||||||
self.pitch_radius() / self.cone_halfangle.tan()
|
self.pitch_radius() / self.cone_halfangle.tan()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Projects a point, expressed as a distance from the pitch circle (perpendicular to the pitch cone), onto the pitch plane.
|
||||||
|
/// Returns the distance from the pitch circle center to the projection.
|
||||||
|
fn project(&self, add: f32) -> f32 {
|
||||||
|
let dir = Vec2::from_angle(self.cone_halfangle);
|
||||||
|
let pt = vec2(self.pitch_radius(), 0.) + dir * add;
|
||||||
|
let r = pt.x / (1. - pt.y / self.pitch_distance());
|
||||||
|
r
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
@ -40,13 +49,29 @@ pub struct BevelGearShape {
|
||||||
|
|
||||||
impl BevelGearShape {
|
impl BevelGearShape {
|
||||||
pub fn new_blank(desc: &BevelGearDesc, n_points: usize) -> Self {
|
pub fn new_blank(desc: &BevelGearDesc, n_points: usize) -> Self {
|
||||||
let r = 0.5 * desc.teeth as f32 + desc.profile.addendum + 0.1;
|
let r = desc.project(desc.profile.addendum + 0.1);
|
||||||
BevelGearShape {
|
BevelGearShape {
|
||||||
desc: *desc,
|
desc: *desc,
|
||||||
points: vec![r; n_points],
|
points: vec![r; n_points],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new_cut(desc: &BevelGearDesc, n_points: usize) -> Self {
|
||||||
|
let cutter = desc.cutter();
|
||||||
|
let points = (0..n_points)
|
||||||
|
.map(|k| {
|
||||||
|
let t = k as f32 / n_points as f32;
|
||||||
|
let tooth = t * desc.teeth as f32;
|
||||||
|
let cut_depth = cutter.profile.y_from_tooth(-tooth);
|
||||||
|
desc.project(-cut_depth)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
BevelGearShape {
|
||||||
|
desc: *desc,
|
||||||
|
points,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn to_points(&self) -> impl Iterator<Item = Vec2> {
|
pub fn to_points(&self) -> impl Iterator<Item = Vec2> {
|
||||||
let angle = 2.0 * PI / self.points.len() as f32;
|
let angle = 2.0 * PI / self.points.len() as f32;
|
||||||
self.points
|
self.points
|
||||||
|
|
|
||||||
46
src/lib.rs
46
src/lib.rs
|
|
@ -64,10 +64,13 @@ pub struct Core {
|
||||||
depth: wgpu::Texture,
|
depth: wgpu::Texture,
|
||||||
|
|
||||||
mesh_pipeline: render::mesh::Pipeline,
|
mesh_pipeline: render::mesh::Pipeline,
|
||||||
|
mesh_pipeline_translucent: render::mesh::Pipeline,
|
||||||
|
|
||||||
|
mesh_gear_precut: render::mesh::GpuMeshIndexed,
|
||||||
mesh_cutter: render::mesh::GpuMeshIndexed,
|
mesh_cutter: render::mesh::GpuMeshIndexed,
|
||||||
|
|
||||||
params_gear: render::mesh::GpuParams,
|
params_gear: render::mesh::GpuParams,
|
||||||
|
params_gear_precut: render::mesh::GpuParams,
|
||||||
params_cutter: render::mesh::GpuParams,
|
params_cutter: render::mesh::GpuParams,
|
||||||
|
|
||||||
bevel_gear_desc: bevel_gear::BevelGearDesc,
|
bevel_gear_desc: bevel_gear::BevelGearDesc,
|
||||||
|
|
@ -111,6 +114,7 @@ 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 mesh_pipeline_translucent = render::mesh::Pipeline::new_translucent(&device);
|
||||||
|
|
||||||
let bevel_gear_desc = bevel_gear::BevelGearDesc {
|
let bevel_gear_desc = bevel_gear::BevelGearDesc {
|
||||||
profile: Default::default(),
|
profile: Default::default(),
|
||||||
|
|
@ -119,6 +123,18 @@ impl Core {
|
||||||
};
|
};
|
||||||
let bevel_gear_shape =
|
let bevel_gear_shape =
|
||||||
bevel_gear::BevelGearShape::new_blank(&bevel_gear_desc, 16 * args.tooth as usize);
|
bevel_gear::BevelGearShape::new_blank(&bevel_gear_desc, 16 * args.tooth as usize);
|
||||||
|
let bevel_gear_mesh = bevel_gear::make_mesh(
|
||||||
|
&bevel_gear_desc,
|
||||||
|
&bevel_gear::BevelGearVisual {
|
||||||
|
pad_in: 4.,
|
||||||
|
pad_out: 0.,
|
||||||
|
},
|
||||||
|
&bevel_gear::BevelGearShape::new_cut(&bevel_gear_desc, 16 * args.tooth as usize),
|
||||||
|
)
|
||||||
|
.to_mesh()
|
||||||
|
.to_standard_mesh()
|
||||||
|
.into_indexed();
|
||||||
|
let mesh_gear_precut = render::mesh::GpuMeshIndexed::new(&device, &bevel_gear_mesh);
|
||||||
|
|
||||||
let crown_gear_desc = bevel_gear_desc.cutter();
|
let crown_gear_desc = bevel_gear_desc.cutter();
|
||||||
let crown_gear_mesh = crown_gear::make_mesh_simple(
|
let crown_gear_mesh = crown_gear::make_mesh_simple(
|
||||||
|
|
@ -138,6 +154,7 @@ impl Core {
|
||||||
let mesh_cutter = render::mesh::GpuMeshIndexed::new(&device, &crown_gear_mesh);
|
let mesh_cutter = render::mesh::GpuMeshIndexed::new(&device, &crown_gear_mesh);
|
||||||
|
|
||||||
let params_gear = GpuParams::new(&device, &mesh_pipeline);
|
let params_gear = GpuParams::new(&device, &mesh_pipeline);
|
||||||
|
let params_gear_precut = GpuParams::new(&device, &mesh_pipeline_translucent);
|
||||||
let params_cutter = GpuParams::new(&device, &mesh_pipeline);
|
let params_cutter = GpuParams::new(&device, &mesh_pipeline);
|
||||||
|
|
||||||
Self::configure_surface(&surface, &device, pixel_size);
|
Self::configure_surface(&surface, &device, pixel_size);
|
||||||
|
|
@ -148,8 +165,11 @@ impl Core {
|
||||||
surface,
|
surface,
|
||||||
depth,
|
depth,
|
||||||
mesh_pipeline,
|
mesh_pipeline,
|
||||||
|
mesh_pipeline_translucent,
|
||||||
mesh_cutter,
|
mesh_cutter,
|
||||||
|
mesh_gear_precut,
|
||||||
params_gear,
|
params_gear,
|
||||||
|
params_gear_precut,
|
||||||
params_cutter,
|
params_cutter,
|
||||||
bevel_gear_desc,
|
bevel_gear_desc,
|
||||||
bevel_gear_shape,
|
bevel_gear_shape,
|
||||||
|
|
@ -159,13 +179,13 @@ impl Core {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gear_tfm(&self) -> Affine3A {
|
fn gear_tfm(&self) -> Affine3A {
|
||||||
let turns = -self.t / self.bevel_gear_desc.teeth as f32;
|
let turns = 0.5 - self.t / self.bevel_gear_desc.teeth as f32;
|
||||||
Affine3A::from_rotation_translation(Quat::from_rotation_z(2. * PI * turns), Vec3::ZERO)
|
Affine3A::from_rotation_translation(Quat::from_rotation_z(2. * PI * turns), Vec3::ZERO)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cutter_tfm(&self) -> Affine3A {
|
fn cutter_tfm(&self) -> Affine3A {
|
||||||
let skip_teeth = self.crown_gear_desc.pitch_radius.floor();
|
let skip_teeth = self.crown_gear_desc.pitch_radius.floor();
|
||||||
let turns = (self.t.fract_gl() + skip_teeth) / self.crown_gear_desc.teeth();
|
let turns = (self.t.fract_gl() - skip_teeth) / self.crown_gear_desc.teeth();
|
||||||
Affine3A::from_rotation_translation(
|
Affine3A::from_rotation_translation(
|
||||||
Quat::from_rotation_y(FRAC_PI_2 + self.bevel_gear_desc.cone_halfangle)
|
Quat::from_rotation_y(FRAC_PI_2 + self.bevel_gear_desc.cone_halfangle)
|
||||||
* Quat::from_rotation_z(2. * PI * turns),
|
* Quat::from_rotation_z(2. * PI * turns),
|
||||||
|
|
@ -192,14 +212,14 @@ impl Core {
|
||||||
let view = Mat4::from_mat3(camera::rotation(-args.cam_yaw, -args.cam_pitch));
|
let view = Mat4::from_mat3(camera::rotation(-args.cam_yaw, -args.cam_pitch));
|
||||||
let light = vec3(0.7, 0.5, 1.0).normalize();
|
let light = vec3(0.7, 0.5, 1.0).normalize();
|
||||||
|
|
||||||
self.mesh_pipeline.set_params(
|
let scene_params = render::mesh::SceneParams {
|
||||||
&self.queue,
|
|
||||||
render::mesh::SceneParams {
|
|
||||||
projection: proj * view,
|
projection: proj * view,
|
||||||
light,
|
light,
|
||||||
_zero: 0.,
|
_zero: 0.,
|
||||||
},
|
};
|
||||||
);
|
self.mesh_pipeline.set_params(&self.queue, scene_params);
|
||||||
|
self.mesh_pipeline_translucent
|
||||||
|
.set_params(&self.queue, scene_params);
|
||||||
|
|
||||||
self.params_gear.set(
|
self.params_gear.set(
|
||||||
&self.queue,
|
&self.queue,
|
||||||
|
|
@ -208,6 +228,13 @@ impl Core {
|
||||||
color: srgba_to_linear(vec4(0.2, 0.8, 0.1, 1.0)),
|
color: srgba_to_linear(vec4(0.2, 0.8, 0.1, 1.0)),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
self.params_gear_precut.set(
|
||||||
|
&self.queue,
|
||||||
|
render::mesh::ObjectParams {
|
||||||
|
transform: self.gear_tfm().into(),
|
||||||
|
color: 0.3 * srgba_to_linear(vec4(0.1, 0.2, 0.8, 1.0)),
|
||||||
|
},
|
||||||
|
);
|
||||||
self.params_cutter.set(
|
self.params_cutter.set(
|
||||||
&self.queue,
|
&self.queue,
|
||||||
render::mesh::ObjectParams {
|
render::mesh::ObjectParams {
|
||||||
|
|
@ -259,6 +286,11 @@ impl Core {
|
||||||
self.mesh_cutter
|
self.mesh_cutter
|
||||||
.render(&mut pass, &self.mesh_pipeline, &self.params_cutter);
|
.render(&mut pass, &self.mesh_pipeline, &self.params_cutter);
|
||||||
mesh_gear.render(&mut pass, &self.mesh_pipeline, &self.params_gear);
|
mesh_gear.render(&mut pass, &self.mesh_pipeline, &self.params_gear);
|
||||||
|
self.mesh_gear_precut.render(
|
||||||
|
&mut pass,
|
||||||
|
&self.mesh_pipeline_translucent,
|
||||||
|
&self.params_gear_precut,
|
||||||
|
);
|
||||||
drop(pass);
|
drop(pass);
|
||||||
self.queue.submit(std::iter::once(encoder.finish()));
|
self.queue.submit(std::iter::once(encoder.finish()));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,30 @@ impl GpuMeshIndexed {
|
||||||
|
|
||||||
impl Pipeline {
|
impl Pipeline {
|
||||||
pub fn new(device: &wgpu::Device) -> Self {
|
pub fn new(device: &wgpu::Device) -> Self {
|
||||||
|
Self::new_any(
|
||||||
|
device,
|
||||||
|
wgpu::BlendState::REPLACE,
|
||||||
|
wgpu::DepthBiasState::default(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_translucent(device: &wgpu::Device) -> Self {
|
||||||
|
Self::new_any(
|
||||||
|
device,
|
||||||
|
wgpu::BlendState::PREMULTIPLIED_ALPHA_BLENDING,
|
||||||
|
wgpu::DepthBiasState {
|
||||||
|
constant: -2,
|
||||||
|
slope_scale: -1. / 32.,
|
||||||
|
clamp: 0.,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_any(
|
||||||
|
device: &wgpu::Device,
|
||||||
|
blend: wgpu::BlendState,
|
||||||
|
depth_bias: wgpu::DepthBiasState,
|
||||||
|
) -> Self {
|
||||||
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
||||||
label: None,
|
label: None,
|
||||||
source: wgpu::ShaderSource::Wgsl(SHADER.into()),
|
source: wgpu::ShaderSource::Wgsl(SHADER.into()),
|
||||||
|
|
@ -141,7 +165,7 @@ impl Pipeline {
|
||||||
depth_write_enabled: true,
|
depth_write_enabled: true,
|
||||||
depth_compare: wgpu::CompareFunction::LessEqual,
|
depth_compare: wgpu::CompareFunction::LessEqual,
|
||||||
stencil: wgpu::StencilState::default(),
|
stencil: wgpu::StencilState::default(),
|
||||||
bias: wgpu::DepthBiasState::default(),
|
bias: depth_bias,
|
||||||
}),
|
}),
|
||||||
multisample: wgpu::MultisampleState {
|
multisample: wgpu::MultisampleState {
|
||||||
count: 1,
|
count: 1,
|
||||||
|
|
@ -154,7 +178,7 @@ impl Pipeline {
|
||||||
compilation_options: wgpu::PipelineCompilationOptions::default(),
|
compilation_options: wgpu::PipelineCompilationOptions::default(),
|
||||||
targets: &[Some(wgpu::ColorTargetState {
|
targets: &[Some(wgpu::ColorTargetState {
|
||||||
format: crate::render::OUTPUT_FORMAT,
|
format: crate::render::OUTPUT_FORMAT,
|
||||||
blend: Some(wgpu::BlendState::REPLACE),
|
blend: Some(blend),
|
||||||
write_mask: wgpu::ColorWrites::ALL,
|
write_mask: wgpu::ColorWrites::ALL,
|
||||||
})],
|
})],
|
||||||
}),
|
}),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user