#include #include #include #include #define GLM_FORCE_CTOR_INIT #include #include #include #include "dvt_unit_common.h" using namespace davinci; //------------------------------------------------------------------------------------- TEST(Math_Matrix4, Basic) { { float data[4][4] = { { FOUR_RANDOM_FLOAT },{ FOUR_RANDOM_FLOAT },{ FOUR_RANDOM_FLOAT }, { FOUR_RANDOM_FLOAT } }; fMatrix4 m1(data), m2(m1); fMatrix4 m3( data[0][0], data[0][1], data[0][2], data[0][3], data[1][0], data[1][1], data[1][2], data[1][3], data[2][0], data[2][1], data[2][2], data[2][3], data[3][0], data[3][1], data[3][2], data[3][3] ); EXPECT_EQ_4X4(m1, data); EXPECT_EQ_4X4(m2, data); EXPECT_EQ_4X4(m3, data); } { fMatrix4 m1(SIXTEEN_RANDOM_FLOAT), m2; m2 = m1; EXPECT_EQ_4X4(m1, m2); EXPECT_TRUE(m1 == m2); m2[0][0] += 1.0; EXPECT_TRUE(m1 != m2); } } //------------------------------------------------------------------------------------- TEST(Math_Matrix4, Algorithm) { //+ { float data1[16] = { SIXTEEN_RANDOM_FLOAT }; float data2[16] = { SIXTEEN_RANDOM_FLOAT }; fMatrix4 m1(SIXTEEN_ELEMENT_ROW(data1)), m2(SIXTEEN_ELEMENT_ROW(data2)); glm::mat4 gm1(SIXTEEN_ELEMENT_COL(data1)), gm2(SIXTEEN_ELEMENT_COL(data2)); fMatrix4 m3 = m1 + m2; glm::mat4 gm3 = gm1 + gm2; EXPECT_EQ_4X4_T(m3, gm3); } //- { float data1[16] = { SIXTEEN_RANDOM_FLOAT }; float data2[16] = { SIXTEEN_RANDOM_FLOAT }; fMatrix4 m1(SIXTEEN_ELEMENT_ROW(data1)), m2(SIXTEEN_ELEMENT_ROW(data2)); glm::mat4 gm1(SIXTEEN_ELEMENT_COL(data1)), gm2(SIXTEEN_ELEMENT_COL(data2)); fMatrix4 m3 = m1 - m2; glm::mat4 gm3 = gm1 - gm2; EXPECT_EQ_4X4_T(m3, gm3); } //* { float data1[16] = { SIXTEEN_RANDOM_FLOAT }; float data2[16] = { SIXTEEN_RANDOM_FLOAT }; fMatrix4 m1(SIXTEEN_ELEMENT_ROW(data1)), m2(SIXTEEN_ELEMENT_ROW(data2)); glm::mat4 gm1(SIXTEEN_ELEMENT_COL(data1)), gm2(SIXTEEN_ELEMENT_COL(data2)); fMatrix4 m3 = m1 * m2; glm::mat4 gm3 = gm1 * gm2; EXPECT_EQ_4X4_T(m3, gm3); } // - { float data1[16] = { SIXTEEN_RANDOM_FLOAT }; fMatrix4 m1(SIXTEEN_ELEMENT_ROW(data1)); glm::mat4 gm1(SIXTEEN_ELEMENT_COL(data1)); fMatrix4 m2 = -m1; glm::mat4 gm2 = -gm1; EXPECT_EQ_4X4_T(m2, gm2); } // vector4 * matrix { float data1[16] = { SIXTEEN_RANDOM_FLOAT }; float data2[4] = { FOUR_RANDOM_FLOAT }; fMatrix4 m1(SIXTEEN_ELEMENT_ROW(data1)); fVector4 v1(data2); fVector4 v2 = v1 * m1; glm::mat4 gm1(SIXTEEN_ELEMENT_COL(data1)); glm::vec4 gv1(FOUR_ELEMENT(data2)); glm::vec4 gv2 = gv1 * gm1; //fVector4 v2 = v1 * m1; EXPECT_TRUE(_floatEqualWithRange(v2.x, gv2.x, std::numeric_limits::epsilon() * 100)); EXPECT_TRUE(_floatEqualWithRange(v2.y, gv2.y, std::numeric_limits::epsilon() * 100)); EXPECT_TRUE(_floatEqualWithRange(v2.z, gv2.z, std::numeric_limits::epsilon() * 100)); EXPECT_TRUE(_floatEqualWithRange(v2.w, gv2.w, std::numeric_limits::epsilon() * 100)); } // matrix * vector4 { float data1[16] = { SIXTEEN_RANDOM_FLOAT }; float data2[4] = { FOUR_RANDOM_FLOAT }; fMatrix4 m1(SIXTEEN_ELEMENT_ROW(data1)); fVector4 v1(data2); fVector4 v2 = m1 * v1; glm::mat4 gm1(SIXTEEN_ELEMENT_COL(data1)); glm::vec4 gv1(FOUR_ELEMENT(data2)); glm::vec4 gv2 = gm1 * gv1; //fVector4 v2 = v1 * m1; EXPECT_TRUE(_floatEqualWithRange(v2.x, gv2.x, std::numeric_limits::epsilon() * 100)); EXPECT_TRUE(_floatEqualWithRange(v2.y, gv2.y, std::numeric_limits::epsilon() * 100)); EXPECT_TRUE(_floatEqualWithRange(v2.z, gv2.z, std::numeric_limits::epsilon() * 100)); EXPECT_TRUE(_floatEqualWithRange(v2.w, gv2.w, std::numeric_limits::epsilon() * 100)); } // matrix * vector3 { float data1[16] = { SIXTEEN_RANDOM_FLOAT }; float data2[3] = { THREE_RANDOM_FLOAT}; fMatrix4 m1(SIXTEEN_ELEMENT_ROW(data1)); fVector3 v1(data2); fVector3 v2 = m1 * v1; glm::mat4 gm1(SIXTEEN_ELEMENT_COL(data1)); glm::vec4 gv1(THREE_ELEMENT(data2), 1); glm::vec4 gv2 = gm1 * gv1; gv2 /= gv2.w; //fVector4 v2 = v1 * m1; EXPECT_TRUE(_floatEqualWithRange(v2.x, gv2.x, std::numeric_limits::epsilon() * 100)); EXPECT_TRUE(_floatEqualWithRange(v2.y, gv2.y, std::numeric_limits::epsilon() * 100)); EXPECT_TRUE(_floatEqualWithRange(v2.z, gv2.z, std::numeric_limits::epsilon() * 100)); } // vector3 * matrix { float data1[16] = { SIXTEEN_RANDOM_FLOAT }; float data2[3] = { THREE_RANDOM_FLOAT }; fMatrix4 m1(SIXTEEN_ELEMENT_ROW(data1)); fVector3 v1(data2); fVector3 v2 = v1 * m1; glm::mat4 gm1(SIXTEEN_ELEMENT_COL(data1)); glm::vec4 gv1(THREE_ELEMENT(data2), 1); glm::vec4 gv2 = gv1 * gm1; gv2 /= gv2.w; EXPECT_TRUE(_floatEqualWithRange(v2.x, gv2.x, std::numeric_limits::epsilon() * 100)); EXPECT_TRUE(_floatEqualWithRange(v2.y, gv2.y, std::numeric_limits::epsilon() * 100)); EXPECT_TRUE(_floatEqualWithRange(v2.z, gv2.z, std::numeric_limits::epsilon() * 100)); } // * float { float data[16] = { SIXTEEN_RANDOM_FLOAT }; float a = _randomFloat(); fMatrix4 m1(SIXTEEN_ELEMENT_ROW(data)); fMatrix4 m2 = m1 * a, m3 = a * m1; glm::mat4 gm1(SIXTEEN_ELEMENT_COL(data)); glm::mat4 gm2 = gm1 * a; EXPECT_EQ_4X4_T(m2, gm2); EXPECT_TRUE(m2 == m3); } // translation { float trans_data[] = { THREE_RANDOM_FLOAT }; fMatrix4 m1 = fMatrix4::makeTrans(THREE_ELEMENT(trans_data)); glm::mat4 gm1 = glm::translate(glm::mat4(1), glm::vec3(THREE_ELEMENT(trans_data))); EXPECT_EQ_4X4_T(m1, gm1); fVector3 p0(THREE_RANDOM_FLOAT); fVector3 p1 = m1 * p0; EXPECT_TRUE(p1 == p0 + fVector3(trans_data)); } // scale { float scale_data[] = { THREE_RANDOM_FLOAT }; fMatrix4 m1 = fMatrix4::makeScale(THREE_ELEMENT(scale_data)); glm::mat4 gm1 = glm::scale(glm::mat4(1.0f), glm::vec3(THREE_ELEMENT(scale_data))); EXPECT_EQ_4X4_T(m1, gm1); } // transpose { float data[16] = { SIXTEEN_RANDOM_FLOAT }; fMatrix4 m1(SIXTEEN_ELEMENT_ROW(data)); fMatrix4 m2 = m1.transpose(); glm::mat4 gm1(SIXTEEN_ELEMENT_COL(data)); glm::mat4 gm2 = glm::transpose(gm1); EXPECT_EQ_4X4_T(m2, gm2); } // rotation { float data[3] = { THREE_RANDOM_FLOAT }; fVector3 axis(data); axis = axis.normalise(); float angle(_randomFloat()); float c = cos(angle*0.5); float s = sin(angle*0.5); fMatrix4 mx = fMatrix4::makeRotate_X(angle); fMatrix4 my = fMatrix4::makeRotate_Y(angle); fMatrix4 mz = fMatrix4::makeRotate_Z(angle); fMatrix4 mv = fMatrix4::makeRotate(axis, angle); fMatrix4 mq = fMatrix4::makeRotate(fVector4(s * axis.x, s * axis.y, s * axis.z, c)); EXPECT_EQ_4X4_APPROX(mv, mq, std::numeric_limits::epsilon() * 1000); glm::vec3 gmaxis(data[0], data[1], data[2]); gmaxis = glm::normalize(gmaxis); glm::mat4 gmx = glm::rotate(glm::mat4(), angle, glm::vec3(1, 0, 0)); glm::mat4 gmy = glm::rotate(glm::mat4(), angle, glm::vec3(0, 1, 0)); glm::mat4 gmz = glm::rotate(glm::mat4(), angle, glm::vec3(0, 0, 1)); glm::mat4 gmv = glm::rotate(glm::mat4(), angle, gmaxis); glm::qua quaternion = glm::qua(c, s * gmaxis.x, s * gmaxis.y, s * gmaxis.z); glm::mat4 gmq = glm::mat4_cast(quaternion); EXPECT_EQ_4X4_T_APPROX(mx, gmx, std::numeric_limits::epsilon() * 1000); EXPECT_EQ_4X4_T_APPROX(my, gmy, std::numeric_limits::epsilon() * 1000); EXPECT_EQ_4X4_T_APPROX(mz, gmz, std::numeric_limits::epsilon() * 1000); EXPECT_EQ_4X4_T_APPROX(mv, gmv, std::numeric_limits::epsilon() * 1000); EXPECT_EQ_4X4_T_APPROX(mq, gmq, std::numeric_limits::epsilon() * 1000); } // inverse { float data[16] = { SIXTEEN_RANDOM_FLOAT }; fMatrix4 m1(SIXTEEN_ELEMENT_ROW(data)); fMatrix4 m2 = m1.inverse(); glm::mat4 gm1(SIXTEEN_ELEMENT_COL(data)); glm::mat4 gm2 = glm::inverse(gm1); EXPECT_EQ_4X4_T_APPROX(m2, gm2, std::numeric_limits::epsilon()*10000); } }