look_at() implemented as a part of Transform trait

This commit is contained in:
Dzmitry Malyshau 2014-01-25 10:54:54 -05:00
parent 39b6bd2a5c
commit 1789f26ea1
8 changed files with 70 additions and 31 deletions

View file

@ -13,7 +13,7 @@ The library provides:
- angle units: `Rad`, `Deg`
- points: `Point2`, `Point3`
- rays: `Ray2`, `Ray3`
- a plane: `Plane`
- a plane type: `Plane`
- perspective projections: `Perspective`, `PerspectiveFov`, `Ortho`
- a view frustum: `Frustrum`
- spatial transformations: `AffineMatrix3`, `Transform3D`

View file

@ -1,4 +1,4 @@
// Copyright 2013 The CGMath Developers. For a full listing of the authors,
// Copyright 2014 The CGMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");

View file

@ -68,7 +68,12 @@ impl<S: Primitive> Mat2<S> {
}
}
impl<S: Float> Mat2<S> {
impl<S: Float + ApproxEq<S>> Mat2<S> {
pub fn look_at(dir: &Vec2<S>, up: &Vec2<S>) -> Mat2<S> {
//TODO: verify look_at 2D
Mat2::from_cols(up.clone(), dir.clone()).transpose()
}
#[inline]
pub fn from_angle(theta: Rad<S>) -> Mat2<S> {
let cos_theta = cos(theta.clone());
@ -115,11 +120,11 @@ impl<S: Primitive> Mat3<S> {
impl<S: Float + ApproxEq<S>>
Mat3<S> {
pub fn look_at(dir: &Vec3<S>, up: &Vec3<S>) -> Mat3<S> {
let dir = dir.normalize();
let side = dir.cross(&up.normalize());
let up = side.cross(&dir).normalize();
let dir = dir.normalize();
let side = up.cross(&dir).normalize();
let up = dir.cross(&side).normalize();
Mat3::from_cols(up, side, dir)
Mat3::from_cols(side, up, dir).transpose()
}
/// Create a matrix from a rotation around the `x` axis (pitch).
@ -672,7 +677,7 @@ impl<S: Float + ApproxEq<S>>
ToQuat<S> for Mat3<S> {
/// Convert the matrix to a quaternion
fn to_quat(&self) -> Quat<S> {
// http://www.cs.ucr.edu/~vbz/resources/Quatut.pdf
// http://www.cs.ucr.edu/~vbz/resources/quatut.pdf
let trace = self.trace();
let half: S = cast(0.5).unwrap();
match () {

View file

@ -37,11 +37,6 @@ impl<S: Num> Point2<S> {
pub fn new(x: S, y: S) -> Point2<S> {
Point2 { x: x, y: y }
}
#[inline]
pub fn origin() -> Point2<S> {
Point2 { x: zero(), y: zero() }
}
}
impl<S: Num> Point3<S> {
@ -49,11 +44,6 @@ impl<S: Num> Point3<S> {
pub fn new(x: S, y: S, z: S) -> Point3<S> {
Point3 { x: x, y: y, z: z }
}
#[inline]
pub fn origin() -> Point3<S> {
Point3 { x: zero(), y: zero(), z: zero() }
}
}
impl<S: Clone + Num + Primitive> Point3<S> {
@ -78,6 +68,8 @@ pub trait Point
>
: Array<S, Slice>
{
#[inline] fn origin() -> Self{ build(|_i| zero::<S>()) }
#[inline] fn from_vec(v: &V) -> Self { build(|i| v.i(i).clone()) }
#[inline] fn to_vec(&self) -> V { build(|i| self.i(i).clone()) }

View file

@ -47,11 +47,6 @@ Quat<S> {
Quat { s: s, v: v }
}
#[inline]
pub fn look_at(dir: &Vec3<S>, up: &Vec3<S>) -> Quat<S> {
Mat3::look_at(dir, up).to_quat()
}
/// Create a matrix from a rotation around the `x` axis (pitch).
#[inline]
pub fn from_angle_x(theta: Rad<S>) -> Quat<S> {

View file

@ -1,4 +1,4 @@
// Copyright 2013 The CGMath Developers. For a full listing of the authors,
// Copyright 2014 The CGMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -36,6 +36,8 @@ pub trait Rotation
+ ApproxEq<S>
{
fn identity() -> Self;
fn look_at(dir: &V, up: &V) -> Self;
fn rotate_vec(&self, vec: &V) -> V;
#[inline]
@ -120,6 +122,16 @@ impl<S: Float + ApproxEq<S>>
Rotation<S, [S, ..2], Vec2<S>, Point2<S>> for Basis2<S> {
#[inline]
fn identity() -> Basis2<S> { Basis2{ mat: Mat2::identity() } }
#[inline]
fn look_at(dir: &Vec2<S>, up: &Vec2<S>) -> Basis2<S> {
Basis2 { mat: Mat2::look_at(dir, up) }
}
#[inline]
fn look_at(dir: &Vec2<S>, up: &Vec2<S>) -> Basis2<S> {
Basis2 { mat: Mat2::look_at(dir, up) }
}
#[inline]
fn rotate_vec(&self, vec: &Vec2<S>) -> Vec2<S> { self.mat.mul_v(vec) }
@ -165,11 +177,6 @@ pub struct Basis3<S> {
impl<S: Float + ApproxEq<S>>
Basis3<S> {
#[inline]
pub fn look_at(dir: &Vec3<S>, up: &Vec3<S>) -> Basis3<S> {
Basis3 { mat: Mat3::look_at(dir, up) }
}
/// Create a rotation matrix from a rotation around the `x` axis (pitch).
pub fn from_angle_x(theta: Rad<S>) -> Basis3<S> {
Basis3 { mat: Mat3::from_angle_x(theta) }
@ -229,6 +236,11 @@ impl<S: Float + ApproxEq<S>>
Rotation<S, [S, ..3], Vec3<S>, Point3<S>> for Basis3<S> {
#[inline]
fn identity() -> Basis3<S> { Basis3{ mat: Mat3::identity() } }
#[inline]
fn look_at(dir: &Vec3<S>, up: &Vec3<S>) -> Basis3<S> {
Basis3 { mat: Mat3::look_at(dir, up) }
}
#[inline]
fn rotate_vec(&self, vec: &Vec3<S>) -> Vec3<S> { self.mat.mul_v(vec) }
@ -278,6 +290,11 @@ impl<S: Float + ApproxEq<S>>
Rotation<S, [S, ..3], Vec3<S>, Point3<S>> for Quat<S> {
#[inline]
fn identity() -> Quat<S> { Quat::identity() }
#[inline]
fn look_at(dir: &Vec3<S>, up: &Vec3<S>) -> Quat<S> {
Mat3::look_at(dir, up).to_quat()
}
#[inline]
fn rotate_vec(&self, vec: &Vec3<S>) -> Vec3<S> { self.mul_v(vec) }

View file

@ -1,4 +1,4 @@
// Copyright 2013 The CGMath Developers. For a full listing of the authors,
// Copyright 2014 The CGMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -33,6 +33,7 @@ pub trait Transform
>
{
fn identity() -> Self;
fn look_at(eye: &P, center: &P, up: &V) -> Self;
fn transform_vec(&self, vec: &V) -> V;
fn transform_point(&self, point: &P) -> P;
@ -90,6 +91,18 @@ Transform<S, Slice, V, P> for Decomposed<S,V,R> {
}
}
#[inline]
fn look_at(eye: &P, center: &P, up: &V) -> Decomposed<S,V,R> {
let origin :P = Point::origin();
let rot :R = Rotation::look_at( &center.sub_p(eye), up );
let disp :V = rot.rotate_vec( &origin.sub_p(eye) );
Decomposed {
scale: num::one(),
rot: rot,
disp: disp,
}
}
#[inline]
fn transform_vec(&self, vec: &V) -> V {
self.rot.rotate_vec( &vec.mul_s( self.scale.clone() ))
@ -162,6 +175,11 @@ Transform<S, [S, ..3], Vec3<S>, Point3<S>> for AffineMatrix3<S> {
fn identity() -> AffineMatrix3<S> {
AffineMatrix3 { mat: Mat4::identity() }
}
#[inline]
fn look_at(eye: &Point3<S>, center: &Point3<S>, up: &Vec3<S>) -> AffineMatrix3<S> {
AffineMatrix3 { mat: Mat4::look_at(eye, center, up) }
}
#[inline]
fn transform_vec(&self, vec: &Vec3<S>) -> Vec3<S> {

View file

@ -1,4 +1,4 @@
// Copyright 2013 The CGMath Developers. For a full listing of the authors,
// Copyright 2014 The CGMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -15,6 +15,7 @@
use cgmath::quaternion::*;
use cgmath::transform::*;
use cgmath::point::*;
use cgmath::vector::*;
use cgmath::approx::ApproxEq;
@ -26,3 +27,14 @@ fn test_invert() {
let vt = t.get().transform_vec( &v );
assert!(v.approx_eq( &ti.transform_vec( &vt ) ));
}
#[test]
fn test_look_at() {
let eye = Point3::new(0.0, 0.0, -5.0);
let center = Point3::new(0.0, 0.0, 0.0);
let up = Vec3::new(1.0, 0.0, 0.0);
let t: Decomposed<f64,Vec3<f64>,Quat<f64>> = Transform::look_at(&eye, &center, &up);
let point = Point3::new(1.0, 0.0, 0.0);
let view_point = Point3::new(0.0, 1.0, 5.0);
assert!( t.transform_point(&point).approx_eq(&view_point) );
}