Skip to content

Commit

Permalink
Implement track operation.
Browse files Browse the repository at this point in the history
  • Loading branch information
n3vu0r committed Feb 20, 2024
1 parent ca0cec3 commit 7745517
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 3 deletions.
32 changes: 32 additions & 0 deletions src/clamp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,38 @@ pub trait Clamp<N: Copy + RealField>: Send + Sync + Debug + 'static {
}
(min_delta != *delta).then_some((min_delta, loops))
}
Delta::Track { vec: _ } => {
let old_frame = frame;
let old_target = frame.target();
let old_rot_inverse = frame.view().rotation.inverse();
let mut min_delta = *delta;
let mut loops = 0;
loop {
let frame = min_delta.transform(old_frame);
let mut bound = false;
if let Some(plane) = self.target(&frame) {
bound = true;
let new_target = plane.project_point(frame.target());
let vec = old_rot_inverse * (new_target - old_target);
min_delta = Delta::Track { vec };
}
let frame = min_delta.transform(old_frame);
if let Some(_plane) = self.up(&frame) {
bound = true;
// TODO Implement gliding.
min_delta = Delta::Frame;
}
if bound {
if loops == self.loops() {
break;
}
loops += 1;
} else {
break;
}
}
(min_delta != *delta).then_some((min_delta, loops))
}
&Delta::Orbit { rot: _, pos } => {
if pos != Point3::origin() {
return Some((Delta::Frame, 0));
Expand Down
11 changes: 11 additions & 0 deletions src/delta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ pub enum Delta<N: Copy + RealField> {
/// Yaw axis.
yaw_axis: Unit<Vector3<N>>,
},
/// Tracks target which slides by vector in world space.
///
/// Preserves eye position inclusive its roll attitude.
Track {
/// Vector in world space of a sliding target to track.
vec: Vector3<N>,
},
/// Orbits eye by rotation in camera space around point in camera space.
///
/// See [`Frame::local_orbit_around()`].
Expand Down Expand Up @@ -58,6 +65,7 @@ impl<N: Copy + RealField> Delta<N> {
yaw,
ref yaw_axis,
} => frame.look_around(*pitch, *yaw, yaw_axis),
Self::Track { vec } => frame.set_target(frame.target() + vec),
Self::Orbit { rot, pos } => frame.local_orbit_around(rot, pos),
Self::Slide { vec } => frame.local_slide(vec),
Self::Scale { rat, pos } => frame.local_scale_around(*rat, pos),
Expand All @@ -80,6 +88,7 @@ impl<N: Copy + RealField> Delta<N> {
yaw: -yaw,
yaw_axis,
},
Self::Track { vec } => Self::Track { vec: -vec },
Self::Orbit { rot, pos } => Self::Orbit {
rot: rot.inverse(),
pos,
Expand Down Expand Up @@ -111,6 +120,7 @@ impl<N: Copy + RealField> Delta<N> {
yaw: yaw * t,
yaw_axis,
},
Self::Track { vec } => Self::Track { vec: vec * t },
Self::Orbit { rot, pos } => Self::Orbit {
rot: rot.powf(t),
pos,
Expand Down Expand Up @@ -139,6 +149,7 @@ impl<N: Copy + RealField> Delta<N> {
yaw: yaw.to_superset(),
yaw_axis: yaw_axis.cast(),
},
Self::Track { vec } => Delta::Track { vec: vec.cast() },
Self::Orbit { rot, pos } => Delta::Orbit {
rot: rot.cast(),
pos: pos.cast(),
Expand Down
12 changes: 9 additions & 3 deletions src/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,16 @@ impl<N: Copy + RealField> Frame<N> {
&self.pos
}
/// Sets target position in world space preserving eye position inclusive its roll attitude.
pub fn set_target(&mut self, target: Point3<N>) {
///
/// Allows to track a moving object.
pub fn set_target(&mut self, pos: Point3<N>) {
let eye = self.eye();
self.pos = target;
self.zat = (self.pos - eye).norm();
let (new_dir, zat) = Unit::new_and_get(pos - eye);
let old_dir = Unit::new_normalize(self.pos - eye);
let rot = UnitQuaternion::rotation_between_axis(&old_dir, &new_dir)
.unwrap_or_else(|| UnitQuaternion::from_axis_angle(&self.yaw_axis(), N::pi()));
let rot = rot * self.rot;
*self = Self { pos, rot, zat }
}
/// Distance between eye and target.
#[must_use]
Expand Down

0 comments on commit 7745517

Please sign in to comment.