forked from 1b-agent/opencadstudio-upstream
Fix wipeout rotation and block frame width
This commit is contained in:
1 parent
4a7f08f80e
commit
d07e8cf7d4
4 files changed
+61
-8
No files matched your search
@@ -722,14 +722,22 @@ impl PropertyEditable for Wipeout {
|
|||||||
let u = glam::DVec3::new(self.u_vector.x, self.u_vector.y, self.u_vector.z);
|
let u = glam::DVec3::new(self.u_vector.x, self.u_vector.y, self.u_vector.z);
|
||||||
let v = glam::DVec3::new(self.v_vector.x, self.v_vector.y, self.v_vector.z);
|
let v = glam::DVec3::new(self.v_vector.x, self.v_vector.y, self.v_vector.z);
|
||||||
let normal = u.cross(v).normalize_or_zero();
|
let normal = u.cross(v).normalize_or_zero();
|
||||||
if normal.length_squared() <= 1e-18 {
|
if normal.length_squared() <= 1e-18 || normal.z.abs() <= 1e-12 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let current_radians = u.y.atan2(u.x);
|
let target_radians = target_degrees.to_radians();
|
||||||
let rotation = glam::DQuat::from_axis_angle(
|
let horizontal = glam::DVec3::new(target_radians.cos(), target_radians.sin(), 0.0);
|
||||||
normal,
|
let target = (normal.z * horizontal - normal.dot(horizontal) * glam::DVec3::Z)
|
||||||
target_degrees.to_radians() - current_radians,
|
* normal.z.signum();
|
||||||
);
|
let direction = u.normalize_or_zero();
|
||||||
|
let target = target.normalize_or_zero();
|
||||||
|
if direction == glam::DVec3::ZERO || target == glam::DVec3::ZERO {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let angle = normal
|
||||||
|
.dot(direction.cross(target))
|
||||||
|
.atan2(direction.dot(target));
|
||||||
|
let rotation = glam::DQuat::from_axis_angle(normal, angle);
|
||||||
let u = rotation * u;
|
let u = rotation * u;
|
||||||
let v = rotation * v;
|
let v = rotation * v;
|
||||||
self.u_vector = acadrust::types::Vector3::new(u.x, u.y, u.z);
|
self.u_vector = acadrust::types::Vector3::new(u.x, u.y, u.z);
|
||||||
@@ -786,3 +794,33 @@ impl Transformable for Wipeout {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod wipeout_property_tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rotation_reaches_the_requested_angle_for_mirrored_and_tilted_frames() {
|
||||||
|
for (u, v, target) in [
|
||||||
|
([1.0, 0.0, 0.0], [0.0, -1.0, 0.0], 90.0),
|
||||||
|
([1.0, 0.0, 1.0], [0.0, 1.0, 0.0], 45.0),
|
||||||
|
] {
|
||||||
|
let mut wipeout = Wipeout::new();
|
||||||
|
wipeout.u_vector = acadrust::types::Vector3::new(u[0], u[1], u[2]);
|
||||||
|
wipeout.v_vector = acadrust::types::Vector3::new(v[0], v[1], v[2]);
|
||||||
|
let lengths = (wipeout.u_vector.length(), wipeout.v_vector.length());
|
||||||
|
|
||||||
|
wipeout.apply_geom_prop("wo_rotation", &target.to_string());
|
||||||
|
|
||||||
|
let angle = wipeout
|
||||||
|
.u_vector
|
||||||
|
.y
|
||||||
|
.atan2(wipeout.u_vector.x)
|
||||||
|
.to_degrees()
|
||||||
|
.rem_euclid(360.0);
|
||||||
|
assert!((angle - target).abs() < 1e-9, "target={target} actual={angle}");
|
||||||
|
assert!((wipeout.u_vector.length() - lengths.0).abs() < 1e-12);
|
||||||
|
assert!((wipeout.v_vector.length() - lengths.1).abs() < 1e-12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1495,6 +1495,19 @@ mod block_wire_storage_tests {
|
|||||||
assert_eq!(names(&packed), names(&storage));
|
assert_eq!(names(&packed), names(&storage));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn both_block_wire_shaders_honor_fixed_screen_width() {
|
||||||
|
for source in [
|
||||||
|
include_str!("../../shaders/block_wire.wgsl"),
|
||||||
|
include_str!("../../shaders/block_wire_storage.wgsl"),
|
||||||
|
] {
|
||||||
|
assert!(source.contains("if world_hw < 0.0"));
|
||||||
|
assert!(source.contains(
|
||||||
|
"resolve_hw(0.0, wire_const.world_half_width, wire_const.half_width)"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn wire_shader_validates_with_naga() {
|
fn wire_shader_validates_with_naga() {
|
||||||
let source = include_str!("../../shaders/wire.wgsl");
|
let source = include_str!("../../shaders/wire.wgsl");
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ fn resolve_hw(taper_ratio: f32, world_hw: f32, px_hw: f32) -> f32 {
|
|||||||
if world_hw > 0.0 {
|
if world_hw > 0.0 {
|
||||||
return max(world_hw / u.world_per_pixel, 0.5);
|
return max(world_hw / u.world_per_pixel, 0.5);
|
||||||
}
|
}
|
||||||
|
if world_hw < 0.0 { return max(-world_hw, 0.5); }
|
||||||
var display_hw = max(px_hw * u.lineweight_scale, 0.5);
|
var display_hw = max(px_hw * u.lineweight_scale, 0.5);
|
||||||
if u.lineweight_scale < 0.0 {
|
if u.lineweight_scale < 0.0 {
|
||||||
let scale = -u.lineweight_scale;
|
let scale = -u.lineweight_scale;
|
||||||
@@ -185,7 +186,7 @@ fn vs_main(@builtin(vertex_index) vertex_index: u32, in: VertexIn) -> VertexOut
|
|||||||
let perpendicular = vec2<f32>(-direction.y, direction.x);
|
let perpendicular = vec2<f32>(-direction.y, direction.x);
|
||||||
let clip_position = mix(clip_a, clip_b, which_end);
|
let clip_position = mix(clip_a, clip_b, which_end);
|
||||||
|
|
||||||
let half_width = resolve_hw(0.0, 0.0, wire_const.half_width);
|
let half_width = resolve_hw(0.0, wire_const.world_half_width, wire_const.half_width);
|
||||||
let extension = which_end * 2.0 - 1.0;
|
let extension = which_end * 2.0 - 1.0;
|
||||||
let offset_px = perpendicular * half_width * side
|
let offset_px = perpendicular * half_width * side
|
||||||
+ direction * half_width * extension;
|
+ direction * half_width * extension;
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ fn resolve_hw(taper_ratio: f32, world_hw: f32, px_hw: f32) -> f32 {
|
|||||||
if world_hw > 0.0 {
|
if world_hw > 0.0 {
|
||||||
return max(world_hw / u.world_per_pixel, 0.5);
|
return max(world_hw / u.world_per_pixel, 0.5);
|
||||||
}
|
}
|
||||||
|
if world_hw < 0.0 { return max(-world_hw, 0.5); }
|
||||||
var display_hw = max(px_hw * u.lineweight_scale, 0.5);
|
var display_hw = max(px_hw * u.lineweight_scale, 0.5);
|
||||||
if u.lineweight_scale < 0.0 {
|
if u.lineweight_scale < 0.0 {
|
||||||
let scale = -u.lineweight_scale;
|
let scale = -u.lineweight_scale;
|
||||||
@@ -216,7 +217,7 @@ fn vs_main(@builtin(vertex_index) vertex_index: u32, in: VertexIn) -> VertexOut
|
|||||||
let perpendicular = vec2<f32>(-direction.y, direction.x);
|
let perpendicular = vec2<f32>(-direction.y, direction.x);
|
||||||
let clip_position = mix(clip_a, clip_b, which_end);
|
let clip_position = mix(clip_a, clip_b, which_end);
|
||||||
|
|
||||||
let half_width = resolve_hw(0.0, 0.0, wire_const.half_width);
|
let half_width = resolve_hw(0.0, wire_const.world_half_width, wire_const.half_width);
|
||||||
let extension = which_end * 2.0 - 1.0;
|
let extension = which_end * 2.0 - 1.0;
|
||||||
let offset_px = perpendicular * half_width * side
|
let offset_px = perpendicular * half_width * side
|
||||||
+ direction * half_width * extension;
|
+ direction * half_width * extension;
|
||||||
|
|||||||
Reference in new issue
Block a user