/******************************************************************************** * ReactPhysics3D physics library, http://www.reactphysics3d.com * * Copyright (c) 2010-2016 Daniel Chappuis * ********************************************************************************* * * * This software is provided 'as-is', without any express or implied warranty. * * In no event will the authors be held liable for any damages arising from the * * use of this software. * * * * Permission is granted to anyone to use this software for any purpose, * * including commercial applications, and to alter it and redistribute it * * freely, subject to the following restrictions: * * * * 1. The origin of this software must not be misrepresented; you must not claim * * that you wrote the original software. If you use this software in a * * product, an acknowledgment in the product documentation would be * * appreciated but is not required. * * * * 2. Altered source versions must be plainly marked as such, and must not be * * misrepresented as being the original software. * * * * 3. This notice may not be removed or altered from any source distribution. * * * ********************************************************************************/ #ifndef TEST_TRANSFORM_H #define TEST_TRANSFORM_H // Libraries #include "Test.h" #include "mathematics/Transform.h" #include "mathematics/Matrix3x3.h" /// Reactphysics3D namespace namespace reactphysics3d { // Class TestTransform /** * Unit test for the Transform class */ class TestTransform : public Test { private : // ---------- Atributes ---------- // /// Identity transform Transform mIdentityTransform; /// First example transform Transform mTransform1; /// Second example transform Transform mTransform2; public : // ---------- Methods ---------- // /// Constructor TestTransform(const std::string& name) : Test(name) { mIdentityTransform.setToIdentity(); Vector3 unitVec(1, 1, 1); unitVec.normalize(); decimal sinA = std::sin(PI/8.0f); decimal cosA = std::cos(PI/8.0f); mTransform1 = Transform(Vector3(4, 5, 6), Quaternion(sinA * unitVec, cosA)); decimal sinB = std::sin(PI/3.0f); decimal cosB = std::cos(PI/3.0f); mTransform2 = Transform(Vector3(8, 45, -6), Quaternion(sinB * unitVec, cosB)); } /// Run the tests void run() { testConstructors(); testGetSet(); testInverse(); testGetSetOpenGLMatrix(); testInterpolateTransform(); testIdentity(); testOperators(); } /// Test the constructors void testConstructors() { Transform transform1(Vector3(1, 2, 3), Quaternion(6, 7, 8, 9)); Transform transform2(Vector3(4, 5, 6), Matrix3x3(1, 0, 0, 0, 1, 0, 0, 0, 1)); Transform transform3(transform1); test(transform1.getPosition() == Vector3(1, 2, 3)); test(transform1.getOrientation() == Quaternion(6, 7, 8, 9)); test(transform2.getPosition() == Vector3(4, 5, 6)); test(transform2.getOrientation() == Quaternion::identity()); test(transform3 == transform1); } /// Test getter and setter void testGetSet() { test(mIdentityTransform.getPosition() == Vector3(0, 0, 0)); test(mIdentityTransform.getOrientation() == Quaternion::identity()); Transform transform; transform.setPosition(Vector3(5, 7, 8)); transform.setOrientation(Quaternion(1, 2, 3, 1)); test(transform.getPosition() == Vector3(5, 7, 8)); test(transform.getOrientation() == Quaternion(1, 2, 3, 1)); transform.setToIdentity(); test(transform.getPosition() == Vector3(0, 0, 0)); test(transform.getOrientation() == Quaternion::identity()); } /// Test the inverse void testInverse() { Transform inverseTransform = mTransform1.getInverse(); Vector3 vector(2, 3, 4); Vector3 tempVector = mTransform1 * vector; Vector3 tempVector2 = inverseTransform * tempVector; test(approxEqual(tempVector2.x, vector.x, decimal(10e-6))); test(approxEqual(tempVector2.y, vector.y, decimal(10e-6))); test(approxEqual(tempVector2.z, vector.z, decimal(10e-6))); } /// Test methods to set and get transform matrix from and to OpenGL void testGetSetOpenGLMatrix() { Transform transform; Vector3 position = mTransform1.getPosition(); Matrix3x3 orientation = mTransform1.getOrientation().getMatrix(); decimal openglMatrix[16] = {orientation[0][0], orientation[1][0], orientation[2][0], 0, orientation[0][1], orientation[1][1], orientation[2][1], 0, orientation[0][2], orientation[1][2], orientation[2][2], 0, position.x, position.y, position.z, 1}; transform.setFromOpenGL(openglMatrix); decimal openglMatrix2[16]; transform.getOpenGLMatrix(openglMatrix2); test(approxEqual(openglMatrix2[0], orientation[0][0])); test(approxEqual(openglMatrix2[1], orientation[1][0])); test(approxEqual(openglMatrix2[2], orientation[2][0])); test(approxEqual(openglMatrix2[3], 0)); test(approxEqual(openglMatrix2[4], orientation[0][1])); test(approxEqual(openglMatrix2[5], orientation[1][1])); test(approxEqual(openglMatrix2[6], orientation[2][1])); test(approxEqual(openglMatrix2[7], 0)); test(approxEqual(openglMatrix2[8], orientation[0][2])); test(approxEqual(openglMatrix2[9], orientation[1][2])); test(approxEqual(openglMatrix2[10], orientation[2][2])); test(approxEqual(openglMatrix2[11], 0)); test(approxEqual(openglMatrix2[12], position.x)); test(approxEqual(openglMatrix2[13], position.y)); test(approxEqual(openglMatrix2[14], position.z)); test(approxEqual(openglMatrix2[15], 1)); } /// Test the method to interpolate transforms void testInterpolateTransform() { Transform transformStart = Transform::interpolateTransforms(mTransform1, mTransform2,0); Transform transformEnd = Transform::interpolateTransforms(mTransform1, mTransform2,1); test(transformStart == mTransform1); test(transformEnd == mTransform2); decimal sinA = sin(PI/3.0f); decimal cosA = cos(PI/3.0f); decimal sinB = sin(PI/6.0f); decimal cosB = cos(PI/6.0f); Transform transform1(Vector3(4, 5, 6), Quaternion::identity()); Transform transform2(Vector3(8, 11, 16), Quaternion(sinA, sinA, sinA, cosA)); Transform transform = Transform::interpolateTransforms(transform1, transform2, 0.5); Vector3 position = transform.getPosition(); Quaternion orientation = transform.getOrientation(); test(approxEqual(position.x, 6)); test(approxEqual(position.y, 8)); test(approxEqual(position.z, 11)); test(approxEqual(orientation.x, sinB)); test(approxEqual(orientation.y, sinB)); test(approxEqual(orientation.z, sinB)); test(approxEqual(orientation.w, cosB)); } /// Test the identity methods void testIdentity() { Transform transform = Transform::identity(); test(transform.getPosition() == Vector3(0, 0, 0)); test(transform.getOrientation() == Quaternion::identity()); Transform transform2(Vector3(5, 6, 2), Quaternion(3, 5, 1, 6)); transform2.setToIdentity(); test(transform2.getPosition() == Vector3(0, 0, 0)); test(transform2.getOrientation() == Quaternion::identity()); } /// Test the overloaded operators void testOperators() { // Equality, inequality operator test(mTransform1 == mTransform1); test(mTransform1 != mTransform2); // Assignment operator Transform transform; transform = mTransform1; test(transform == mTransform1); // Multiplication Vector3 vector(7, 53, 5); Vector3 vector2 = mTransform2 * (mTransform1 * vector); Vector3 vector3 = (mTransform2 * mTransform1) * vector; test(approxEqual(vector2.x, vector3.x, decimal(10e-6))); test(approxEqual(vector2.y, vector3.y, decimal(10e-6))); test(approxEqual(vector2.z, vector3.z, decimal(10e-6))); } }; } #endif