Merge #491
491: Fix Matrix2::look_at, add look_at_stable r=kvark a=blargg ## Changes 1. Fixes `Matrix2::look_at` 2. Adds tests for `look_at` 3. Adds a new function, `look_at_stable` ## Notes I added a new function for 2d look at rotation. `look_at` is a bit weird in practice for 2d. For example, if you are making a basis matrix to orient a 2d character to look at a point, `look_at` will flip the character as they rotate past `up` or `-up` vectors. This is the best match for what look_at is supposed to do, I think. `look_at_stable` will not flip based on orientation, you just pass in which way to flip. This is a bit easier to use to rotate 2d characters. `look_at_stable` could have a better name. I think we can also consider removing the flip param, and just let the user flip the matrix with a transform later. Co-authored-by: blargg <tomjankauski@gmail.com>
This commit is contained in:
commit
f69e781b8f
3 changed files with 45 additions and 4 deletions
|
@ -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]
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue