Browse Source

Math: using Rad for Quaternion and DualQuaternion functions.

pull/7/head
Vladimír Vondruš 13 years ago
parent
commit
c293630c7c
  1. 6
      src/Math/DualQuaternion.h
  2. 20
      src/Math/Quaternion.h
  3. 39
      src/Math/Test/DualQuaternionTest.cpp
  4. 48
      src/Math/Test/QuaternionTest.cpp

6
src/Math/DualQuaternion.h

@ -46,9 +46,9 @@ template<class T> class DualQuaternion: public Dual<Quaternion<T>> {
* @f]
* @see rotationAngle(), rotationAxis(), Quaternion::rotation(),
* Matrix4::rotation(), Vector3::xAxis(), Vector3::yAxis(),
* Vector3::zAxis(), deg(), rad()
* Vector3::zAxis()
*/
inline static DualQuaternion<T> rotation(T angle, const Vector3<T>& normalizedAxis) {
inline static DualQuaternion<T> rotation(Rad<T> angle, const Vector3<T>& normalizedAxis) {
return {Quaternion<T>::rotation(angle, normalizedAxis), {{}, T(0)}};
}
@ -112,7 +112,7 @@ template<class T> class DualQuaternion: public Dual<Quaternion<T>> {
* @f]
* @see rotationAxis(), rotation(), Quaternion::rotationAngle()
*/
inline T rotationAngle() const {
inline Math::Rad<T> rotationAngle() const {
return this->real().rotationAngle();
}

20
src/Math/Quaternion.h

@ -55,16 +55,16 @@ template<class T> class Quaternion {
}
/**
* @brief Angle between normalized quaternions (in radians)
* @brief Angle between normalized quaternions
*
* Expects that both quaternions are normalized. @f[
* \theta = acos \left( \frac{p \cdot q}{|p| \cdot |q|} \right)
* @f]
*/
inline static T angle(const Quaternion<T>& normalizedA, const Quaternion<T>& normalizedB) {
inline static Rad<T> angle(const Quaternion<T>& normalizedA, const Quaternion<T>& normalizedB) {
CORRADE_ASSERT(MathTypeTraits<T>::equals(normalizedA.dot(), T(1)) && MathTypeTraits<T>::equals(normalizedB.dot(), T(1)),
"Math::Quaternion::angle(): quaternions must be normalized", std::numeric_limits<T>::quiet_NaN());
return angleInternal(normalizedA, normalizedB);
"Math::Quaternion::angle(): quaternions must be normalized", Rad<T>(std::numeric_limits<T>::quiet_NaN()));
return Rad<T>(angleInternal(normalizedA, normalizedB));
}
/**
@ -116,13 +116,13 @@ template<class T> class Quaternion {
* @f]
* @see rotationAngle(), rotationAxis(), DualQuaternion::rotation(),
* Matrix4::rotation(), Vector3::xAxis(), Vector3::yAxis(),
* Vector3::zAxis(), deg(), rad()
* Vector3::zAxis()
*/
inline static Quaternion<T> rotation(T angle, const Vector3<T>& normalizedAxis) {
inline static Quaternion<T> rotation(Rad<T> angle, const Vector3<T>& normalizedAxis) {
CORRADE_ASSERT(MathTypeTraits<T>::equals(normalizedAxis.dot(), T(1)),
"Math::Quaternion::rotation(): axis must be normalized", {});
return {normalizedAxis*std::sin(angle/2), std::cos(angle/2)};
return {normalizedAxis*std::sin(T(angle)/2), std::cos(T(angle)/2)};
}
/**
@ -177,11 +177,11 @@ template<class T> class Quaternion {
* @f]
* @see rotationAxis(), rotation()
*/
inline T rotationAngle() const {
inline Rad<T> rotationAngle() const {
CORRADE_ASSERT(MathTypeTraits<T>::equals(dot(), T(1)),
"Math::Quaternion::rotationAngle(): quaternion must be normalized",
std::numeric_limits<T>::quiet_NaN());
return T(2)*std::acos(_scalar);
Rad<T>(std::numeric_limits<T>::quiet_NaN()));
return Rad<T>(T(2)*std::acos(_scalar));
}
/**

39
src/Math/Test/DualQuaternionTest.cpp

@ -50,6 +50,8 @@ class DualQuaternionTest: public Corrade::TestSuite::Tester {
void debug();
};
typedef Math::Deg<float> Deg;
typedef Math::Rad<float> Rad;
typedef Math::Dual<float> Dual;
typedef Math::Matrix4<float> Matrix4;
typedef Math::DualQuaternion<float> DualQuaternion;
@ -169,15 +171,14 @@ void DualQuaternionTest::rotation() {
std::ostringstream o;
Error::setOutput(&o);
float angle = deg(120.0f);
Vector3 axis(1.0f/Constants<float>::sqrt3());
CORRADE_COMPARE(DualQuaternion::rotation(angle, axis*2.0f), DualQuaternion());
CORRADE_COMPARE(DualQuaternion::rotation(Deg(120.0f), axis*2.0f), DualQuaternion());
CORRADE_COMPARE(o.str(), "Math::Quaternion::rotation(): axis must be normalized\n");
DualQuaternion q = DualQuaternion::rotation(angle, axis);
DualQuaternion q = DualQuaternion::rotation(Deg(120.0f), axis);
CORRADE_COMPARE(q, DualQuaternion({Vector3(0.5f, 0.5f, 0.5f), 0.5f}, {{}, 0.0f}));
CORRADE_COMPARE(q.rotationAngle(), angle);
CORRADE_COMPARE_AS(q.rotationAngle(), Deg(120.0f), Deg);
CORRADE_COMPARE(q.rotationAxis(), axis);
}
@ -190,21 +191,21 @@ void DualQuaternionTest::translation() {
void DualQuaternionTest::combinedTransformParts() {
Vector3 translation = Vector3(-1.0f, 2.0f, 3.0f);
DualQuaternion a = DualQuaternion::translation(translation)*DualQuaternion::rotation(deg(23.0f), Vector3::xAxis());
DualQuaternion b = DualQuaternion::rotation(deg(23.0f), Vector3::xAxis())*DualQuaternion::translation(translation);
DualQuaternion a = DualQuaternion::translation(translation)*DualQuaternion::rotation(Deg(23.0f), Vector3::xAxis());
DualQuaternion b = DualQuaternion::rotation(Deg(23.0f), Vector3::xAxis())*DualQuaternion::translation(translation);
CORRADE_COMPARE(a.rotationAxis(), Vector3::xAxis());
CORRADE_COMPARE(b.rotationAxis(), Vector3::xAxis());
CORRADE_COMPARE(a.rotationAngle(), deg(23.0f));
CORRADE_COMPARE(b.rotationAngle(), deg(23.0f));
CORRADE_COMPARE_AS(a.rotationAngle(), Deg(23.0f), Rad);
CORRADE_COMPARE_AS(b.rotationAngle(), Deg(23.0f), Rad);
CORRADE_COMPARE(a.translation(), translation);
CORRADE_COMPARE(b.translation(), Quaternion::rotation(deg(23.0f), Vector3::xAxis()).rotateVectorNormalized(translation));
CORRADE_COMPARE(b.translation(), Quaternion::rotation(Deg(23.0f), Vector3::xAxis()).rotateVectorNormalized(translation));
}
void DualQuaternionTest::matrix() {
DualQuaternion q = DualQuaternion::rotation(deg(23.0f), Vector3::xAxis())*DualQuaternion::translation({-1.0f, 2.0f, 3.0f});
Matrix4 m = Matrix4::rotationX(deg(23.0f))*Matrix4::translation({-1.0f, 2.0f, 3.0f});
DualQuaternion q = DualQuaternion::rotation(Deg(23.0f), Vector3::xAxis())*DualQuaternion::translation({-1.0f, 2.0f, 3.0f});
Matrix4 m = Matrix4::rotationX(Deg(23.0f))*Matrix4::translation({-1.0f, 2.0f, 3.0f});
/* Verify that negated dual quaternion gives the same transformation */
CORRADE_COMPARE(q.matrix(), m);
@ -212,10 +213,10 @@ void DualQuaternionTest::matrix() {
}
void DualQuaternionTest::transformPoint() {
DualQuaternion a = DualQuaternion::translation({-1.0f, 2.0f, 3.0f})*DualQuaternion::rotation(deg(23.0f), Vector3::xAxis());
DualQuaternion b = DualQuaternion::rotation(deg(23.0f), Vector3::xAxis())*DualQuaternion::translation({-1.0f, 2.0f, 3.0f});
Matrix4 m = Matrix4::translation({-1.0f, 2.0f, 3.0f})*Matrix4::rotationX(deg(23.0f));
Matrix4 n = Matrix4::rotationX(deg(23.0f))*Matrix4::translation({-1.0f, 2.0f, 3.0f});
DualQuaternion a = DualQuaternion::translation({-1.0f, 2.0f, 3.0f})*DualQuaternion::rotation(Deg(23.0f), Vector3::xAxis());
DualQuaternion b = DualQuaternion::rotation(Deg(23.0f), Vector3::xAxis())*DualQuaternion::translation({-1.0f, 2.0f, 3.0f});
Matrix4 m = Matrix4::translation({-1.0f, 2.0f, 3.0f})*Matrix4::rotationX(Deg(23.0f));
Matrix4 n = Matrix4::rotationX(Deg(23.0f))*Matrix4::translation({-1.0f, 2.0f, 3.0f});
Vector3 v(0.0f, -3.6f, 0.7f);
Vector3 transformedA = (a*Dual(2)).transformPoint(v);
@ -228,10 +229,10 @@ void DualQuaternionTest::transformPoint() {
}
void DualQuaternionTest::transformPointNormalized() {
DualQuaternion a = DualQuaternion::translation({-1.0f, 2.0f, 3.0f})*DualQuaternion::rotation(deg(23.0f), Vector3::xAxis());
DualQuaternion b = DualQuaternion::rotation(deg(23.0f), Vector3::xAxis())*DualQuaternion::translation({-1.0f, 2.0f, 3.0f});
Matrix4 m = Matrix4::translation({-1.0f, 2.0f, 3.0f})*Matrix4::rotationX(deg(23.0f));
Matrix4 n = Matrix4::rotationX(deg(23.0f))*Matrix4::translation({-1.0f, 2.0f, 3.0f});
DualQuaternion a = DualQuaternion::translation({-1.0f, 2.0f, 3.0f})*DualQuaternion::rotation(Deg(23.0f), Vector3::xAxis());
DualQuaternion b = DualQuaternion::rotation(Deg(23.0f), Vector3::xAxis())*DualQuaternion::translation({-1.0f, 2.0f, 3.0f});
Matrix4 m = Matrix4::translation({-1.0f, 2.0f, 3.0f})*Matrix4::rotationX(Deg(23.0f));
Matrix4 n = Matrix4::rotationX(Deg(23.0f))*Matrix4::translation({-1.0f, 2.0f, 3.0f});
Vector3 v(0.0f, -3.6f, 0.7f);
std::ostringstream o;

48
src/Math/Test/QuaternionTest.cpp

@ -58,6 +58,8 @@ class QuaternionTest: public Corrade::TestSuite::Tester {
void debug();
};
typedef Math::Deg<float> Deg;
typedef Math::Rad<float> Rad;
typedef Math::Matrix<3, float> Matrix3;
typedef Math::Matrix4<float> Matrix4;
typedef Math::Quaternion<float> Quaternion;
@ -227,48 +229,48 @@ void QuaternionTest::rotation() {
std::ostringstream o;
Error::setOutput(&o);
float angle = deg(120.0f);
Vector3 axis(1.0f/Constants<float>::sqrt3());
CORRADE_COMPARE(Quaternion::rotation(deg(-74.0f), {-1.0f, 2.0f, 2.0f}), Quaternion());
CORRADE_COMPARE(Quaternion::rotation(Deg(-74.0f), {-1.0f, 2.0f, 2.0f}), Quaternion());
CORRADE_COMPARE(o.str(), "Math::Quaternion::rotation(): axis must be normalized\n");
Quaternion q = Quaternion::rotation(angle, axis);
Quaternion q = Quaternion::rotation(Deg(120.0f), axis);
CORRADE_COMPARE(q, Quaternion(Vector3(0.5f, 0.5f, 0.5f), 0.5f));
CORRADE_COMPARE(q.rotationAngle(), angle);
CORRADE_COMPARE_AS(q.rotationAngle(), Deg(120.0f), Deg);
CORRADE_COMPARE(q.rotationAxis(), axis);
CORRADE_COMPARE(q.rotationAxis().length(), 1.0f);
/* Verify negative angle */
Quaternion q2 = Quaternion::rotation(deg(-120.0f), axis);
Quaternion q2 = Quaternion::rotation(Deg(-120.0f), axis);
CORRADE_COMPARE(q2, Quaternion(Vector3(-0.5f, -0.5f, -0.5f), 0.5f));
CORRADE_COMPARE(q2.rotationAngle(), deg(120.0f));
CORRADE_COMPARE_AS(q2.rotationAngle(), Deg(120.0f), Deg);
CORRADE_COMPARE(q2.rotationAxis(), -axis);
/* Default-constructed quaternion has zero angle and NaN axis */
CORRADE_COMPARE(Quaternion().rotationAngle(), deg(0.0f));
CORRADE_COMPARE_AS(Quaternion().rotationAngle(), Deg(0.0f), Deg);
CORRADE_VERIFY(Quaternion().rotationAxis() != Quaternion().rotationAxis());
}
void QuaternionTest::angle() {
std::ostringstream o;
Corrade::Utility::Error::setOutput(&o);
CORRADE_COMPARE(Quaternion::angle(Quaternion({1.0f, 2.0f, -3.0f}, -4.0f).normalized(), {{4.0f, -3.0f, 2.0f}, -1.0f}),
std::numeric_limits<Vector3::Type>::quiet_NaN());
auto angle = Quaternion::angle(Quaternion({1.0f, 2.0f, -3.0f}, -4.0f).normalized(), {{4.0f, -3.0f, 2.0f}, -1.0f});
CORRADE_VERIFY(angle != angle);
CORRADE_COMPARE(o.str(), "Math::Quaternion::angle(): quaternions must be normalized\n");
o.str("");
CORRADE_COMPARE(Quaternion::angle({{1.0f, 2.0f, -3.0f}, -4.0f}, Quaternion({4.0f, -3.0f, 2.0f}, -1.0f).normalized()),
std::numeric_limits<Vector3::Type>::quiet_NaN());
angle = Quaternion::angle({{1.0f, 2.0f, -3.0f}, -4.0f}, Quaternion({4.0f, -3.0f, 2.0f}, -1.0f).normalized());
CORRADE_VERIFY(angle != angle);
CORRADE_COMPARE(o.str(), "Math::Quaternion::angle(): quaternions must be normalized\n");
CORRADE_COMPARE(Quaternion::angle(Quaternion({1.0f, 2.0f, -3.0f}, -4.0f).normalized(), Quaternion({4.0f, -3.0f, 2.0f}, -1.0f).normalized()),
rad(1.704528f));
CORRADE_COMPARE(Quaternion::angle(Quaternion({1.0f, 2.0f, -3.0f}, -4.0f).normalized(),
Quaternion({4.0f, -3.0f, 2.0f}, -1.0f).normalized()),
Rad(1.704528f));
}
void QuaternionTest::matrix() {
Quaternion q = Quaternion::rotation(deg(37.0f), Vector3(1.0f/Constants<float>::sqrt3()));
Matrix3 m = Matrix4::rotation(deg(37.0f), Vector3(1.0f/Constants<float>::sqrt3())).rotationScaling();
Quaternion q = Quaternion::rotation(Deg(37.0f), Vector3(1.0f/Constants<float>::sqrt3()));
Matrix3 m = Matrix4::rotation(Deg(37.0f), Vector3(1.0f/Constants<float>::sqrt3())).rotationScaling();
/* Verify that negated quaternion gives the same rotation */
CORRADE_COMPARE(q.matrix(), m);
@ -276,8 +278,8 @@ void QuaternionTest::matrix() {
}
void QuaternionTest::lerp() {
Quaternion a = Quaternion::rotation(deg(15.0f), Vector3(1.0f/Constants<float>::sqrt3()));
Quaternion b = Quaternion::rotation(deg(23.0f), Vector3::xAxis());
Quaternion a = Quaternion::rotation(Deg(15.0f), Vector3(1.0f/Constants<float>::sqrt3()));
Quaternion b = Quaternion::rotation(Deg(23.0f), Vector3::xAxis());
std::ostringstream o;
Corrade::Utility::Error::setOutput(&o);
@ -298,8 +300,8 @@ void QuaternionTest::lerp() {
}
void QuaternionTest::slerp() {
Quaternion a = Quaternion::rotation(deg(15.0f), Vector3(1.0f/Constants<float>::sqrt3()));
Quaternion b = Quaternion::rotation(deg(23.0f), Vector3::xAxis());
Quaternion a = Quaternion::rotation(Deg(15.0f), Vector3(1.0f/Constants<float>::sqrt3()));
Quaternion b = Quaternion::rotation(Deg(23.0f), Vector3::xAxis());
std::ostringstream o;
Corrade::Utility::Error::setOutput(&o);
@ -320,8 +322,8 @@ void QuaternionTest::slerp() {
}
void QuaternionTest::rotateVector() {
Quaternion a = Quaternion::rotation(deg(23.0f), Vector3::xAxis());
Matrix4 m = Matrix4::rotationX(deg(23.0f));
Quaternion a = Quaternion::rotation(Deg(23.0f), Vector3::xAxis());
Matrix4 m = Matrix4::rotationX(Deg(23.0f));
Vector3 v(5.0f, -3.6f, 0.7f);
Vector3 rotated = a.rotateVector(v);
@ -330,8 +332,8 @@ void QuaternionTest::rotateVector() {
}
void QuaternionTest::rotateVectorNormalized() {
Quaternion a = Quaternion::rotation(deg(23.0f), Vector3::xAxis());
Matrix4 m = Matrix4::rotationX(deg(23.0f));
Quaternion a = Quaternion::rotation(Deg(23.0f), Vector3::xAxis());
Matrix4 m = Matrix4::rotationX(Deg(23.0f));
Vector3 v(5.0f, -3.6f, 0.7f);
std::ostringstream o;

Loading…
Cancel
Save