void QuatOpsTest::testQuatVectorSub() { // test out mult( result, quat, quat ) const float eps = 0.0001f; gmtl::Quat<float> q3( 1, 2, 3, 4 ), q5, q6( 2, 3, 4, 5 ); gmtl::sub( q5, q3, q6 ); gmtl::Quat<float> expected_result1( -1, -1, -1, -1 ); CPPUNIT_ASSERT( gmtl::isEqual( expected_result1, q5, eps ) ); }
void QuatOpsTest::testQuatVectorMult() { // test out mult( result, quat, quat ) const float eps = 0.0001f; gmtl::Quat<float> q3( 1, 2, 3, 4 ), q5; gmtl::mult( q5, q3, 23.0f ); gmtl::Quat<float> expected_result1( 1 * 23.0f, 2 * 23.0f, 3 * 23.0f, 4 * 23.0f ); CPPUNIT_ASSERT( gmtl::isEqual( expected_result1, q5, eps ) ); }
void QuatOpsTest::testQuatConj() { const float eps = 0.0001f; gmtl::Quat<float> q3( 0,0,342334,0 ), q5( 342334,-342334,342334,-342334 ); gmtl::conj( q3 ); gmtl::conj( q5 ); gmtl::Quat<float> expected_result1( 0, 0, -342334, 0 ), expected_result2( -342334,342334,-342334,-342334 ); CPPUNIT_ASSERT( gmtl::isEqual( expected_result1, q3, eps ) ); CPPUNIT_ASSERT( gmtl::isEqual( expected_result2, q5, eps ) ); }
void QuatOpsTest::testQuatNormalize() { const float eps = 0.0001f; gmtl::Quat<float> q3( 0,0,342334,0 ), q5( 342334,-342334,342334,-342334 ); gmtl::normalize( q3 ); gmtl::normalize( q5 ); gmtl::Quat<float> expected_result1( 0, 0, 1, 0 ), expected_result2( 0.5, -0.5, 0.5, -0.5 ); CPPUNIT_ASSERT( gmtl::isEqual( expected_result1, q3, eps ) ); CPPUNIT_ASSERT( gmtl::isEqual( expected_result2, q5, eps ) ); CPPUNIT_ASSERT( gmtl::isNormalized( expected_result1 ) ); CPPUNIT_ASSERT( gmtl::isNormalized( expected_result2 ) ); }
void QuatOpsTest::testQuatLerp() { const float eps = 0.0001f; gmtl::Quat<float> q1( 1, 2, 3, 4 ), q2( 9, 8, 7, 6 ); gmtl::normalize( q1 ); // make sure they are valid rotation quaternions gmtl::normalize( q2 ); gmtl::Quat<float> expected_result1( q1 ), res1; gmtl::Quat<float> expected_result2( q2 ), res2; gmtl::lerp( res1, 0.0f, q1, q2 ); gmtl::lerp( res2, 1.0f, q1, q2 ); CPPUNIT_ASSERT( gmtl::isEqual( expected_result1, res1, eps ) ); CPPUNIT_ASSERT( gmtl::isEqual( expected_result2, res2, eps ) ); /// @todo, test interpolated values... }
void QuatOpsTest::testQuatNegate() { const float eps = 0.0001f; gmtl::Quat<float> q3( 0,0,342334,0 ), q5( 342334,-342334,342334,-342334 ); gmtl::Quat<float> expected_result1( 0, 0, -342334, 0 ), expected_result2( -342334,342334,-342334,342334 ); // test operator- CPPUNIT_ASSERT( gmtl::isEqual( expected_result1, -q3, eps ) ); CPPUNIT_ASSERT( gmtl::isEqual( expected_result2, -q5, eps ) ); // test negate(quat) gmtl::negate( q3 ); gmtl::negate( q5 ); CPPUNIT_ASSERT( gmtl::isEqual( expected_result1, q3, eps ) ); CPPUNIT_ASSERT( gmtl::isEqual( expected_result2, q5, eps ) ); }
void QuatGenTest::testQuatMakeRot() { const float eps = 0.0001f; gmtl::Quat<float> q1, q2; q1 = gmtl::make<gmtl::Quat<float> >( gmtl::AxisAnglef( gmtl::Math::deg2Rad( 90.0f ), 1.0f, 0.0f, 0.0f ) ); q2 = gmtl::make<gmtl::Quat<float> >( gmtl::AxisAnglef( gmtl::Math::deg2Rad( 32.0f ), 0.0f, 1.0f, 0.0f ) ); gmtl::Quat<float> expected_result1( 0.707107f, 0, 0, 0.707107f ); gmtl::Quat<float> expected_result2( 0, 0.275637f, 0, 0.961262f ); CPPUNIT_ASSERT( gmtl::isEqual( expected_result1, q1, eps ) ); CPPUNIT_ASSERT( gmtl::isEqual( expected_result2, q2, eps ) ); CPPUNIT_ASSERT( gmtl::isNormalized( q1, eps ) ); CPPUNIT_ASSERT( gmtl::isNormalized( q2, eps ) ); // values from VR Juggler math lib... std::vector< gmtl::Quat<float> > quats; quats.push_back( gmtl::Quat<float>( 0, 0, 0, -1 ) ); quats.push_back( gmtl::Quat<float>( -0, -0.173648f, -0, -0.984808f) ); quats.push_back( gmtl::Quat<float>( -0, -0.34202f, -0, -0.939693f ) ); quats.push_back( gmtl::Quat<float>( -0, -0.5f, -0, -0.866025f ) ); quats.push_back( gmtl::Quat<float>( -0, -0.642788f, -0, -0.766044f) ); quats.push_back( gmtl::Quat<float>( -0, -0.766044f, -0, -0.642788f) ); quats.push_back( gmtl::Quat<float>( -0, -0.866025f, -0, -0.5f ) ); quats.push_back( gmtl::Quat<float>( -0, -0.939693f, -0, -0.34202f ) ); quats.push_back( gmtl::Quat<float>( -0, -0.984808f, -0, -0.173648f) ); quats.push_back( gmtl::Quat<float>( -0, -1, -0, 0 ) ); quats.push_back( gmtl::Quat<float>( -0, -0.984808f, -0, 0.173648f ) ); quats.push_back( gmtl::Quat<float>( -0, -0.939693f, -0, 0.34202f ) ); quats.push_back( gmtl::Quat<float>( -0, -0.866025f, -0, 0.5f ) ); quats.push_back( gmtl::Quat<float>( -0, -0.766044f, -0, 0.642788f ) ); quats.push_back( gmtl::Quat<float>( -0, -0.642788f, -0, 0.766044f ) ); quats.push_back( gmtl::Quat<float>( -0, -0.5f, -0, 0.866025f ) ); quats.push_back( gmtl::Quat<float>( -0, -0.34202f, -0, 0.939693f ) ); quats.push_back( gmtl::Quat<float>( -0, -0.173648f, -0, 0.984808f ) ); quats.push_back( gmtl::Quat<float>( 0, 0, 0, 1 ) ); quats.push_back( gmtl::Quat<float>( 0, 0.173648f, 0, 0.984808f ) ); quats.push_back( gmtl::Quat<float>( 0, 0.34202f, 0, 0.939693f ) ); quats.push_back( gmtl::Quat<float>( 0, 0.5f, 0, 0.866025f ) ); quats.push_back( gmtl::Quat<float>( 0, 0.642788f, 0, 0.766044f ) ); quats.push_back( gmtl::Quat<float>( 0, 0.766044f, 0, 0.642788f ) ); quats.push_back( gmtl::Quat<float>( 0, 0.866025f, 0, 0.5f ) ); quats.push_back( gmtl::Quat<float>( 0, 0.939693f, 0, 0.34202f ) ); quats.push_back( gmtl::Quat<float>( 0, 0.984808f, 0, 0.173648f ) ); quats.push_back( gmtl::Quat<float>( 0, 1, 0, 0 ) ); quats.push_back( gmtl::Quat<float>( 0, 0.984808f, 0, -0.173648f ) ); quats.push_back( gmtl::Quat<float>( 0, 0.939693f, 0, -0.34202f ) ); quats.push_back( gmtl::Quat<float>( 0, 0.866025f, 0, -0.5f ) ); quats.push_back( gmtl::Quat<float>( 0, 0.766044f, 0, -0.642788f ) ); quats.push_back( gmtl::Quat<float>( 0, 0.642788f, 0, -0.766044f ) ); quats.push_back( gmtl::Quat<float>( 0, 0.5f, 0, -0.866025f ) ); quats.push_back( gmtl::Quat<float>( 0, 0.34202f, 0, -0.939693f ) ); quats.push_back( gmtl::Quat<float>( 0, 0.173648f, 0, -0.984808f ) ); quats.push_back( gmtl::Quat<float>( -0, 0, -0, -1 ) ); /// @todo check this against another math lib other than VR Juggler... int count = 0; for (int x = -360; x <= 360; x += 20) { gmtl::Quat<float> q3; CPPUNIT_ASSERT( count >= 0 ); gmtl::set( q2, gmtl::AxisAnglef( gmtl::Math::deg2Rad( float(x) ), 0.0f, 1.0f, 0.0f ) ); gmtl::set( q3, gmtl::AxisAnglef( gmtl::Math::deg2Rad( float(x) ), gmtl::Vec3f( 0.0f, 1.0f, 0.0f ) ) ); CPPUNIT_ASSERT( gmtl::isEqual( quats[count], q2, eps ) ); CPPUNIT_ASSERT( gmtl::isEqual( q3, q2, eps ) ); // make sure that makeRot and setRot do the same thing... CPPUNIT_ASSERT( gmtl::make<gmtl::Quat<float> >( gmtl::AxisAnglef( gmtl::Math::deg2Rad( float(x) ), 0.0f, 1.0f, 0.0f ) ) == q2 ); CPPUNIT_ASSERT( gmtl::make<gmtl::Quat<float> >( gmtl::AxisAnglef( gmtl::Math::deg2Rad( float(x) ), gmtl::Vec3f( 0.0f, 1.0f, 0.0f ) ) ) == q3 ); count++; } }
void QuatOpsTest::testQuatSlerp() { const float eps = 0.0001f; gmtl::Quat<float> q1( 100, 2, 3, 4 ), q2( 9.01f, 8.4f, 7.1f, 6 ); gmtl::normalize( q1 ); // make sure they are valid rotation quaternions gmtl::normalize( q2 ); gmtl::Quat<float> expected_result1( q1 ), res1; gmtl::Quat<float> expected_result2( q2 ), res2; gmtl::slerp( res1, 0.0f, q1, q2 ); gmtl::slerp( res2, 1.0f, q1, q2 ); CPPUNIT_ASSERT( gmtl::isEqual( expected_result1, res1, eps ) ); CPPUNIT_ASSERT( gmtl::isEqual( expected_result2, res2, eps ) ); /// test interpolated values... gmtl::Vec3f quadrant[8]; quadrant[0].set( 1.0f, 1.0f, 1.0f ); quadrant[1].set( -1.0f, 1.0f, 1.0f ); quadrant[2].set( -1.0f, 1.0f, -1.0f ); quadrant[3].set( 1.0f, 1.0f, -1.0f ); quadrant[4].set( 1.0f, -1.0f, -1.0f ); quadrant[5].set( 1.0f, -1.0f, 1.0f ); quadrant[6].set( -1.0f, -1.0f, 1.0f ); quadrant[7].set( -1.0f, -1.0f, -1.0f ); //gmtl::Quatf expected_result0, expected_result180, expected_result90, expected_result_0001; // create one quat for each of the 8 quadrants... gmtl::Quatf q0[8], q180[8], q90[8], q_0001[8]; for (unsigned int x = 0; x < 8; ++x) { gmtl::normalize( quadrant[x] ); gmtl::setRot( q0[x], gmtl::AxisAnglef( gmtl::Math::deg2Rad( 0.0f ), quadrant[x] ) ); gmtl::setRot( q180[x], gmtl::AxisAnglef( gmtl::Math::deg2Rad( 180.0f ), quadrant[x] ) ); gmtl::setRot( q90[x], gmtl::AxisAnglef( gmtl::Math::deg2Rad( 90.0f ), quadrant[x] ) ); gmtl::setRot( q_0001[x], gmtl::AxisAnglef( gmtl::Math::deg2Rad( 0.0001f ), quadrant[x] ) ); /// @todo test these: // same yields same // gmtl::slerp( result, 0.0f, q0[x], q0[x] ); // yields q0 // gmtl::slerp( result, 0.5f, q0[x], q0[x] ); // yields q0 // gmtl::slerp( result, 1.0f, q0[x], q0[x] ); // yields q0 // 180 deg - there is more than one valid path to take, // gmtl::slerp( result, 0.0f, q0[x], q180[x] ); // yields q0 // gmtl::slerp( result, 0.5f, q0[x], q180[x] ); // not sure what to test here... // gmtl::slerp( result, 1.0f, q0[x], q180[x] ); // yields q180 // 90 deg // gmtl::slerp( result, 0.0f, q0[x], q90[x] ); // yields q0 // gmtl::slerp( result, 0.5f, q0[x], q90[x] ); // yields shortest path // gmtl::slerp( result, 1.0f, q0[x], q90[x] ); // yields q90 // .0001 deg // gmtl::slerp( result, 0.0f, q0[x], q_0001[x] ); // yields q0 // gmtl::slerp( result, 0.5f, q0[x], q_0001[x] ); // yields shortest path (very close to q0 or q_0001) // gmtl::slerp( result, 1.0f, q0[x], q_0001[x] ); // yields q_0001 } /// @todo given 8 quadrants, (8 quats), test each quat against every other quat (56 total checks) // note: might have to test with two different angled quats, not sure... }