Browse Source

Assuming the vectors are normalized in Matrix4::rotation().

vectorfields
Vladimír Vondruš 14 years ago
parent
commit
7c17871c90
  1. 35
      src/Math/Matrix4.h
  2. 3
      src/Math/Test/CMakeLists.txt
  3. 22
      src/Math/Test/Matrix4Test.cpp

35
src/Math/Matrix4.h

@ -69,36 +69,39 @@ template<class T> class Matrix4: public Matrix<4, T> {
/**
* @brief 3D rotation matrix
* @param angle Rotation angle (counterclockwise, in radians)
* @param vec Rotation vector
* @param vec Normalized rotation vector
*
* @see Matrix3::rotation(), Vector3::xAxis(), Vector3::yAxis(), Vector3::zAxis(), deg(), rad()
* @todo optimize - Assume the vectors are normalized?
* @see Matrix3::rotation(), Vector3::xAxis(), Vector3::yAxis(),
* Vector3::zAxis(), deg(), rad()
* @attention Assertion fails on non-normalized rotation vector and
* identity matrix is returned.
*/
static Matrix4<T> rotation(T angle, const Vector3<T>& vec) {
Vector3<T> vn = vec.normalized();
CORRADE_ASSERT(MathTypeTraits<T>::equals(vec.dot(), T(1)),
"Math::Matrix4::rotation(): vector must be normalized", {});
T sine = std::sin(angle);
T cosine = std::cos(angle);
T oneMinusCosine = T(1) - cosine;
T xx = vn.x()*vn.x();
T xy = vn.x()*vn.y();
T xz = vn.x()*vn.z();
T yy = vn.y()*vn.y();
T yz = vn.y()*vn.z();
T zz = vn.z()*vn.z();
T xx = vec.x()*vec.x();
T xy = vec.x()*vec.y();
T xz = vec.x()*vec.z();
T yy = vec.y()*vec.y();
T yz = vec.y()*vec.z();
T zz = vec.z()*vec.z();
return Matrix4<T>( /* Column-major! */
cosine + xx*oneMinusCosine,
xy*oneMinusCosine + vn.z()*sine,
xz*oneMinusCosine - vn.y()*sine,
xy*oneMinusCosine + vec.z()*sine,
xz*oneMinusCosine - vec.y()*sine,
T(0),
xy*oneMinusCosine - vn.z()*sine,
xy*oneMinusCosine - vec.z()*sine,
cosine + yy*oneMinusCosine,
yz*oneMinusCosine + vn.x()*sine,
yz*oneMinusCosine + vec.x()*sine,
T(0),
xz*oneMinusCosine + vn.y()*sine,
yz*oneMinusCosine - vn.x()*sine,
xz*oneMinusCosine + vec.y()*sine,
yz*oneMinusCosine - vec.x()*sine,
cosine + zz*oneMinusCosine,
T(0),
T(0), T(0), T(0), T(1)

3
src/Math/Test/CMakeLists.txt

@ -5,7 +5,6 @@ corrade_add_test2(MathMathTypeTraitsTest MathTypeTraitsTest.cpp)
corrade_add_test2(MathRectangularMatrixTest RectangularMatrixTest.cpp)
corrade_add_test2(MathVectorTest VectorTest.cpp)
set_target_properties(MathVectorTest PROPERTIES COMPILE_FLAGS -DCORRADE_GRACEFUL_ASSERT)
corrade_add_test2(MathVector2Test Vector2Test.cpp)
corrade_add_test2(MathVector3Test Vector3Test.cpp)
corrade_add_test2(MathVector4Test Vector4Test.cpp)
@ -16,3 +15,5 @@ corrade_add_test2(MathPoint3DTest Point3DTest.cpp)
corrade_add_test2(MathMatrixTest MatrixTest.cpp)
corrade_add_test2(MathMatrix3Test Matrix3Test.cpp)
corrade_add_test2(MathMatrix4Test Matrix4Test.cpp)
set_target_properties(MathVectorTest MathMatrix4Test PROPERTIES COMPILE_FLAGS -DCORRADE_GRACEFUL_ASSERT)

22
src/Math/Test/Matrix4Test.cpp

@ -29,6 +29,7 @@ namespace Magnum { namespace Math { namespace Test {
typedef Math::Matrix4<float> Matrix4;
typedef Math::Matrix3<float> Matrix3;
typedef Math::Vector3<float> Vector3;
Matrix4Test::Matrix4Test() {
addTests(&Matrix4Test::constructIdentity,
@ -88,14 +89,19 @@ void Matrix4Test::scaling() {
}
void Matrix4Test::rotation() {
ostringstream o;
Error::setOutput(&o);
CORRADE_COMPARE(Matrix4::rotation(deg(-74.0f), {-1.0f, 2.0f, 2.0f}), Matrix4());
CORRADE_COMPARE(o.str(), "Math::Matrix4::rotation(): vector must be normalized\n");
Matrix4 matrix(
0.35612214f, -0.80181062f, 0.47987163f, 0.0f,
0.47987163f, 0.59757638f, 0.6423595f, 0.0f,
-0.80181062f, 0.0015183985f, 0.59757638f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
0.35612214f, -0.80181062f, 0.47987163f, 0.0f,
0.47987163f, 0.59757638f, 0.6423595f, 0.0f,
-0.80181062f, 0.0015183985f, 0.59757638f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
);
CORRADE_COMPARE(Matrix4::rotation(deg(-74.0f), {-1.0f, 2.0f, 2.0f}), matrix);
CORRADE_COMPARE(Matrix4::rotation(deg(-74.0f), Vector3(-1.0f, 2.0f, 2.0f).normalized()), matrix);
}
void Matrix4Test::rotationScalingPart() {
@ -122,10 +128,10 @@ void Matrix4Test::rotationPart() {
-0.80181062f, 0.0015183985f, 0.59757638f
);
Matrix4 rotation = Matrix4::rotation(deg(-74.0f), {-1.0f, 2.0f, 2.0f});
Matrix4 rotation = Matrix4::rotation(deg(-74.0f), Vector3(-1.0f, 2.0f, 2.0f).normalized());
CORRADE_COMPARE(rotation.rotation(), expectedRotationPart);
Matrix4 rotationTransformed = Matrix4::translation({2.0f, 5.0f, -3.0f})*rotation*Matrix4::scaling(Vector3<float>(9.0f));
Matrix4 rotationTransformed = Matrix4::translation({2.0f, 5.0f, -3.0f})*rotation*Matrix4::scaling(Vector3(9.0f));
CORRADE_COMPARE(rotationTransformed.rotation(), expectedRotationPart);
}

Loading…
Cancel
Save