Files
davinci2/test/unit/dvt_unit_matrix4.cpp
T
2025-06-11 22:45:11 +08:00

286 lines
7.9 KiB
C++

#include <math/dvc_matrix4.h>
#include <math/dvc_vector3.h>
#include <math/dvc_vector4.h>
#include <gtest/gtest.h>
#define GLM_FORCE_CTOR_INIT
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/quaternion.hpp>
#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<float>::epsilon() * 100));
EXPECT_TRUE(_floatEqualWithRange(v2.y, gv2.y, std::numeric_limits<float>::epsilon() * 100));
EXPECT_TRUE(_floatEqualWithRange(v2.z, gv2.z, std::numeric_limits<float>::epsilon() * 100));
EXPECT_TRUE(_floatEqualWithRange(v2.w, gv2.w, std::numeric_limits<float>::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<float>::epsilon() * 100));
EXPECT_TRUE(_floatEqualWithRange(v2.y, gv2.y, std::numeric_limits<float>::epsilon() * 100));
EXPECT_TRUE(_floatEqualWithRange(v2.z, gv2.z, std::numeric_limits<float>::epsilon() * 100));
EXPECT_TRUE(_floatEqualWithRange(v2.w, gv2.w, std::numeric_limits<float>::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<float>::epsilon() * 100));
EXPECT_TRUE(_floatEqualWithRange(v2.y, gv2.y, std::numeric_limits<float>::epsilon() * 100));
EXPECT_TRUE(_floatEqualWithRange(v2.z, gv2.z, std::numeric_limits<float>::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<float>::epsilon() * 100));
EXPECT_TRUE(_floatEqualWithRange(v2.y, gv2.y, std::numeric_limits<float>::epsilon() * 100));
EXPECT_TRUE(_floatEqualWithRange(v2.z, gv2.z, std::numeric_limits<float>::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<float>::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<float>::epsilon() * 1000);
EXPECT_EQ_4X4_T_APPROX(my, gmy, std::numeric_limits<float>::epsilon() * 1000);
EXPECT_EQ_4X4_T_APPROX(mz, gmz, std::numeric_limits<float>::epsilon() * 1000);
EXPECT_EQ_4X4_T_APPROX(mv, gmv, std::numeric_limits<float>::epsilon() * 1000);
EXPECT_EQ_4X4_T_APPROX(mq, gmq, std::numeric_limits<float>::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<float>::epsilon()*10000);
}
}