diff --git a/src/matrix.rs b/src/matrix.rs index 8b98632..3f28998 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -161,6 +161,8 @@ impl Matrix3 { } /// Create a rotation matrix from an angle around an arbitrary axis. + /// + /// The specified axis **must be normalized**, or it represents an invalid rotation. pub fn from_axis_angle(axis: Vector3, angle: Rad) -> Matrix3 { let (s, c) = Rad::sin_cos(angle); let _1subc = S::one() - c; @@ -266,6 +268,8 @@ impl Matrix4 { } /// Create a homogeneous transformation matrix from an angle around an arbitrary axis. + /// + /// The specified axis **must be normalized**, or it represents an invalid rotation. pub fn from_axis_angle(axis: Vector3, angle: Rad) -> Matrix4 { let (s, c) = Rad::sin_cos(angle); let _1subc = S::one() - c; diff --git a/src/rotation.rs b/src/rotation.rs index d819de0..5352e6e 100644 --- a/src/rotation.rs +++ b/src/rotation.rs @@ -72,6 +72,8 @@ pub trait Rotation3: Rotation> + Into> + From>> { /// Create a rotation using an angle around a given axis. + /// + /// The specified axis **must be normalized**, or it represents an invalid rotation. fn from_axis_angle(axis: Vector3, angle: Rad) -> Self; /// Create a rotation from an angle around the `x` axis (pitch). diff --git a/tests/quaternion.rs b/tests/quaternion.rs index 10a47af..78ac4f5 100644 --- a/tests/quaternion.rs +++ b/tests/quaternion.rs @@ -168,3 +168,55 @@ mod rotate_from_euler { assert_approx_eq!(vec3(1.0, 0.0, 0.0), rot * vec); } } + +mod rotate_from_axis_angle { + use cgmath::*; + + #[test] + fn test_x() { + let vec = vec3(0.0, 0.0, 1.0); + + let rot = Quaternion::from_angle_x(deg(90.0).into()); + assert_approx_eq!(vec3(0.0, -1.0, 0.0), rot * vec); + } + + #[test] + fn test_y() { + let vec = vec3(0.0, 0.0, 1.0); + + let rot = Quaternion::from_angle_y(deg(90.0).into()); + assert_approx_eq!(vec3(1.0, 0.0, 0.0), rot * vec); + } + + #[test] + fn test_z() { + let vec = vec3(1.0, 0.0, 0.0); + + let rot = Quaternion::from_angle_z(deg(90.0).into()); + assert_approx_eq!(vec3(0.0, 1.0, 0.0), rot * vec); + } + + #[test] + fn test_xy() { + let vec = vec3(0.0, 0.0, 1.0); + + let rot = Quaternion::from_axis_angle(vec3(1.0, 1.0, 0.0).normalize(), deg(90.0).into()); + assert_approx_eq!(vec3(2.0f32.sqrt() / 2.0, -2.0f32.sqrt() / 2.0, 0.0), rot * vec); + } + + #[test] + fn test_yz() { + let vec = vec3(1.0, 0.0, 0.0); + + let rot = Quaternion::from_axis_angle(vec3(0.0, 1.0, 1.0).normalize(), deg(-90.0).into()); + assert_approx_eq!(vec3(0.0, -2.0f32.sqrt() / 2.0, 2.0f32.sqrt() / 2.0), rot * vec); + } + + #[test] + fn test_xz() { + let vec = vec3(0.0, 1.0, 0.0); + + let rot = Quaternion::from_axis_angle(vec3(1.0, 0.0, 1.0).normalize(), deg(90.0).into()); + assert_approx_eq!(vec3(-2.0f32.sqrt() / 2.0, 0.0, 2.0f32.sqrt() / 2.0), rot * vec); + } +}