Browse Source

Math: properly test also (s)lerpShortestPath() assertions.

And boom, there was a bug.
pull/284/head
Vladimír Vondruš 8 years ago
parent
commit
dfcd33ffe8
  1. 2
      src/Magnum/Math/Quaternion.h
  2. 105
      src/Magnum/Math/Test/QuaternionTest.cpp

2
src/Magnum/Math/Quaternion.h

@ -203,7 +203,7 @@ otherwise, the interpolation is performed as: @f[
*/
template<class T> inline Quaternion<T> slerpShortestPath(const Quaternion<T>& normalizedA, const Quaternion<T>& normalizedB, T t) {
CORRADE_ASSERT(normalizedA.isNormalized() && normalizedB.isNormalized(),
"Math::slerp(): quaternions must be normalized", {});
"Math::slerpShortestPath(): quaternions must be normalized", {});
const T cosHalfAngle = dot(normalizedA, normalizedB);
/* Avoid division by zero */

105
src/Magnum/Math/Test/QuaternionTest.cpp

@ -91,13 +91,15 @@ struct QuaternionTest: Corrade::TestSuite::Tester {
void matrix();
void lerp();
void lerpShortestPath();
void lerp2D();
void lerpNotNormalized();
void lerpShortestPath();
void lerpShortestPathNotNormalized();
void slerp();
void slerpShortestPath();
void slerp2D();
void slerpNotNormalized();
void slerpShortestPath();
void slerpShortestPathNotNormalized();
void transformVector();
void transformVectorNormalized();
@ -156,13 +158,15 @@ QuaternionTest::QuaternionTest() {
&QuaternionTest::matrix,
&QuaternionTest::lerp,
&QuaternionTest::lerpShortestPath,
&QuaternionTest::lerp2D,
&QuaternionTest::lerpNotNormalized,
&QuaternionTest::lerpShortestPath,
&QuaternionTest::lerpShortestPathNotNormalized,
&QuaternionTest::slerp,
&QuaternionTest::slerpShortestPath,
&QuaternionTest::slerp2D,
&QuaternionTest::slerpNotNormalized,
&QuaternionTest::slerpShortestPath,
&QuaternionTest::slerpShortestPathNotNormalized,
&QuaternionTest::transformVector,
&QuaternionTest::transformVectorNormalized,
@ -501,24 +505,6 @@ void QuaternionTest::lerp() {
CORRADE_COMPARE(lerpShortestPath, expected);
}
void QuaternionTest::lerpShortestPath() {
Quaternion a = Quaternion::rotation(0.0_degf, Vector3::zAxis());
Quaternion b = Quaternion::rotation(225.0_degf, Vector3::zAxis());
Quaternion slerp = Math::lerp(a, b, 0.25f);
Quaternion slerpShortestPath = Math::lerpShortestPath(a, b, 0.25f);
CORRADE_VERIFY(slerp.isNormalized());
CORRADE_VERIFY(slerpShortestPath.isNormalized());
CORRADE_COMPARE(slerp.axis(), Vector3::zAxis());
CORRADE_COMPARE(slerpShortestPath.axis(), Vector3::zAxis());
CORRADE_COMPARE(slerp.angle(), 38.8848_degf);
CORRADE_COMPARE(slerpShortestPath.angle(), 329.448_degf);
CORRADE_COMPARE(slerp, (Quaternion{{0.0f, 0.0f, 0.332859f}, 0.942977f}));
CORRADE_COMPARE(slerpShortestPath, (Quaternion{{0.0f, 0.0f, 0.26347f}, -0.964667f}));
}
void QuaternionTest::lerp2D() {
/* Results should be consistent with ComplexTest::lerp() */
Quaternion a = Quaternion::rotation(15.0_degf, Vector3::zAxis());
@ -542,6 +528,37 @@ void QuaternionTest::lerpNotNormalized() {
"Math::lerp(): quaternions must be normalized\n");
}
void QuaternionTest::lerpShortestPath() {
Quaternion a = Quaternion::rotation(0.0_degf, Vector3::zAxis());
Quaternion b = Quaternion::rotation(225.0_degf, Vector3::zAxis());
Quaternion lerp = Math::lerp(a, b, 0.25f);
Quaternion lerpShortestPath = Math::lerpShortestPath(a, b, 0.25f);
CORRADE_VERIFY(lerp.isNormalized());
CORRADE_VERIFY(lerpShortestPath.isNormalized());
CORRADE_COMPARE(lerp.axis(), Vector3::zAxis());
CORRADE_COMPARE(lerpShortestPath.axis(), Vector3::zAxis());
CORRADE_COMPARE(lerp.angle(), 38.8848_degf);
CORRADE_COMPARE(lerpShortestPath.angle(), 329.448_degf);
CORRADE_COMPARE(lerp, (Quaternion{{0.0f, 0.0f, 0.332859f}, 0.942977f}));
CORRADE_COMPARE(lerpShortestPath, (Quaternion{{0.0f, 0.0f, 0.26347f}, -0.964667f}));
}
void QuaternionTest::lerpShortestPathNotNormalized() {
std::ostringstream out;
Error redirectError{&out};
Quaternion a;
Math::lerpShortestPath(a*3.0f, a, 0.35f);
Math::lerpShortestPath(a, a*-3.0f, 0.35f);
/* lerpShortestPath() is calling lerp(), so the message is from there */
CORRADE_COMPARE(out.str(),
"Math::lerp(): quaternions must be normalized\n"
"Math::lerp(): quaternions must be normalized\n");
}
void QuaternionTest::slerp() {
Quaternion a = Quaternion::rotation(15.0_degf, Vector3(1.0f/Constants<Float>::sqrt3()));
Quaternion b = Quaternion::rotation(23.0_degf, Vector3::xAxis());
@ -563,6 +580,29 @@ void QuaternionTest::slerp() {
CORRADE_COMPARE(Math::slerpShortestPath(a, -a, 0.25f), a);
}
void QuaternionTest::slerp2D() {
/* Result angle should be equivalent to ComplexTest::slerp() */
Quaternion a = Quaternion::rotation(15.0_degf, Vector3::zAxis());
Quaternion b = Quaternion::rotation(57.0_degf, Vector3::zAxis());
Quaternion slerp = Math::slerp(a, b, 0.35f);
CORRADE_VERIFY(slerp.isNormalized());
CORRADE_COMPARE(slerp.angle(), 29.7_degf); /* 15 + (57-15)*0.35 */
CORRADE_COMPARE(slerp, (Quaternion{{0.0f, 0.0f, 0.256289f}, 0.9666f}));
}
void QuaternionTest::slerpNotNormalized() {
std::ostringstream out;
Error redirectError{&out};
Quaternion a;
Math::slerp(a*3.0f, a, 0.35f);
Math::slerp(a, a*-3.0f, 0.35f);
CORRADE_COMPARE(out.str(),
"Math::slerp(): quaternions must be normalized\n"
"Math::slerp(): quaternions must be normalized\n");
}
void QuaternionTest::slerpShortestPath() {
Quaternion a = Quaternion::rotation(0.0_degf, Vector3::zAxis());
Quaternion b = Quaternion::rotation(225.0_degf, Vector3::zAxis());
@ -581,27 +621,16 @@ void QuaternionTest::slerpShortestPath() {
CORRADE_COMPARE(slerpShortestPath, (Quaternion{{0.0f, 0.0f, 0.290285f}, -0.95694f}));
}
void QuaternionTest::slerp2D() {
/* Result angle should be equivalent to ComplexTest::slerp() */
Quaternion a = Quaternion::rotation(15.0_degf, Vector3::zAxis());
Quaternion b = Quaternion::rotation(57.0_degf, Vector3::zAxis());
Quaternion slerp = Math::slerp(a, b, 0.35f);
CORRADE_VERIFY(slerp.isNormalized());
CORRADE_COMPARE(slerp.angle(), 29.7_degf); /* 15 + (57-15)*0.35 */
CORRADE_COMPARE(slerp, (Quaternion{{0.0f, 0.0f, 0.256289f}, 0.9666f}));
}
void QuaternionTest::slerpNotNormalized() {
void QuaternionTest::slerpShortestPathNotNormalized() {
std::ostringstream out;
Error redirectError{&out};
Quaternion a;
Math::slerp(a*3.0f, a, 0.35f);
Math::slerp(a, a*-3.0f, 0.35f);
Math::slerpShortestPath(a*3.0f, a, 0.35f);
Math::slerpShortestPath(a, a*-3.0f, 0.35f);
CORRADE_COMPARE(out.str(),
"Math::slerp(): quaternions must be normalized\n"
"Math::slerp(): quaternions must be normalized\n");
"Math::slerpShortestPath(): quaternions must be normalized\n"
"Math::slerpShortestPath(): quaternions must be normalized\n");
}
void QuaternionTest::transformVector() {

Loading…
Cancel
Save