Refined rotator gizmo

This commit is contained in:
Danny McGee
2023-10-11 16:07:35 -04:00
parent ac6773b117
commit 0a6b4401f5
+49 -6
View File
@@ -1,3 +1,5 @@
use std::f32::consts;
use bevy::{prelude::*, window::PrimaryWindow};
use crate::design_system;
@@ -33,10 +35,10 @@ pub(super) fn draw(
let dist = Vec3::distance(camera_xform.translation, xform.translation);
if transform.contains(InteractionTransform::TRANSLATE) {
draw_translate_gizmo(&xform, &mut gizmos, space, dist / 14.);
draw_translate_gizmo(&xform, &mut gizmos, space, dist / 12.5);
}
if transform.contains(InteractionTransform::ROTATE) {
draw_rotate_gizmo(&xform, &mut gizmos, space, dist / 20.);
draw_rotate_gizmo(&xform, camera_xform, &mut gizmos, space, dist / 20.);
}
}
}
@@ -61,14 +63,55 @@ fn draw_translate_gizmo(xform: &Transform, gizmos: &mut Gizmos, space: Transform
}
#[inline]
fn draw_rotate_gizmo(xform: &Transform, gizmos: &mut Gizmos, space: TransformSpace, radius: f32) {
fn draw_rotate_gizmo(
xform: &Transform,
camera_xform: &Transform,
gizmos: &mut Gizmos,
space: TransformSpace,
radius: f32,
) {
let origin = xform.translation;
let basis = match space {
TransformSpace::Local => xform,
TransformSpace::World => &Transform::IDENTITY,
};
gizmos.circle(origin, basis.local_x(), radius, design_system::Color::RED);
gizmos.circle(origin, basis.local_y(), radius, design_system::Color::GREEN);
gizmos.circle(origin, basis.local_z(), radius, design_system::Color::BLUE);
// Draw a screen-space rotator ring
gizmos.circle(origin, camera_xform.forward(), radius * 1.2, Color::WHITE);
// Draw a semicircle for each of the X, Y and Z axes
for (normal, color) in [
(basis.local_x(), design_system::Color::RED),
(basis.local_y(), design_system::Color::GREEN),
(basis.local_z(), design_system::Color::BLUE),
] {
let perp = Vec3::cross(normal, camera_xform.forward()).normalize();
let start = origin + perp * radius;
gizmos.arc(origin, normal, start, consts::PI, color);
}
}
trait Arc {
/// Draw an arc around `center` with angular `length` (in radians),
/// beginning at `point` and progressing counter-clockwise around `axis`
/// (if axis were pointed toward the viewer). The radius is derived from the
/// distance between `center` and `start`.
fn arc(&mut self, center: Vec3, axis: Vec3, start: Vec3, length: f32, color: Color);
}
impl<'a> Arc for Gizmos<'a> {
fn arc(&mut self, center: Vec3, normal: Vec3, start: Vec3, length: f32, color: Color) {
let two_pi = consts::PI * 2.;
let segments = f32::round(32. * (length / two_pi));
let angle_inc = length / segments;
let rotator = Mat3::from_axis_angle(normal, angle_inc);
let mut vector = start - center;
for _ in 0..(segments as usize) {
let next = rotator * vector;
self.line(center + vector, center + next, color);
vector = next;
}
}
}