reactphysics3d/test/tests/mathematics/TestTransform.h
2018-01-14 10:47:39 +01:00

219 lines
9.6 KiB
C++

/********************************************************************************
* 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"
/// 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