Add Transform::{look_at_rh, look_at_lh} and deprecate look_at
Corresponding functions have been added to Matrix4 and Decomposed and are now consistent. Matrix3, Matrix2, and the Rotation trait are only partially updated.
This commit is contained in:
parent
164808eebc
commit
213fc580a9
3 changed files with 154 additions and 0 deletions
|
@ -189,6 +189,7 @@ impl<S: BaseFloat> Matrix3<S> {
|
|||
|
||||
/// Create a rotation matrix that will cause a vector to point at
|
||||
/// `dir`, using `up` for orientation.
|
||||
#[deprecated = "Use Matrix3::look_at_lh"]
|
||||
pub fn look_at(dir: Vector3<S>, up: Vector3<S>) -> Matrix3<S> {
|
||||
let dir = dir.normalize();
|
||||
let side = up.cross(dir).normalize();
|
||||
|
@ -197,6 +198,26 @@ impl<S: BaseFloat> Matrix3<S> {
|
|||
Matrix3::from_cols(side, up, dir).transpose()
|
||||
}
|
||||
|
||||
/// Create a rotation matrix that will cause a vector to point at
|
||||
/// `dir`, using `up` for orientation.
|
||||
pub fn look_at_lh(dir: Vector3<S>, up: Vector3<S>) -> Matrix3<S> {
|
||||
let dir = dir.normalize();
|
||||
let side = up.cross(dir).normalize();
|
||||
let up = dir.cross(side).normalize();
|
||||
|
||||
Matrix3::from_cols(side, up, dir).transpose()
|
||||
}
|
||||
|
||||
/// Create a rotation matrix that will cause a vector to point at
|
||||
/// `dir`, using `up` for orientation.
|
||||
pub fn look_at_rh(dir: Vector3<S>, up: Vector3<S>) -> Matrix3<S> {
|
||||
let dir = -dir.normalize();
|
||||
let side = up.cross(dir).normalize();
|
||||
let up = dir.cross(side).normalize();
|
||||
|
||||
Matrix3::from_cols(side, up, dir).transpose()
|
||||
}
|
||||
|
||||
/// Create a rotation matrix from a rotation around the `x` axis (pitch).
|
||||
pub fn from_angle_x<A: Into<Rad<S>>>(theta: A) -> Matrix3<S> {
|
||||
// http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations
|
||||
|
@ -333,6 +354,7 @@ impl<S: BaseFloat> Matrix4<S> {
|
|||
|
||||
/// Create a homogeneous transformation matrix that will cause a vector to point at
|
||||
/// `dir`, using `up` for orientation.
|
||||
#[deprecated = "Use Matrix4::look_to_rh"]
|
||||
pub fn look_at_dir(eye: Point3<S>, dir: Vector3<S>, up: Vector3<S>) -> Matrix4<S> {
|
||||
let f = dir.normalize();
|
||||
let s = f.cross(up).normalize();
|
||||
|
@ -347,12 +369,47 @@ impl<S: BaseFloat> Matrix4<S> {
|
|||
)
|
||||
}
|
||||
|
||||
/// Create a homogeneous transformation matrix that will cause a vector to point at
|
||||
/// `dir`, using `up` for orientation.
|
||||
pub fn look_to_rh(eye: Point3<S>, dir: Vector3<S>, up: Vector3<S>) -> Matrix4<S> {
|
||||
let f = dir.normalize();
|
||||
let s = f.cross(up).normalize();
|
||||
let u = s.cross(f);
|
||||
|
||||
#[cfg_attr(rustfmt, rustfmt_skip)]
|
||||
Matrix4::new(
|
||||
s.x.clone(), u.x.clone(), -f.x.clone(), S::zero(),
|
||||
s.y.clone(), u.y.clone(), -f.y.clone(), S::zero(),
|
||||
s.z.clone(), u.z.clone(), -f.z.clone(), S::zero(),
|
||||
-eye.dot(s), -eye.dot(u), eye.dot(f), S::one(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a homogeneous transformation matrix that will cause a vector to point at
|
||||
/// `dir`, using `up` for orientation.
|
||||
pub fn look_to_lh(eye: Point3<S>, dir: Vector3<S>, up: Vector3<S>) -> Matrix4<S> {
|
||||
Matrix4::look_to_rh(eye, -dir, up)
|
||||
}
|
||||
|
||||
/// Create a homogeneous transformation matrix that will cause a vector to point at
|
||||
/// `center`, using `up` for orientation.
|
||||
#[deprecated = "Use Matrix4::look_at_rh"]
|
||||
pub fn look_at(eye: Point3<S>, center: Point3<S>, up: Vector3<S>) -> Matrix4<S> {
|
||||
Matrix4::look_at_dir(eye, center - eye, up)
|
||||
}
|
||||
|
||||
/// Create a homogeneous transformation matrix that will cause a vector to point at
|
||||
/// `center`, using `up` for orientation.
|
||||
pub fn look_at_rh(eye: Point3<S>, center: Point3<S>, up: Vector3<S>) -> Matrix4<S> {
|
||||
Matrix4::look_to_rh(eye, center - eye, up)
|
||||
}
|
||||
|
||||
/// Create a homogeneous transformation matrix that will cause a vector to point at
|
||||
/// `center`, using `up` for orientation.
|
||||
pub fn look_at_lh(eye: Point3<S>, center: Point3<S>, up: Vector3<S>) -> Matrix4<S> {
|
||||
Matrix4::look_to_lh(eye, center - eye, up)
|
||||
}
|
||||
|
||||
/// Create a homogeneous transformation matrix from a rotation around the `x` axis (pitch).
|
||||
pub fn from_angle_x<A: Into<Rad<S>>>(theta: A) -> Matrix4<S> {
|
||||
// http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations
|
||||
|
@ -1043,6 +1100,16 @@ impl<S: BaseFloat> Transform<Point2<S>> for Matrix3<S> {
|
|||
Matrix3::from(Matrix2::look_at(dir, up))
|
||||
}
|
||||
|
||||
fn look_at_lh(eye: Point2<S>, center: Point2<S>, up: Vector2<S>) -> Matrix3<S> {
|
||||
let dir = center - eye;
|
||||
Matrix3::from(Matrix2::look_at(dir, up))
|
||||
}
|
||||
|
||||
fn look_at_rh(eye: Point2<S>, center: Point2<S>, up: Vector2<S>) -> Matrix3<S> {
|
||||
let dir = eye - center;
|
||||
Matrix3::from(Matrix2::look_at(dir, up))
|
||||
}
|
||||
|
||||
fn transform_vector(&self, vec: Vector2<S>) -> Vector2<S> {
|
||||
(self * vec.extend(S::zero())).truncate()
|
||||
}
|
||||
|
@ -1066,6 +1133,16 @@ impl<S: BaseFloat> Transform<Point3<S>> for Matrix3<S> {
|
|||
Matrix3::look_at(dir, up)
|
||||
}
|
||||
|
||||
fn look_at_lh(eye: Point3<S>, center: Point3<S>, up: Vector3<S>) -> Matrix3<S> {
|
||||
let dir = center - eye;
|
||||
Matrix3::look_at_lh(dir, up)
|
||||
}
|
||||
|
||||
fn look_at_rh(eye: Point3<S>, center: Point3<S>, up: Vector3<S>) -> Matrix3<S> {
|
||||
let dir = center - eye;
|
||||
Matrix3::look_at_rh(dir, up)
|
||||
}
|
||||
|
||||
fn transform_vector(&self, vec: Vector3<S>) -> Vector3<S> {
|
||||
self * vec
|
||||
}
|
||||
|
@ -1084,10 +1161,19 @@ impl<S: BaseFloat> Transform<Point3<S>> for Matrix3<S> {
|
|||
}
|
||||
|
||||
impl<S: BaseFloat> Transform<Point3<S>> for Matrix4<S> {
|
||||
|
||||
fn look_at(eye: Point3<S>, center: Point3<S>, up: Vector3<S>) -> Matrix4<S> {
|
||||
Matrix4::look_at(eye, center, up)
|
||||
}
|
||||
|
||||
fn look_at_lh(eye: Point3<S>, center: Point3<S>, up: Vector3<S>) -> Matrix4<S> {
|
||||
Matrix4::look_at_lh(eye, center, up)
|
||||
}
|
||||
|
||||
fn look_at_rh(eye: Point3<S>, center: Point3<S>, up: Vector3<S>) -> Matrix4<S> {
|
||||
Matrix4::look_at_rh(eye, center, up)
|
||||
}
|
||||
|
||||
fn transform_vector(&self, vec: Vector3<S>) -> Vector3<S> {
|
||||
(self * vec.extend(S::zero())).truncate()
|
||||
}
|
||||
|
|
|
@ -30,8 +30,17 @@ use std::ops::Mul;
|
|||
pub trait Transform<P: EuclideanSpace>: Sized + One {
|
||||
/// Create a transformation that rotates a vector to look at `center` from
|
||||
/// `eye`, using `up` for orientation.
|
||||
#[deprecated = "Use look_at_rh or look_at_lh"]
|
||||
fn look_at(eye: P, center: P, up: P::Diff) -> Self;
|
||||
|
||||
/// Create a transformation that rotates a vector to look at `center` from
|
||||
/// `eye`, using `up` for orientation.
|
||||
fn look_at_rh(eye: P, center: P, up: P::Diff) -> Self;
|
||||
|
||||
/// Create a transformation that rotates a vector to look at `center` from
|
||||
/// `eye`, using `up` for orientation.
|
||||
fn look_at_lh(eye: P, center: P, up: P::Diff) -> Self;
|
||||
|
||||
/// Transform a vector using this transform.
|
||||
fn transform_vector(&self, vec: P::Diff) -> P::Diff;
|
||||
|
||||
|
@ -113,6 +122,28 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn look_at_lh(eye: P, center: P, up: P::Diff) -> Decomposed<P::Diff, R> {
|
||||
let rot = R::look_at(center - eye, up);
|
||||
let disp = rot.rotate_vector(P::origin() - eye);
|
||||
Decomposed {
|
||||
scale: P::Scalar::one(),
|
||||
rot: rot,
|
||||
disp: disp,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn look_at_rh(eye: P, center: P, up: P::Diff) -> Decomposed<P::Diff, R> {
|
||||
let rot = R::look_at(eye - center, up);
|
||||
let disp = rot.rotate_vector(P::origin() - eye);
|
||||
Decomposed {
|
||||
scale: P::Scalar::one(),
|
||||
rot: rot,
|
||||
disp: disp,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn transform_vector(&self, vec: P::Diff) -> P::Diff {
|
||||
self.rot.rotate_vector(vec * self.scale)
|
||||
|
|
|
@ -88,6 +88,7 @@ fn test_inverse_vector() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[allow(deprecated)]
|
||||
fn test_look_at() {
|
||||
let eye = Point3::new(0.0f64, 0.0, -5.0);
|
||||
let center = Point3::new(0.0f64, 0.0, 0.0);
|
||||
|
@ -98,6 +99,42 @@ fn test_look_at() {
|
|||
assert_ulps_eq!(&t.transform_point(point), &view_point);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_look_at_lh() {
|
||||
let eye = Point3::new(0.0f64, 0.0, -5.0);
|
||||
let center = Point3::new(0.0f64, 0.0, 0.0);
|
||||
let up = Vector3::new(1.0f64, 0.0, 0.0);
|
||||
let t: Decomposed<Vector3<f64>, Quaternion<f64>> = Transform::look_at_lh(eye, center, up);
|
||||
let point = Point3::new(1.0f64, 0.0, 0.0);
|
||||
let view_point = Point3::new(0.0f64, 1.0, 5.0);
|
||||
assert_ulps_eq!(&t.transform_point(point), &view_point);
|
||||
|
||||
// Decomposed::look_at_lh and Matrix4::look_at_lh should be consistent
|
||||
let t: Matrix4<f64> = Transform::look_at_lh(eye, center, up);
|
||||
assert_ulps_eq!(&t.transform_point(point), &view_point);
|
||||
|
||||
// Decomposed::look_at is inconsistent and deprecated, but verify that the behvaior
|
||||
// remains the same until removed.
|
||||
#[allow(deprecated)]
|
||||
let t: Decomposed<Vector3<f64>, Quaternion<f64>> = Transform::look_at(eye, center, up);
|
||||
assert_ulps_eq!(&t.transform_point(point), &view_point);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_look_at_rh() {
|
||||
let eye = Point3::new(0.0f64, 0.0, -5.0);
|
||||
let center = Point3::new(0.0f64, 0.0, 0.0);
|
||||
let up = Vector3::new(1.0f64, 0.0, 0.0);
|
||||
let t: Decomposed<Vector3<f64>, Quaternion<f64>> = Transform::look_at_rh(eye, center, up);
|
||||
let point = Point3::new(1.0f64, 0.0, 0.0);
|
||||
let view_point = Point3::new(0.0f64, 1.0, -5.0);
|
||||
assert_ulps_eq!(&t.transform_point(point), &view_point);
|
||||
|
||||
// Decomposed::look_at_rh and Matrix4::look_at_rh should be consistent
|
||||
let t: Matrix4<f64> = Transform::look_at_rh(eye, center, up);
|
||||
assert_ulps_eq!(&t.transform_point(point), &view_point);
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
#[test]
|
||||
fn test_serialize() {
|
||||
|
|
Loading…
Reference in a new issue