#include #include "tests/MatrixTests.h" #include "tests/Test.h" #include "utils/StringBuffer.h" #include "math/Matrix.h" const float eps = 0.0001f; template static void compareVectors(Test& test, const Vector& wanted, const Vector& actual, const char* text) { for(int i = 0; i < N; i++) { test.checkFloat(wanted[i], actual[i], eps, StringBuffer<50>(text).append(" (").append(i).append(")")); } } static void testInit(Test& test) { Matrix m; const float* data = m.getValues(); for(int i = 0; i < 16; i++) { int x = i % 4; int y = i / 4; test.checkEqual(static_cast (x == y), data[i], StringBuffer<50>("init ").append(i)); } } static void testTranspose(Test& test) { Matrix m; m.set(0, Vector4(1.0f, 2.0f, 3.0f, 4.0f)); m.set(1, Vector4(5.0f, 6.0f, 7.0f, 8.0f)); m.set(2, Vector4(9.0f, 10.0f, 11.0f, 12.0f)); m.set(3, Vector4(13.0f, 14.0f, 15.0f, 16.0f)); Matrix t = m.transpose(); Matrix m2 = t.transpose(); const float* mp = m.getValues(); const float* tp = t.getValues(); for(int x = 0; x < 4; x++) { for(int y = 0; y < 4; y++) { StringBuffer<50> s("transpose "); s.append(x).append(" | ").append(y); test.checkEqual(mp[y * 4 + x], tp[x * 4 + y], s); } } const float* mp2 = m2.getValues(); for(int i = 0; i < 16; i++) { test.checkEqual(mp[i], mp2[i], StringBuffer<50>("transpose ").append(i)); } } static void testScale(Test& test) { Matrix m; m.scale(Vector3(2.0f, 3.0f, 4.0f)); compareVectors(test, Vector3(-8.0f, 18.0f, 28.0f), m * Vector3(-4.0f, 6.0f, 7.0f), "scale"); } static void testUniformScale(Test& test) { Matrix m; m.scale(2.0f); compareVectors(test, Vector3(-8.0f, 12.0f, 14.0f), m * Vector3(-4.0f, 6.0f, 7.0f), "uniform scale"); } static void testTranslateX(Test& test) { Matrix m; m.translateX(5.0f); compareVectors(test, Vector3(1.0f, 6.0f, 7.0f), m * Vector3(-4.0f, 6.0f, 7.0f), "translate x"); } static void testTranslateY(Test& test) { Matrix m; m.translateY(6.0f); compareVectors(test, Vector3(-4.0f, 12.0f, 7.0f), m * Vector3(-4.0f, 6.0f, 7.0f), "translate y"); } static void testTranslateZ(Test& test) { Matrix m; m.translateZ(7.0f); compareVectors(test, Vector3(-4.0f, 6.0f, 14.0f), m * Vector3(-4.0f, 6.0f, 7.0f), "translate z"); } static void testTranslate(Test& test) { Matrix m; m.translate(Vector3(1.0f, 2.0f, 3.0f)); compareVectors(test, Vector3(-3.0f, 8.0f, 10.0f), m * Vector3(-4.0f, 6.0f, 7.0f), "translate"); } static void testCombination(Test& test) { Matrix m; m.scale(2.0f); m.translateX(1.0f); m.translateY(2.0f); m.translateZ(3.0f); m.translate(Vector3(-4.0f, 2.0f, 3.0f)); m.scale(Vector3(2.0f, 3.0f, 4.0f)); m.scale(0.5f); compareVectors(test, Vector3(-1.0f, 9.0f, 16.0f), m * Vector3(1.0f, 1.0f, 1.0f), "combination"); } static void testMatrixCombination(Test& test) { Matrix a; a.scale(2.0f); a.translate(Vector3(1.0f, 2.0f, 3.0f)); Matrix b; b.scale(3.0f); b.translate(Vector3(1.0f, 1.0f, 1.0f)); Matrix c; c.translate(Vector3(-1.0f, -2.0f, -3.0f)); c *= b * a; compareVectors(test, Vector3(9.0f, 11.0f, 13.0f), c * Vector3(1.0f, 1.0f, 1.0f), "combination"); } static void testRotateX(Test& test) { Matrix m; m.rotateX(90); compareVectors(test, Vector3(1.0f, 0.0f, 0.0f), m * Vector3(1.0f, 0.0f, 0.0f), "rotate x 1"); compareVectors(test, Vector3(0.0f, 0.0f, 1.0f), m * Vector3(0.0f, 1.0f, 0.0f), "rotate x 2"); compareVectors(test, Vector3(0.0f, -1.0f, 0.0f), m * Vector3(0.0f, 0.0f, 1.0f), "rotate x 3"); } static void testRotateY(Test& test) { Matrix m; m.rotateY(90); compareVectors(test, Vector3(0.0f, 0.0f, -1.0f), m * Vector3(1.0f, 0.0f, 0.0f), "rotate y 1"); compareVectors(test, Vector3(0.0f, 1.0f, 0.0f), m * Vector3(0.0f, 1.0f, 0.0f), "rotate y 2"); compareVectors(test, Vector3(1.0f, 0.0f, 0.0f), m * Vector3(0.0f, 0.0f, 1.0f), "rotate y 3"); } static void testRotateZ(Test& test) { Matrix m; m.rotateZ(90); compareVectors(test, Vector3(0.0f, 1.0f, 0.0f), m * Vector3(1.0f, 0.0f, 0.0f), "rotate z 1"); compareVectors(test, Vector3(-1.0f, 0.0f, 0.0f), m * Vector3(0.0f, 1.0f, 0.0f), "rotate z 2"); compareVectors(test, Vector3(0.0f, 0.0f, 1.0f), m * Vector3(0.0f, 0.0f, 1.0f), "rotate z 3"); } static void testToString(Test& test) { StringBuffer<200> s; Matrix m; m.set(0, Vector4(1.0f, 2.0f, 3.0f, 4.0f)); m.set(1, Vector4(5.0f, 6.0f, 7.0f, 8.0f)); m.set(2, Vector4(9.0f, 10.0f, 11.0f, 12.0f)); m.set(3, Vector4(13.0f, 14.0f, 15.0f, 16.0f)); s.append(m); test.checkEqual(StringBuffer<200>("[[1.00, 2.00, 3.00, 4.00], [5.00, 6.00, 7.00, 8.00], " "[9.00, 10.00, 11.00, 12.00], [13.00, 14.00, 15.00, 16.00]]"), s, "to string"); } static void testQuaternionMatrix(Test& test) { Quaternion q1(Vector3(1.0f, 0.0f, 0.0f), 48.0f); Quaternion q2(Vector3(0.0f, 1.0f, 0.0f), 52.0f); Quaternion q3(Vector3(0.0f, 0.0f, 1.0f), 60.0f); Matrix m; m.translate(Vector3(1.0f, 2.0f, 3.0f)); m = q1 * m; m = q2 * m; m = q3 * m; m.translate(Vector3(1.0f, 2.0f, 3.0f)); Matrix check; check.translate(Vector3(1.0f, 2.0f, 3.0f)); check.rotateX(48.0f); check.rotateY(52.0f); check.rotateZ(60.0f); check.translate(Vector3(1.0f, 2.0f, 3.0f)); for(int i = 0; i < 16; i++) { test.checkFloat(check.getValues()[i], m.getValues()[i], eps, "mul matrix"); } } static void testMulSetQuaternion(Test& test) { Quaternion q1(Vector3(1.0f, 0.0f, 0.0f), 48.0f); Quaternion q2(Vector3(0.0f, 1.0f, 0.0f), 52.0f); Quaternion q3(Vector3(0.0f, 0.0f, 1.0f), 60.0f); Matrix m; m *= q1; m *= q2; m *= q3; m.translate(Vector3(1.0f, 2.0f, 3.0f)); Matrix check; check.rotateZ(60.0f); check.rotateY(52.0f); check.rotateX(48.0f); check.translate(Vector3(1.0f, 2.0f, 3.0f)); for(int i = 0; i < 16; i++) { test.checkFloat(check.getValues()[i], m.getValues()[i], eps, "mul matrix"); } } static void testMatrixQuaternion(Test& test) { Quaternion q1(Vector3(1.0f, 0.0f, 0.0f), 48.0f); Quaternion q2(Vector3(0.0f, 1.0f, 0.0f), 52.0f); Quaternion q3(Vector3(0.0f, 0.0f, 1.0f), 60.0f); Matrix m; m = m * q1; m = m * q2; m = m * q3; m.translate(Vector3(1.0f, 2.0f, 3.0f)); Matrix check; check.rotateZ(60.0f); check.rotateY(52.0f); check.rotateX(48.0f); check.translate(Vector3(1.0f, 2.0f, 3.0f)); for(int i = 0; i < 16; i++) { test.checkFloat(check.getValues()[i], m.getValues()[i], eps, "mul matrix"); } } void MatrixTests::test() { Test test("Matrix"); testInit(test); testScale(test); testUniformScale(test); testTranspose(test); testTranslateX(test); testTranslateY(test); testTranslateZ(test); testTranslate(test); testCombination(test); testMatrixCombination(test); testRotateX(test); testRotateY(test); testRotateZ(test); testToString(test); testQuaternionMatrix(test); testMulSetQuaternion(test); testMatrixQuaternion(test); test.finalize(); }