unify cutter position calculations
This commit is contained in:
parent
f066a3b913
commit
cf30027976
|
|
@ -1,6 +1,6 @@
|
||||||
use std::f32::consts::{FRAC_PI_2, PI};
|
use std::f32::consts::PI;
|
||||||
|
|
||||||
use glam::{Affine3A, FloatExt, Quat, Vec2, Vec3, Vec3Swizzles, vec3};
|
use glam::{Affine3A, Vec2, Vec3, Vec3Swizzles, vec3};
|
||||||
|
|
||||||
use crate::{crown_gear::CrownGearDesc, profile::Profile, render::mesh::MeshIndexed};
|
use crate::{crown_gear::CrownGearDesc, profile::Profile, render::mesh::MeshIndexed};
|
||||||
|
|
||||||
|
|
@ -55,34 +55,29 @@ impl BevelGearShape {
|
||||||
.map(move |(k, r)| Vec2::from_angle(k as f32 * angle) * r)
|
.map(move |(k, r)| Vec2::from_angle(k as f32 * angle) * r)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cut(&mut self, offset_teeth: f32) {
|
pub fn cut(&mut self, cutter_tfm: Affine3A) {
|
||||||
let cutter = self.desc.cutter();
|
let cutter = self.desc.cutter();
|
||||||
let crown_skip_teeth = cutter.pitch_radius.floor();
|
|
||||||
let crown_turns = (offset_teeth.fract_gl() + crown_skip_teeth) / (2. * cutter.pitch_radius);
|
|
||||||
let cutter_tfm = Affine3A::from_rotation_translation(
|
|
||||||
Quat::from_rotation_y(FRAC_PI_2 + self.desc.cone_halfangle)
|
|
||||||
* Quat::from_rotation_z(2. * PI * crown_turns),
|
|
||||||
vec3(0., 0., self.desc.pitch_distance()),
|
|
||||||
);
|
|
||||||
let z_proj = self.desc.pitch_distance();
|
let z_proj = self.desc.pitch_distance();
|
||||||
let cutting_line = cutter.to_shape(0.375..0.725, 200);
|
let cutting_line = cutter.to_shape(0.375..0.625, 200);
|
||||||
let cutting_line: Vec<_> = cutting_line
|
let cutting_line: Vec<_> = cutting_line
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|pt| {
|
.map(|pt| {
|
||||||
let pt_3d = cutter_tfm.transform_point3(pt);
|
let pt_3d = cutter_tfm.transform_point3(pt);
|
||||||
let pt_2d = -pt_3d.xy() * (z_proj / (z_proj - pt_3d.z));
|
let pt_2d = pt_3d.xy() * (z_proj / (z_proj - pt_3d.z));
|
||||||
pt_2d
|
pt_2d
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let len = self.points.len();
|
let angle = 2.0 * PI / self.points.len() as f32;
|
||||||
for (k, pt) in self.points.iter_mut().enumerate() {
|
for (k, pt) in self.points.iter_mut().enumerate() {
|
||||||
let dir = Vec2::from_angle(
|
let dir = Vec2::from_angle(k as f32 * angle);
|
||||||
2.0 * PI * (k as f32 / len as f32 - offset_teeth / self.desc.teeth as f32),
|
|
||||||
);
|
|
||||||
for line in cutting_line.iter().zip(&cutting_line[1..]) {
|
for line in cutting_line.iter().zip(&cutting_line[1..]) {
|
||||||
if line.0.dot(dir.perp()) >= 0. && line.1.dot(dir.perp()) <= 0. {
|
if line.0.dot(dir) <= 0. || line.1.dot(dir) <= 0. {
|
||||||
*pt = pt.min(f32::min(line.0.length(), line.1.length()));
|
continue;
|
||||||
}
|
}
|
||||||
|
if line.0.dot(dir.perp()) < 0. || line.1.dot(dir.perp()) > 0. {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
*pt = pt.min(f32::min(line.0.length(), line.1.length()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,10 @@ pub struct CrownGearVisual {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CrownGearDesc {
|
impl CrownGearDesc {
|
||||||
|
pub fn teeth(&self) -> f32 {
|
||||||
|
2. * self.pitch_radius
|
||||||
|
}
|
||||||
|
|
||||||
pub fn to_shape(&self, part: Range<f32>, sides: usize) -> Vec<Vec3> {
|
pub fn to_shape(&self, part: Range<f32>, sides: usize) -> Vec<Vec3> {
|
||||||
let teeth = 2.0 * self.pitch_radius;
|
let teeth = 2.0 * self.pitch_radius;
|
||||||
let mut ret = Vec::new();
|
let mut ret = Vec::new();
|
||||||
|
|
|
||||||
37
src/lib.rs
37
src/lib.rs
|
|
@ -3,7 +3,7 @@ use std::{
|
||||||
f32::consts::{FRAC_PI_2, PI},
|
f32::consts::{FRAC_PI_2, PI},
|
||||||
};
|
};
|
||||||
|
|
||||||
use glam::{FloatExt, Mat4, Quat, UVec2, Vec3, Vec4, vec3, vec4};
|
use glam::{Affine3A, FloatExt, Mat4, Quat, UVec2, Vec3, Vec4, vec3, vec4};
|
||||||
|
|
||||||
use crate::render::mesh::GpuParams;
|
use crate::render::mesh::GpuParams;
|
||||||
|
|
||||||
|
|
@ -156,6 +156,21 @@ impl Core {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn gear_tfm(&self) -> Affine3A {
|
||||||
|
let turns = -self.t / self.bevel_gear_desc.teeth as f32;
|
||||||
|
Affine3A::from_rotation_translation(Quat::from_rotation_z(2. * PI * turns), Vec3::ZERO)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cutter_tfm(&self) -> Affine3A {
|
||||||
|
let skip_teeth = self.crown_gear_desc.pitch_radius.floor();
|
||||||
|
let turns = (self.t.fract_gl() + skip_teeth) / self.crown_gear_desc.teeth();
|
||||||
|
Affine3A::from_rotation_translation(
|
||||||
|
Quat::from_rotation_y(FRAC_PI_2 + self.bevel_gear_desc.cone_halfangle)
|
||||||
|
* Quat::from_rotation_z(2. * PI * turns),
|
||||||
|
vec3(0., 0., self.bevel_gear_desc.pitch_distance()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn render(&self, output: &wgpu::Texture, args: &RedrawArgs) {
|
fn render(&self, output: &wgpu::Texture, args: &RedrawArgs) {
|
||||||
let y_frac = {
|
let y_frac = {
|
||||||
let size = output.size();
|
let size = output.size();
|
||||||
|
|
@ -184,30 +199,17 @@ impl Core {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
let turn_teeth = self.t;
|
|
||||||
let bevel_turns = 0.5 - turn_teeth / self.bevel_gear_desc.teeth as f32;
|
|
||||||
let crown_skip_teeth = self.crown_gear_desc.pitch_radius.floor();
|
|
||||||
let crown_turns =
|
|
||||||
(turn_teeth.fract_gl() + crown_skip_teeth) / (2. * self.crown_gear_desc.pitch_radius);
|
|
||||||
|
|
||||||
self.params_gear.set(
|
self.params_gear.set(
|
||||||
&self.queue,
|
&self.queue,
|
||||||
render::mesh::ObjectParams {
|
render::mesh::ObjectParams {
|
||||||
transform: Mat4::from_rotation_translation(
|
transform: self.gear_tfm().into(),
|
||||||
Quat::from_rotation_z(2. * PI * bevel_turns),
|
|
||||||
Vec3::ZERO,
|
|
||||||
),
|
|
||||||
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_cutter.set(
|
self.params_cutter.set(
|
||||||
&self.queue,
|
&self.queue,
|
||||||
render::mesh::ObjectParams {
|
render::mesh::ObjectParams {
|
||||||
transform: Mat4::from_rotation_translation(
|
transform: self.cutter_tfm().into(),
|
||||||
Quat::from_rotation_y(FRAC_PI_2 + self.bevel_gear_desc.cone_halfangle)
|
|
||||||
* Quat::from_rotation_z(2. * PI * crown_turns),
|
|
||||||
vec3(0., 0., self.bevel_gear_desc.pitch_distance()),
|
|
||||||
),
|
|
||||||
color: srgba_to_linear(vec4(0.8, 0.2, 0.1, 1.0)),
|
color: srgba_to_linear(vec4(0.8, 0.2, 0.1, 1.0)),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
@ -302,7 +304,8 @@ impl Core {
|
||||||
///
|
///
|
||||||
/// [`Self::configure`] must be called at least once before this.
|
/// [`Self::configure`] must be called at least once before this.
|
||||||
pub fn redraw(&mut self, args: &RedrawArgs) {
|
pub fn redraw(&mut self, args: &RedrawArgs) {
|
||||||
self.bevel_gear_shape.cut(self.t);
|
self.bevel_gear_shape
|
||||||
|
.cut(self.gear_tfm().inverse() * self.cutter_tfm());
|
||||||
let output = self.surface.get_current_texture().unwrap();
|
let output = self.surface.get_current_texture().unwrap();
|
||||||
self.render(&output.texture, args);
|
self.render(&output.texture, args);
|
||||||
output.present();
|
output.present();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user