Fix Matrix2::look_at, add look_at_stable

Fix bug in look_at

Use the up vector to determine turn direction

Add look_at_stable

Matrix2::look_at calls look_at_stable
This commit is contained in:
blargg 2019-08-24 15:48:38 -05:00
parent ec5261d15b
commit dd9f08ccee
3 changed files with 45 additions and 4 deletions

View file

@ -99,11 +99,23 @@ impl<S> Matrix2<S> {
}
impl<S: BaseFloat> Matrix2<S> {
/// Create a transformation matrix that will cause a vector to point at
/// `dir`, using `up` for orientation.
/// Create a transformation matrix that will cause `unit_x()` to point at
/// `dir`. `unit_y()` will be perpendicular to `dir`, and the closest to `up`.
pub fn look_at(dir: Vector2<S>, up: Vector2<S>) -> Matrix2<S> {
//TODO: verify look_at 2D
Matrix2::from_cols(up, dir).transpose()
Matrix2::look_at_stable(dir, up.x * dir.y >= up.y * dir.x)
}
/// Crate a transformation that will cause `unit_x()` to point at
/// `dir`. This is similar to `look_at`, but does not take an `up` vector.
/// This will not cause `unit_y()` to flip when `dir` crosses over the `up` vector.
pub fn look_at_stable(dir: Vector2<S>, flip: bool) -> Matrix2<S> {
let basis1 = dir.normalize();
let basis2 = if flip {
Vector2::new(basis1.y, -basis1.x)
} else {
Vector2::new(-basis1.y, basis1.x)
};
Matrix2::from_cols(basis1, basis2)
}
#[inline]

View file

@ -146,6 +146,14 @@ pub struct Basis2<S> {
mat: Matrix2<S>,
}
impl<S: BaseFloat> Basis2<S> {
pub fn look_at_stable(dir: Vector2<S>, flip: bool) -> Basis2<S> {
Basis2 {
mat: Matrix2::look_at_stable(dir, flip),
}
}
}
impl<S: BaseFloat> AsRef<Matrix2<S>> for Basis2<S> {
#[inline]
fn as_ref(&self) -> &Matrix2<S> {

View file

@ -175,6 +175,27 @@ pub mod matrix2 {
let rot3: Matrix2<f64> = Matrix2::from_angle(Rad(f64::consts::PI));
assert_ulps_eq!(rot3 * Vector2::new(1.0, 1.0), &Vector2::new(-1.0, -1.0));
}
#[test]
fn test_look_at() {
// rot should rotate unit_x() to look at the input vector
let rot = Matrix2::look_at(V, Vector2::unit_y());
assert_eq!(rot * Vector2::unit_x(),
V.normalize());
let new_up = Vector2::new(-V.y, V.x).normalize();
assert_eq!(rot * Vector2::unit_y(),
new_up);
let rot_down = Matrix2::look_at(V, -1.0 * Vector2::unit_y());
assert_eq!(rot_down * Vector2::unit_x(),
V.normalize());
assert_eq!(rot_down * Vector2::unit_y(),
-1.0 * new_up);
let rot2 = Matrix2::look_at(-V, Vector2::unit_y());
assert_eq!(rot2 * Vector2::unit_x(),
(-V).normalize());
}
}
pub mod matrix3 {