diff --git a/test/main.cpp b/test/main.cpp index 91a2c47e..11139b6f 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -28,18 +28,20 @@ #include "tests/mathematics/TestVector3.h" #include "tests/mathematics/TestTransform.h" #include "tests/mathematics/TestQuaternion.h" +#include "tests/mathematics/TestMatrix3x3.h" using namespace reactphysics3d; int main() { - TestSuite testSuite("ReactPhysics3D tests"); + TestSuite testSuite("ReactPhysics3D Tests"); // ---------- Mathematics tests ---------- // testSuite.addTest(new TestVector3); testSuite.addTest(new TestTransform); testSuite.addTest(new TestQuaternion); + testSuite.addTest(new TestMatrix3x3); // ----------------------------- --------- // diff --git a/test/tests/mathematics/TestMatrix3x3.h b/test/tests/mathematics/TestMatrix3x3.h index 325f9861..ccdda9a9 100644 --- a/test/tests/mathematics/TestMatrix3x3.h +++ b/test/tests/mathematics/TestMatrix3x3.h @@ -51,21 +51,229 @@ class TestMatrix3x3 : public Test { /// Identity transform Matrix3x3 mIdentity; + /// First example matrix + Matrix3x3 mMatrix1; + public : // ---------- Methods ---------- // /// Constructor - TestMatrix3x3() : mIdentity(Matrix3x3::identity()){ + TestMatrix3x3() : mIdentity(Matrix3x3::identity()), + mMatrix1(2, 24, 4, 5, -6, 234, -15, 11, 66) { } /// Run the tests void run() { - + testConstructors(); + testGetSet(); + testIdentity(); + testOthersMethods(); + testOperators(); } + /// Test the constructors + void testConstructors() { + + Matrix3x3 test1(5.0); + Matrix3x3 test2(2, 3, 4, 5, 6, 7, 8, 9, 10); + Matrix3x3 test3(mMatrix1); + test(test1[0][0] == 5); + test(test1[0][1] == 5); + test(test1[0][2] == 5); + test(test1[1][0] == 5); + test(test1[1][1] == 5); + test(test1[1][2] == 5); + test(test1[2][0] == 5); + test(test1[2][1] == 5); + test(test1[2][2] == 5); + + test(test2[0][0] == 2); + test(test2[0][1] == 3); + test(test2[0][2] == 4); + test(test2[1][0] == 5); + test(test2[1][1] == 6); + test(test2[1][2] == 7); + test(test2[2][0] == 8); + test(test2[2][1] == 9); + test(test2[2][2] == 10); + + test(test3 == mMatrix1); + } + + /// Test the getter and setter methods + void testGetSet() { + + // Test method to set all the values + Matrix3x3 test2; + test2.setAllValues(2, 24, 4, 5, -6, 234, -15, 11, 66); + test(test2 == mMatrix1); + + // Test method to set to zero + test2.setToZero(); + test(test2 == Matrix3x3(0, 0, 0, 0, 0, 0, 0, 0, 0)); + + // Test method that returns a column + Vector3 column1 = mMatrix1.getColumn(0); + Vector3 column2 = mMatrix1.getColumn(1); + Vector3 column3 = mMatrix1.getColumn(2); + test(column1 == Vector3(2, 5, -15)); + test(column2 == Vector3(24, -6, 11)); + test(column3 == Vector3(4, 234, 66)); + + // Test method that returns a row + Vector3 row1 = mMatrix1.getRow(0); + Vector3 row2 = mMatrix1.getRow(1); + Vector3 row3 = mMatrix1.getRow(2); + test(row1 == Vector3(2, 24, 4)); + test(row2 == Vector3(5, -6, 234)); + test(row3 == Vector3(-15, 11, 66)); + } + + /// Test the identity methods + void testIdentity() { + + Matrix3x3 identity = Matrix3x3::identity(); + Matrix3x3 test1; + test1.setToIdentity(); + + test(identity[0][0] == 1); + test(identity[0][1] == 0); + test(identity[0][2] == 0); + test(identity[1][0] == 0); + test(identity[1][1] == 1); + test(identity[1][2] == 0); + test(identity[2][0] == 0); + test(identity[2][1] == 0); + test(identity[2][2] == 1); + + test(test1 == Matrix3x3::identity()); + } + + /// Test others methods + void testOthersMethods() { + + // Test transpose + Matrix3x3 transpose = mMatrix1.getTranspose(); + test(transpose == Matrix3x3(2, 5, -15, 24, -6, 11, 4, 234, 66)); + + // Test trace + test(mMatrix1.getTrace() == 62); + test(Matrix3x3::identity().getTrace() == 3); + + // Test determinant + Matrix3x3 matrix(-24, 64, 253, -35, 52, 72, 21, -35, -363); + test(mMatrix1.getDeterminant() == -98240); + test(matrix.getDeterminant() == -290159); + test(mIdentity.getDeterminant() == 1); + + // Test inverse + Matrix3x3 inverseMatrix = matrix.getInverse(); + test(approxEqual(inverseMatrix[0][0], decimal(0.056369), decimal(10e-6))); + test(approxEqual(inverseMatrix[0][1], decimal(-0.049549), decimal(10e-6))); + test(approxEqual(inverseMatrix[0][2], decimal(0.029460), decimal(10e-6))); + test(approxEqual(inverseMatrix[1][0], decimal(0.038575), decimal(10e-6))); + test(approxEqual(inverseMatrix[1][1], decimal(-0.011714), decimal(10e-6))); + test(approxEqual(inverseMatrix[1][2], decimal(0.024562), decimal(10e-6))); + test(approxEqual(inverseMatrix[2][0], decimal(-0.000458), decimal(10e-6))); + test(approxEqual(inverseMatrix[2][1], decimal(-0.001737), decimal(10e-6))); + test(approxEqual(inverseMatrix[2][2], decimal(-0.003419), decimal(10e-6))); + Matrix3x3 inverseMatrix1 = mMatrix1.getInverse(); + test(approxEqual(inverseMatrix1[0][0], decimal(0.030232), decimal(10e-6))); + test(approxEqual(inverseMatrix1[0][1], decimal(0.015676), decimal(10e-6))); + test(approxEqual(inverseMatrix1[0][2], decimal(-0.057410), decimal(10e-6))); + test(approxEqual(inverseMatrix1[1][0], decimal(0.039088), decimal(10e-6))); + test(approxEqual(inverseMatrix1[1][1], decimal(-0.001954), decimal(10e-6))); + test(approxEqual(inverseMatrix1[1][2], decimal(0.004560), decimal(10e-6))); + test(approxEqual(inverseMatrix1[2][0], decimal(0.000356), decimal(10e-6))); + test(approxEqual(inverseMatrix1[2][1], decimal(0.003888), decimal(10e-6))); + test(approxEqual(inverseMatrix1[2][2], decimal(0.001344), decimal(10e-6))); + + // Test absolute matrix + Matrix3x3 matrix2(-2, -3, -4, -5, -6, -7, -8, -9, -10); + test(matrix.getAbsoluteMatrix() == Matrix3x3(24, 64, 253, 35, 52, 72, 21, 35, 363)); + Matrix3x3 absoluteMatrix = matrix2.getAbsoluteMatrix(); + test(absoluteMatrix == Matrix3x3(2, 3, 4, 5, 6, 7, 8, 9, 10)); + } + + /// Test the operators + void testOperators() { + + // Test addition + Matrix3x3 matrix1(2, 3, 4, 5, 6, 7, 8, 9, 10); + Matrix3x3 matrix2(-2, 3, -5, 10, 4, 7, 2, 5, 8); + Matrix3x3 addition1 = matrix1 + matrix2; + Matrix3x3 addition2(matrix1); + addition2 += matrix2; + test(addition1 == Matrix3x3(0, 6, -1, 15, 10, 14, 10, 14, 18)); + test(addition2 == Matrix3x3(0, 6, -1, 15, 10, 14, 10, 14, 18)); + + // Test substraction + Matrix3x3 substraction1 = matrix1 - matrix2; + Matrix3x3 substraction2(matrix1); + substraction2 -= matrix2; + test(substraction1 == Matrix3x3(4, 0, 9, -5, 2, 0, 6, 4, 2)); + test(substraction2 == Matrix3x3(4, 0, 9, -5, 2, 0, 6, 4, 2)); + + // Test negative operator + Matrix3x3 negative = -matrix1; + test(negative == Matrix3x3(-2, -3, -4, -5, -6, -7, -8, -9, -10)); + + // Test multiplication with a number + Matrix3x3 multiplication1 = 3 * matrix1; + Matrix3x3 multiplication2 = matrix1 * 3; + Matrix3x3 multiplication3(matrix1); + multiplication3 *= 3; + test(multiplication1 == Matrix3x3(6, 9, 12, 15, 18, 21, 24, 27, 30)); + test(multiplication2 == Matrix3x3(6, 9, 12, 15, 18, 21, 24, 27, 30)); + test(multiplication3 == Matrix3x3(6, 9, 12, 15, 18, 21, 24, 27, 30)); + + // Test multiplication with a matrix + Matrix3x3 multiplication4 = matrix1 * matrix2; + Matrix3x3 multiplication5 = matrix2 * matrix1; + test(multiplication4 == Matrix3x3(34, 38, 43, 64, 74, 73, 94, 110, 103)); + test(multiplication5 == Matrix3x3(-29, -33, -37, 96, 117, 138, 93, 108, 123)); + + // Test multiplication with a vector + Vector3 vector1(3, -32, 59); + Vector3 vector2(-31, -422, 34); + Vector3 test1 = matrix1 * vector1; + Vector3 test2 = matrix2 * vector2; + test(test1 == Vector3(146, 236, 326)); + test(test2 == Vector3(-1374, -1760, -1900)); + + // Test equality operators + test(Matrix3x3(34, 38, 43, 64, 74, 73, 94, 110, 103) == + Matrix3x3(34, 38, 43, 64, 74, 73, 94, 110, 103)); + test(Matrix3x3(34, 64, 43, 7, -1, 73, 94, 110, 103) != + Matrix3x3(34, 38, 43, 64, 74, 73, 94, 110, 103)); + + // Test operator to read a value + test(mMatrix1[0][0] == 2); + test(mMatrix1[0][1] == 24); + test(mMatrix1[0][2] == 4); + test(mMatrix1[1][0] == 5); + test(mMatrix1[1][1] == -6); + test(mMatrix1[1][2] == 234); + test(mMatrix1[2][0] == -15); + test(mMatrix1[2][1] == 11); + test(mMatrix1[2][2] == 66); + + // Test operator to set a value + Matrix3x3 test3; + test3[0][0] = 2; + test3[0][1] = 24; + test3[0][2] = 4; + test3[1][0] = 5; + test3[1][1] = -6; + test3[1][2] = 234; + test3[2][0] = -15; + test3[2][1] = 11; + test3[2][2] = 66; + test(test3 == mMatrix1); + } }; diff --git a/test/tests/mathematics/TestQuaternion.h b/test/tests/mathematics/TestQuaternion.h index 66ff0266..cc177eca 100644 --- a/test/tests/mathematics/TestQuaternion.h +++ b/test/tests/mathematics/TestQuaternion.h @@ -61,18 +61,25 @@ class TestQuaternion : public Test { /// Constructor TestQuaternion() : mIdentity(Quaternion::identity()) { - decimal sinA = sin(PI/8.0f); - decimal cosA = cos(PI/8.0f); - mQuaternion1 = Quaternion(sinA, sinA, sinA, cosA); + decimal sinA = sin(decimal(PI/8.0)); + decimal cosA = cos(decimal(PI/8.0)); + Vector3 vector(2, 3, 4); + vector.normalize(); + mQuaternion1 = Quaternion(vector.x * sinA, vector.y * sinA, vector.z * sinA, cosA); + mQuaternion1.normalize(); } /// Run the tests void run() { testConstructors(); + testUnitLengthNormalize(); + testOthersMethods(); + testOperators(); } /// Test the constructors void testConstructors() { + Quaternion quaternion1(mQuaternion1); test(mQuaternion1== quaternion1); @@ -80,21 +87,144 @@ class TestQuaternion : public Test { test(quaternion2 == Quaternion(4, 5, 6, 7)); Quaternion quaternion3(8, Vector3(3, 5, 2)); - test(quaternion3 == Quaternion(5, 6, 7, 4)); + test(quaternion3 == Quaternion(3, 5, 2, 8)); - Matrix3x3 matrix(2, 3, 4, 5, 6, 7, 8, 9, 10); - Quaternion quaternion4(matrix); - Matrix3x3 result = quaternion4.getMatrix(); - test(approxEqual(matrix.getValue(0, 0), result.getValue(0, 0), 0.1)); - std::cout << "matrix : " << matrix.getValue(0, 0) << ", " << result.getValue(0, 0) << std::endl; - test(approxEqual(matrix.getValue(0, 1), result.getValue(0, 1), 0.1)); - test(approxEqual(matrix.getValue(0, 2), result.getValue(0, 2), 0.1)); - test(approxEqual(matrix.getValue(1, 0), result.getValue(1, 0), 0.1)); - test(approxEqual(matrix.getValue(1, 1), result.getValue(1, 1), 0.1)); - test(approxEqual(matrix.getValue(1, 2), result.getValue(1, 2), 0.1)); - test(approxEqual(matrix.getValue(2, 0), result.getValue(2, 0), 0.1)); - test(approxEqual(matrix.getValue(2, 1), result.getValue(2, 1), 0.1)); - test(approxEqual(matrix.getValue(2, 2), result.getValue(2, 2), 0.1)); + Quaternion quaternion4(mQuaternion1.getMatrix()); + test(approxEqual(quaternion4.x, mQuaternion1.x)); + test(approxEqual(quaternion4.y, mQuaternion1.y)); + test(approxEqual(quaternion4.z, mQuaternion1.z)); + test(approxEqual(quaternion4.w, mQuaternion1.w)); + } + + /// Test unit, length, normalize methods + void testUnitLengthNormalize() { + + // Test method that returns the length + Quaternion quaternion(2, 3, -4, 5); + test(approxEqual(quaternion.length(), sqrt(decimal(54.0)))); + + // Test method that returns a unit quaternion + test(approxEqual(quaternion.getUnit().length(), 1.0)); + + // Test the normalization method + Quaternion quaternion2(4, 5, 6, 7); + quaternion2.normalize(); + test(approxEqual(quaternion2.length(), 1.0)); + } + + /// Test others methods + void testOthersMethods() { + + // Test the method to set the values + Quaternion quaternion; + quaternion.setAllValues(1, 2, 3, 4); + test(quaternion == Quaternion(1, 2, 3, 4)); + + // Test the method to set the quaternion to zero + quaternion.setToZero(); + test(quaternion == Quaternion(0, 0, 0, 0)); + + // Test the method to get the vector (x, y, z) + Vector3 v = mQuaternion1.getVectorV(); + test(v.x == mQuaternion1.x); + test(v.y == mQuaternion1.y); + test(v.z == mQuaternion1.z); + + // Test the conjugate method + Quaternion conjugate = mQuaternion1.getConjugate(); + test(conjugate.x == -mQuaternion1.x); + test(conjugate.y == -mQuaternion1.y); + test(conjugate.z == -mQuaternion1.z); + test(conjugate.w == mQuaternion1.w); + + // Test the inverse method + Quaternion inverse = mQuaternion1.getInverse(); + Quaternion product = mQuaternion1 * inverse; + test(approxEqual(product.x, mIdentity.x, decimal(10e-6))); + test(approxEqual(product.y, mIdentity.y, decimal(10e-6))); + test(approxEqual(product.z, mIdentity.z, decimal(10e-6))); + test(approxEqual(product.w, mIdentity.w, decimal(10e-6))); + + // Test the dot product + Quaternion quaternion1(2, 3, 4, 5); + Quaternion quaternion2(6, 7, 8, 9); + decimal dotProduct = quaternion1.dot(quaternion2); + test(dotProduct == 110); + + // Test the method that returns the rotation angle and axis + Vector3 axis; + decimal angle; + Vector3 originalAxis = Vector3(2, 3, 4).getUnit(); + mQuaternion1.getRotationAngleAxis(angle, axis); + test(approxEqual(axis.x, originalAxis.x)); + test(approxEqual(angle, decimal(PI/4.0), decimal(10e-6))); + + // Test the method that returns the corresponding matrix + Matrix3x3 matrix = mQuaternion1.getMatrix(); + Vector3 vector(56, -2, 82); + Vector3 vector1 = matrix * vector; + Vector3 vector2 = mQuaternion1 * vector; + test(approxEqual(vector1.x, vector2.x)); + test(approxEqual(vector1.y, vector2.y)); + test(approxEqual(vector1.z, vector2.z)); + + // Test slerp method + Quaternion quatStart = quaternion1.getUnit(); + Quaternion quatEnd = quaternion2.getUnit(); + Quaternion test1 = Quaternion::slerp(quatStart, quatEnd, 0.0); + Quaternion test2 = Quaternion::slerp(quatStart, quatEnd, 1.0); + test(test1 == quatStart); + test(test2 == quatEnd); + decimal sinA = sin(decimal(PI/4.0)); + decimal cosA = cos(decimal(PI/4.0)); + Quaternion quat(sinA, 0, 0, cosA); + Quaternion test3 = Quaternion::slerp(mIdentity, quat, decimal(0.5)); + test(approxEqual(test3.x, sin(decimal(PI/8.0)))); + test(approxEqual(test3.y, 0.0)); + test(approxEqual(test3.z, 0.0)); + test(approxEqual(test3.w, cos(decimal(PI/8.0)), decimal(10e-6))); + } + + /// Test overloaded operators + void testOperators() { + + // Test addition + Quaternion quat1(4, 5, 2, 10); + Quaternion quat2(-2, 7, 8, 3); + Quaternion test1 = quat1 + quat2; + test(test1 == Quaternion(2, 12, 10, 13)); + + // Test substraction + Quaternion test2 = quat1 - quat2; + test(test2 == Quaternion(6, -2, -6, 7)); + + // Test multiplication with a number + Quaternion test3 = quat1 * 3.0; + test(test3 == Quaternion(12, 15, 6, 30)); + + // Test multiplication between two quaternions + Quaternion test4 = quat1 * quat2; + Quaternion test5 = mQuaternion1 * mIdentity; + test(test4 == Quaternion(18, 49, 124, -13)); + test(test5 == mQuaternion1); + + // Test multiplication between a quaternion and a point + Vector3 point(5, -24, 563); + Vector3 vector1 = mIdentity * point; + Vector3 vector2 = mQuaternion1 * point; + Vector3 testVector2 = mQuaternion1.getMatrix() * point; + test(vector1 == point); + test(approxEqual(vector2.x, testVector2.x, decimal(10e-6))); + test(approxEqual(vector2.y, testVector2.y, decimal(10e-6))); + test(approxEqual(vector2.z, testVector2.z, decimal(10e-6))); + + // Test assignment operator + Quaternion quaternion; + quaternion = mQuaternion1; + test(quaternion == mQuaternion1); + + // Test equality operator + test(mQuaternion1 == mQuaternion1); } }; diff --git a/test/tests/mathematics/TestTransform.h b/test/tests/mathematics/TestTransform.h index 2de02d79..4c700a0d 100644 --- a/test/tests/mathematics/TestTransform.h +++ b/test/tests/mathematics/TestTransform.h @@ -82,6 +82,7 @@ class TestTransform : public Test { testInverse(); testGetSetOpenGLMatrix(); testInterpolateTransform(); + testIdentity(); testOperators(); } @@ -127,27 +128,27 @@ class TestTransform : public Test { Transform transform; Vector3 position = mTransform1.getPosition(); Matrix3x3 orientation = mTransform1.getOrientation().getMatrix(); - decimal openglMatrix[16] = {orientation.getValue(0,0), orientation.getValue(1,0), - orientation.getValue(2,0), 0, - orientation.getValue(0,1), orientation.getValue(1,1), - orientation.getValue(2,1), 0, - orientation.getValue(0,2), orientation.getValue(1,2), - orientation.getValue(2,2), 0, + 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.getValue(0,0))); - test(approxEqual(openglMatrix2[1], orientation.getValue(1,0))); - test(approxEqual(openglMatrix2[2], orientation.getValue(2,0))); + 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.getValue(0,1))); - test(approxEqual(openglMatrix2[5], orientation.getValue(1,1))); - test(approxEqual(openglMatrix2[6], orientation.getValue(2,1))); + 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.getValue(0,2))); - test(approxEqual(openglMatrix2[9], orientation.getValue(1,2))); - test(approxEqual(openglMatrix2[10], orientation.getValue(2,2))); + 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)); @@ -180,6 +181,18 @@ class TestTransform : public Test { 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() { diff --git a/test/tests/mathematics/TestVector3.h b/test/tests/mathematics/TestVector3.h index 4097e730..d8f42599 100644 --- a/test/tests/mathematics/TestVector3.h +++ b/test/tests/mathematics/TestVector3.h @@ -92,6 +92,10 @@ class TestVector3 : public Test { test(approxEqual(newVector2.x, decimal(6.1))); test(approxEqual(newVector2.y, decimal(7.2))); test(approxEqual(newVector2.z, decimal(8.6))); + + // Test method to set to zero + newVector2.setToZero(); + test(newVector2 == Vector3(0, 0, 0)); } /// Test the length, unit vector and normalize methods @@ -219,6 +223,11 @@ class TestVector3 : public Test { vector4 /= 3; test(vector3 == Vector3(60, 330, 620)); test(vector4 == Vector3(5, 20, 11)); + + // Negative operator + Vector3 vector5(-34, 5, 422); + Vector3 negative = -vector5; + test(negative == Vector3(34, -5, -422)); } };