init commit

This commit is contained in:
2025-06-11 22:45:11 +08:00
commit 71307f3e53
115 changed files with 13922 additions and 0 deletions
+39
View File
@@ -0,0 +1,39 @@
enable_testing()
include_directories(
${DV_AUTO_INCLUDE_PATH}
${DV_CORE_INCLUDE_PATH}
${DV_UTILS_INCLUDE_PATH}
)
set(DVT_UNIT_SOURCE_FILES
dvt_unit_main.cpp
dvt_unit_vector2.cpp
dvt_unit_vector3.cpp
dvt_unit_vector4.cpp
dvt_unit_matrix3.cpp
dvt_unit_matrix4.cpp
dvt_unit_math_util.cpp
dvt_unit_rasterizer.cpp
)
add_definitions(-DGLM_FORCE_PURE -DGLM_FORCE_LEFT_HANDED -DGLM_FORCE_DEPTH_ZERO_TO_ONE)
add_executable(dvt_unit
dvt_unit_common.h
${DVT_UNIT_SOURCE_FILES}
)
set_property(TARGET dvt_unit PROPERTY FOLDER "test")
target_link_libraries(dvt_unit
dv_core
dv_utils
GTest::gtest
GTest::gtest_main
glm::glm
)
include(GoogleTest)
gtest_discover_tests(dvt_unit)
+47
View File
@@ -0,0 +1,47 @@
#pragma once
#include <math/dvc_math_util.h>
using namespace davinci;
//-------------------------------------------------------------------------------------
inline float _randomFloat(void) {
return MathUtil::rangeRandom(-65521 / 16.f, 65521 / 16.f);
}
//-------------------------------------------------------------------------------------
inline bool _floatEqualWithRange(float a, float b, float t = std::numeric_limits<float>::epsilon()) {
if (MathUtil::floatEqual(a, b)) return true;
float d = std::abs(a - b) / std::min(std::abs(a), std::abs(b));
return MathUtil::floatEqual(d, 0.f, t);
}
//-------------------------------------------------------------------------------------
#define TWO_RANDOM_FLOAT _randomFloat(), _randomFloat()
#define THREE_RANDOM_FLOAT _randomFloat(), _randomFloat(), _randomFloat()
#define FOUR_RANDOM_FLOAT _randomFloat(), _randomFloat(), _randomFloat(), _randomFloat()
#define NINE_RANDOM_FLOAT THREE_RANDOM_FLOAT, THREE_RANDOM_FLOAT, THREE_RANDOM_FLOAT
#define SIXTEEN_RANDOM_FLOAT FOUR_RANDOM_FLOAT, FOUR_RANDOM_FLOAT, FOUR_RANDOM_FLOAT, FOUR_RANDOM_FLOAT
#define THREE_ELEMENT(data) data[0], data[1], data[2]
#define FOUR_ELEMENT(data) data[0], data[1], data[2], data[3]
#define NINE_ELEMENT_ROW(data) data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8]
#define NINE_ELEMENT_COL(data) data[0], data[3], data[6], data[1], data[4], data[7], data[2], data[5], data[8]
#define SIXTEEN_ELEMENT_ROW(data) data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15]
#define SIXTEEN_ELEMENT_COL(data) data[0], data[4], data[8], data[12], data[1], data[5], data[9], data[13], data[2], data[6], data[10], data[14], data[3], data[7], data[11], data[15]
#define EXPECT_EQ_3X3(a, b) for(int32_t i=0; i<3; i++) for(int32_t j=0; j<3; j++) EXPECT_EQ(a[i][j], b[i][j]);
#define EXPECT_EQ_3X3_T(a, b) for(int32_t i=0; i<3; i++) for(int32_t j=0; j<3; j++) EXPECT_EQ(a[i][j], b[j][i]);
#define EXPECT_EQ_4X4(a, b) for(int32_t i=0; i<4; i++) for(int32_t j=0; j<4; j++) EXPECT_EQ(a[i][j], b[i][j]);
#define EXPECT_EQ_4X4_T(a, b) for(int32_t i=0; i<4; i++) for(int32_t j=0; j<4; j++) EXPECT_EQ(a[i][j], b[j][i]);
//-------------------------------------------------------------------------------------
#define SIXTEEN_RANDOM_FLOAT2 THREE_RANDOM_FLOAT, 0.f, THREE_RANDOM_FLOAT, 0.f, THREE_RANDOM_FLOAT, 0.f, THREE_RANDOM_FLOAT, 1.f
#define EXPECT_EQ_4X4_APPROX(a, b, t) for(int32_t ii=0; ii<4; ii++) for(int32_t jj=0; jj<4; jj++) \
EXPECT_TRUE(_floatEqualWithRange(a[ii][jj], b[ii][jj], t));
#define EXPECT_EQ_4X4_T_APPROX(a, b, t) for(int32_t ii=0; ii<4; ii++) for(int32_t jj=0; jj<4; jj++) \
EXPECT_TRUE(_floatEqualWithRange(a[ii][jj], b[jj][ii], t));
+14
View File
@@ -0,0 +1,14 @@
#include <stdio.h>
#include <gtest/gtest.h>
//-------------------------------------------------------------------------------------
int main(int argc, char* argv[])
{
testing::InitGoogleTest(&argc, argv);
uint32_t seed = (uint32_t)::time(0);
//seed = 1748961760;
srand(seed);
printf("seed=%d\n", seed);
return RUN_ALL_TESTS();
}
+79
View File
@@ -0,0 +1,79 @@
#include <math/dvc_math_util.h>
#include <math/dvc_matrix4.h>
#include <math/dvc_vector3.h>
#include <math/dvc_vector4.h>
#include <gtest/gtest.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "dvt_unit_common.h"
using namespace davinci;
//-------------------------------------------------------------------------------------
TEST(MathUtil, Basic)
{
//lookat view matrix
{
float dEye[3] = { 0.0f, 4.0f, -10.0f };
float dAt[3] = { 0.0f, 1.0f, 0.0f };
float dUp[3] = { 0.0f, 1.0f, 0.0f };
fMatrix4 m1 = MathUtil::lookatRH(
fVector3(THREE_ELEMENT(dEye)),
fVector3(THREE_ELEMENT(dAt)),
fVector3(THREE_ELEMENT(dUp)));
glm::mat4 gm1 = glm::lookAtRH(glm::vec3(THREE_ELEMENT(dEye)), glm::vec3(THREE_ELEMENT(dAt)), glm::vec3(THREE_ELEMENT(dUp)));
EXPECT_EQ_4X4_T(m1, gm1);
}
//lookat view matrix(random)
{
for (int i = 0; i < 10; i++) {
fVector3 dEye, dAt, dUp;
do {
dEye[0] = _randomFloat(); dEye[1] = _randomFloat(); dEye[2] = _randomFloat();
dAt[0] = _randomFloat(); dAt[1] = _randomFloat(); dAt[2] = _randomFloat();
dUp[0] = _randomFloat(); dUp[1] = _randomFloat(); dUp[2] = _randomFloat();
} while ((dEye == dAt) || (dUp == fVector3::ZERO));
fMatrix4 m1 = MathUtil::lookatRH(
fVector3(THREE_ELEMENT(dEye)),
fVector3(THREE_ELEMENT(dAt)),
fVector3(THREE_ELEMENT(dUp)));
glm::mat4 gm1 = glm::lookAtRH(glm::vec3(THREE_ELEMENT(dEye)), glm::vec3(THREE_ELEMENT(dAt)), glm::vec3(THREE_ELEMENT(dUp)));
EXPECT_EQ_4X4_T_APPROX(m1, gm1, std::numeric_limits<float>::epsilon() * 1000);
}
}
//perspective
{
float width = 640.f, height = 480.f;
fMatrix4 m1 = MathUtil::perspectiveFovRH(MathUtil::PI_DIV4, width / height, 0.01f, 100.f);
glm::mat4 gm1 = glm::perspectiveRH(MathUtil::PI_DIV4, width / height, 0.01f, 100.f);
EXPECT_EQ_4X4_T_APPROX(m1, gm1, std::numeric_limits<float>::epsilon());
}
//perspective(random)
{
for (int i = 0; i < 10; i++) {
float fov = MathUtil::rangeRandom(0.1f, MathUtil::PI);
float aspect = MathUtil::rangeRandom(0.1f, 100.f);
float zNear = MathUtil::rangeRandom(0.00001f, 0.01f);
float zFar = MathUtil::rangeRandom(100.f, 10000.f);
fMatrix4 m1 = MathUtil::perspectiveFovRH(fov, aspect, zNear, zFar);
glm::mat4 gm1 = glm::perspectiveRH(fov, aspect, zNear, zFar);
EXPECT_EQ_4X4_T_APPROX(m1, gm1, std::numeric_limits<float>::epsilon() * 100);
}
}
}
+182
View File
@@ -0,0 +1,182 @@
#include <math/dvc_matrix3.h>
#include <math/dvc_vector3.h>
#include <gtest/gtest.h>
#include <glm/glm.hpp>
#include "dvt_unit_common.h"
using namespace davinci;
//-------------------------------------------------------------------------------------
TEST(Math_Matrix3, Basic)
{
{
float data[3][3] = { { THREE_RANDOM_FLOAT }, { THREE_RANDOM_FLOAT }, { THREE_RANDOM_FLOAT } };
fMatrix3 m1(data), m2(m1);
fMatrix3 m3(
data[0][0], data[0][1], data[0][2],
data[1][0], data[1][1], data[1][2],
data[2][0], data[2][1], data[2][2]
);
EXPECT_EQ_3X3(m1, data);
EXPECT_EQ_3X3(m2, data);
EXPECT_EQ_3X3(m3, data);
}
{
fMatrix3 m1(NINE_RANDOM_FLOAT), m2;
m2 = m1;
EXPECT_EQ_3X3(m1, m2);
EXPECT_TRUE(m1 == m2);
m2[0][0] += 1.0;
EXPECT_TRUE(m1 != m2);
}
}
//-------------------------------------------------------------------------------------
TEST(Math_Matrix3, Algorithm)
{
//+
{
float data1[9] = { NINE_RANDOM_FLOAT };
float data2[9] = { NINE_RANDOM_FLOAT };
fMatrix3 m1(NINE_ELEMENT_ROW(data1)), m2(NINE_ELEMENT_ROW(data2));
glm::mat3 gm1(NINE_ELEMENT_COL(data1)), gm2(NINE_ELEMENT_COL(data2));
fMatrix3 m3 = m1 + m2;
glm::mat3 gm3 = gm1 + gm2;
EXPECT_EQ_3X3_T(m3, gm3);
}
//-
{
float data1[9] = { NINE_RANDOM_FLOAT };
float data2[9] = { NINE_RANDOM_FLOAT };
fMatrix3 m1(NINE_ELEMENT_ROW(data1)), m2(NINE_ELEMENT_ROW(data2));
glm::mat3 gm1(NINE_ELEMENT_COL(data1)), gm2(NINE_ELEMENT_COL(data2));
fMatrix3 m3 = m1 - m2;
glm::mat3 gm3 = gm1 - gm2;
EXPECT_EQ_3X3_T(m3, gm3);
}
//*
{
float data1[9] = { NINE_RANDOM_FLOAT };
float data2[9] = { NINE_RANDOM_FLOAT };
fMatrix3 m1(NINE_ELEMENT_ROW(data1)), m2(NINE_ELEMENT_ROW(data2));
glm::mat3 gm1(NINE_ELEMENT_COL(data1)), gm2(NINE_ELEMENT_COL(data2));
fMatrix3 m3 = m1 * m2;
glm::mat3 gm3 = gm1 * gm2;
EXPECT_EQ_3X3_T(m3, gm3);
}
// -
{
float data1[9] = { NINE_RANDOM_FLOAT };
fMatrix3 m1(NINE_ELEMENT_ROW(data1));
glm::mat3 gm1(NINE_ELEMENT_COL(data1));
fMatrix3 m2 = -m1;
glm::mat3 gm2 = -gm1;
EXPECT_EQ_3X3_T(m2, gm2);
}
// vector * matrix
{
float data1[9] = { NINE_RANDOM_FLOAT };
float data2[3] = { THREE_RANDOM_FLOAT };
fMatrix3 m1(NINE_ELEMENT_ROW(data1));
fVector3 v1(data2);
fVector3 v2 = v1 * m1;
glm::mat3 gm1(NINE_ELEMENT_COL(data1));
glm::vec3 gv1(data2[0], data2[1], data2[2]);
glm::vec3 gv2 = gv1*gm1;
EXPECT_EQ(v2.x, gv2.x);
EXPECT_EQ(v2.y, gv2.y);
EXPECT_EQ(v2.z, gv2.z);
}
// matrix * vector
{
float data1[9] = { NINE_RANDOM_FLOAT };
float data2[3] = { THREE_RANDOM_FLOAT };
fMatrix3 m1(NINE_ELEMENT_ROW(data1));
fVector3 v1(data2);
fVector3 v2 = m1 * v1;
glm::mat3 gm1(NINE_ELEMENT_COL(data1));
glm::vec3 gv1(data2[0], data2[1], data2[2]);
glm::vec3 gv2 = gm1 * gv1;
EXPECT_EQ(v2.x, gv2.x);
EXPECT_EQ(v2.y, gv2.y);
EXPECT_EQ(v2.z, gv2.z);
}
// * float
{
float data1[9] = { NINE_RANDOM_FLOAT };
float a = _randomFloat();
fMatrix3 m1(NINE_ELEMENT_ROW(data1));
fMatrix3 m2 = m1 * a, m3 = a * m1;
glm::mat3 gm1(NINE_ELEMENT_COL(data1));
glm::mat3 gm2 = gm1 * a;
EXPECT_EQ_3X3_T(m2, gm2);
EXPECT_TRUE(m2 == m3);
}
// transpose
{
float data1[9] = { NINE_RANDOM_FLOAT };
fMatrix3 m1(NINE_ELEMENT_ROW(data1));
fMatrix3 m2 = m1.transpose();
glm::mat3 gm1(NINE_ELEMENT_COL(data1));
glm::mat3 gm2 = glm::transpose(gm1);
EXPECT_EQ_3X3_T(m2, gm2);
}
// inverse
{
float data1[9] = { NINE_RANDOM_FLOAT };
fMatrix3 m1(NINE_ELEMENT_ROW(data1)), m2;
bool inv = m1.inverse(m2);
glm::mat3 gm1(NINE_ELEMENT_COL(data1));
glm::mat3 gm2 = glm::inverse(gm1);
if (inv)
EXPECT_EQ_3X3_T(m2, gm2);
EXPECT_FALSE(fMatrix3::ZERO.inverse(m2));
}
}
+285
View File
@@ -0,0 +1,285 @@
#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);
}
}
+416
View File
@@ -0,0 +1,416 @@
#include <pipe/dvc_rasterizer.h>
#include <buffer/dvu_dump_buffer.h>
#include <gtest/gtest.h>
#include <atomic>
using namespace davinci;
class Edge
{
public:
Edge(const fVector2 &_p1, const fVector2 &_p2) : p1(_p1), p2(_p2) {};
Edge(const Edge &e) : p1(e.p1), p2(e.p2) {};
fVector2 p1;
fVector2 p2;
};
//-------------------------------------------------------------------------------------
inline bool operator == (const Edge & e1, const Edge & e2)
{
return (e1.p1 == e2.p1 && e1.p2 == e2.p2) ||
(e1.p1 == e2.p2 && e1.p2 == e2.p1);
}
//-------------------------------------------------------------------------------------
class Triangle
{
public:
Triangle(const fVector2 &_p1, const fVector2 &_p2, const fVector2 &_p3)
: p1(_p1), p2(_p2), p3(_p3)
{}
bool containsVertex(const fVector2 &v)
{
return p1 == v || p2 == v || p3 == v;
}
bool circumCircleContains(const fVector2 &v)
{
float ab = (p1.x * p1.x) + (p1.y * p1.y);
float cd = (p2.x * p2.x) + (p2.y * p2.y);
float ef = (p3.x * p3.x) + (p3.y * p3.y);
float circum_x = (ab * (p3.y - p2.y) + cd * (p1.y - p3.y) + ef * (p2.y - p1.y)) / (p1.x * (p3.y - p2.y) + p2.x * (p1.y - p3.y) + p3.x * (p2.y - p1.y)) / 2.f;
float circum_y = (ab * (p3.x - p2.x) + cd * (p1.x - p3.x) + ef * (p2.x - p1.x)) / (p1.y * (p3.x - p2.x) + p2.y * (p1.x - p3.x) + p3.y * (p2.x - p1.x)) / 2.f;
float circum_radius = sqrtf(((p1.x - circum_x) * (p1.x - circum_x)) + ((p1.y - circum_y) * (p1.y - circum_y)));
float dist = sqrtf(((v.x - circum_x) * (v.x - circum_x)) + ((v.y - circum_y) * (v.y - circum_y)));
return dist <= circum_radius;
}
fVector2 p1;
fVector2 p2;
fVector2 p3;
};
//-------------------------------------------------------------------------------------
inline bool operator == (const Triangle &t1, const Triangle &t2)
{
return (t1.p1 == t2.p1 || t1.p1 == t2.p2 || t1.p1 == t2.p3) &&
(t1.p2 == t2.p1 || t1.p2 == t2.p2 || t1.p2 == t2.p3) &&
(t1.p3 == t2.p1 || t1.p3 == t2.p2 || t1.p3 == t2.p3);
}
//-------------------------------------------------------------------------------------
class Delaunay
{
/*
https://github.com/Bl4ckb0ne/delaunay-triangulation
*/
public:
static void triangulate(const std::vector<fVector2> & vertices, std::vector<Triangle>& _triangles)
{
// Determinate the super triangle
float minX = vertices[0].x;
float minY = vertices[0].y;
float maxX = minX;
float maxY = minY;
for (std::size_t i = 0; i < vertices.size(); ++i)
{
if (vertices[i].x < minX) minX = vertices[i].x;
if (vertices[i].y < minY) minY = vertices[i].y;
if (vertices[i].x > maxX) maxX = vertices[i].x;
if (vertices[i].y > maxY) maxY = vertices[i].y;
}
float dx = maxX - minX;
float dy = maxY - minY;
float deltaMax = std::max(dx, dy);
float midx = (minX + maxX) / 2.f;
float midy = (minY + maxY) / 2.f;
fVector2 p1(midx - 20 * deltaMax, midy - deltaMax);
fVector2 p2(midx, midy + 20 * deltaMax);
fVector2 p3(midx + 20 * deltaMax, midy - deltaMax);
// Create a list of triangles, and add the supertriangle in it
_triangles.push_back(Triangle(p1, p2, p3));
for (auto p = begin(vertices); p != end(vertices); p++) {
std::vector<Triangle> badTriangles;
std::vector<Edge> polygon;
for (auto t = begin(_triangles); t != end(_triangles); t++) {
if (t->circumCircleContains(*p)) {
badTriangles.push_back(*t);
polygon.push_back(Edge(t->p1, t->p2));
polygon.push_back(Edge(t->p2, t->p3));
polygon.push_back(Edge(t->p3, t->p1));
}
}
_triangles.erase(std::remove_if(begin(_triangles), end(_triangles), [badTriangles](Triangle &t) {
for (auto bt = begin(badTriangles); bt != end(badTriangles); bt++) {
if (*bt == t) {
return true;
}
}
return false;
}), end(_triangles));
std::vector<Edge> badEdges;
for (auto e1 = begin(polygon); e1 != end(polygon); e1++) {
for (auto e2 = begin(polygon); e2 != end(polygon); e2++) {
if (e1 == e2) continue;
if (*e1 == *e2) {
badEdges.push_back(*e1);
badEdges.push_back(*e2);
}
}
}
polygon.erase(std::remove_if(begin(polygon), end(polygon), [badEdges](Edge &e) {
for (auto it = begin(badEdges); it != end(badEdges); it++) {
if (*it == e) return true;
}
return false;
}), end(polygon));
for (auto e = begin(polygon); e != end(polygon); e++)
_triangles.push_back(Triangle(e->p1, e->p2, *p));
}
_triangles.erase(std::remove_if(begin(_triangles), end(_triangles), [p1, p2, p3](Triangle &t) {
return t.containsVertex(p1) || t.containsVertex(p2) || t.containsVertex(p3);
}), end(_triangles));
}
};
//-------------------------------------------------------------------------------------
struct Pixel
{
int32_t x, y;
};
typedef std::vector<Pixel> PixelBuf;
//-------------------------------------------------------------------------------------
class Canvas
{
public:
Canvas() : m_width(0), m_height(0), m_pixelBuf(nullptr), m_errorFlag(false) { }
~Canvas() {
delete[] m_pixelBuf;
m_pixelBuf = nullptr;
}
int32_t getWidth(void) const { return m_width; }
int32_t getHeight(void) const { return m_height; }
void init(int32_t width, int32_t height) {
if (m_width != width || m_height != height) {
if (m_pixelBuf) delete[] m_pixelBuf;
m_width = width;
m_height = height;
//alloc pixels
m_pixelBuf = new std::atomic<uint32_t>[m_width*m_height];
}
for (size_t i = 0; i < (size_t)(m_width*m_height); i++) {
m_pixelBuf[i] = 0;
}
m_errorFlag = false;
}
void clear(void) {
for (size_t i = 0; i < (size_t)(m_width*m_height); i++) {
m_pixelBuf[i] = 0;
}
m_errorFlag = false;
}
void razFunction_fetchadd(const std::pair<int32_t, int32_t>& pixel, const fVector3& b) {
if (m_errorFlag.load()) return;
if (pixel.first < 0 || pixel.first >= m_width || pixel.second < 0 || pixel.second >= m_height) {
bool _false = false;
m_errorFlag.compare_exchange_strong(_false, true);
return;
}
m_pixelBuf[pixel.second*m_width + pixel.first].fetch_add(1);
}
void razFunction(const std::pair<int32_t, int32_t>& pixel, const fVector3& b, uint32_t randCol) {
if (m_errorFlag.load()) return;
if (pixel.first < 0 || pixel.first >= m_width || pixel.second < 0 || pixel.second >= m_height) {
bool _false = false;
m_errorFlag.compare_exchange_strong(_false, true);
return;
}
m_pixelBuf[pixel.second*m_width + pixel.first] = randCol;
}
bool checkResult(bool debug=false) {
if (m_errorFlag) return false;
if (debug) {
bool succ = true;
uint32_t* colBuf = new uint32_t[m_width*m_height];
for (int32_t i = 0; i < m_width*m_height; i++) {
colBuf[i] = m_pixelBuf[i].load();
if (m_pixelBuf[i] == 0) {
if (debug) printf("error: %d,%d=%d\n", i%m_width, i/ m_width, m_pixelBuf[(size_t)i].load());
succ = false;
//return false;
}
}
davinci_utils::dump_pixel_buffer("debug.png", m_width, m_height, colBuf, PF_UINT8_RGBA);
delete[] colBuf;
return succ;
}
else {
for (size_t i = 0; i < (size_t)(m_width*m_height); i++) {
if (m_pixelBuf[i] == 0) return false;
}
}
return true;
}
bool checkResult(const PixelBuf& pixelExpected) {
if (m_errorFlag) return false;
for (const auto& pixel : pixelExpected) {
assert(pixel.x >= 0 && pixel.x < m_width && pixel.y >= 0 && pixel.y < m_height);
auto& p = m_pixelBuf[pixel.y*m_width + pixel.x];
if (p != 1) return false;
p = 0;
}
for (size_t i = 0; i < (size_t)(m_width*m_height); i++) {
if (m_pixelBuf[i] != 0) return false;
}
return true;
}
private:
int32_t m_width, m_height;
std::atomic<uint32_t>* m_pixelBuf;
std::atomic<bool> m_errorFlag;
std::string m_strError;
};
//-------------------------------------------------------------------------------------
static bool _triangleRasterizationRules(Canvas& canvas, const Triangle& triangle, const PixelBuf& pixelExpect, bool ccw=true)
{
auto razFunc = std::bind(&Canvas::razFunction_fetchadd, &canvas, std::placeholders::_1, std::placeholders::_2);
canvas.clear();
Rasterizer::drawTriangleLarrabee(canvas.getWidth(), canvas.getHeight(),
triangle.p1, triangle.p2, triangle.p3,
razFunc, ccw);
return canvas.checkResult(pixelExpect);
}
//-------------------------------------------------------------------------------------
TEST(Rasterizer, Basic)
{
const int32_t canvasWidth = 64, canvasHeight = 64;
Canvas canvas;
canvas.init(canvasWidth, canvasHeight);
/*
Triangle Rasterization rules test(Without Multisampling)
https://msdn.microsoft.com/en-us/library/windows/desktop/cc627092(v=vs.85).aspx
*/
{
Triangle triangle(fVector2(4.5f, 7.5f), fVector2(4.5f, 7.5f), fVector2(4.5f, 7.5f));
PixelBuf pixels = {};
EXPECT_TRUE(_triangleRasterizationRules(canvas, triangle, pixels, false));
}
{
Triangle triangle(fVector2(1, 2), fVector2(7, 4), fVector2(5, 2));
PixelBuf pixels = { {2, 2}, {3, 2}, {4, 2}, {5, 3} };
EXPECT_TRUE(_triangleRasterizationRules(canvas, triangle, pixels, false));
}
{
Triangle triangle(fVector2(5, 2), fVector2(7, 4), fVector2(8, 1));
PixelBuf pixels = { { 5, 2 },{ 6, 1 },{ 6, 2 },{ 6, 3 }, {7, 1} };
EXPECT_TRUE(_triangleRasterizationRules(canvas, triangle, pixels, false));
}
{
Triangle triangle(fVector2(8, 1), fVector2(7, 4), fVector2(9.5f, 2.5f));
PixelBuf pixels = { { 7, 2 },{ 7, 3 }, { 8, 2 } };
EXPECT_TRUE(_triangleRasterizationRules(canvas, triangle, pixels, false));
}
{
Triangle triangle(fVector2(1, 7), fVector2(6, 6), fVector2(2, 4));
PixelBuf pixels = { { 2, 4 }, {1, 5 }, { 2, 5 }, { 3, 5 }, { 4, 5 }, { 1, 6 }, { 2, 6 }, };
EXPECT_TRUE(_triangleRasterizationRules(canvas, triangle, pixels, false));
}
{
Triangle triangle(fVector2(5.25f, 6.75f), fVector2(6.25f, 7.75f), fVector2(6.25f, 6.75f));
PixelBuf pixels = { };
EXPECT_TRUE(_triangleRasterizationRules(canvas, triangle, pixels, false));
}
{
Triangle triangle(fVector2(6.5f, 5.5f), fVector2(7.5f, 7.5f), fVector2(7.5f, 6.5f));
PixelBuf pixels = {};
EXPECT_TRUE(_triangleRasterizationRules(canvas, triangle, pixels, false));
}
{
Triangle triangle(fVector2(7.6f, 5.5f), fVector2(9.75f, 7.25f), fVector2(11.6f, 5.5f));
PixelBuf pixels = { { 9,6 },{ 10, 6 } };
EXPECT_TRUE(_triangleRasterizationRules(canvas, triangle, pixels, false));
}
{
Triangle triangle(fVector2(7.6f, 5.5f), fVector2(11.6f, 5.5f), fVector2(9.5f, 2.6f));
PixelBuf pixels = { {8, 5}, { 9, 5 }, { 10, 5 }, { 11, 5 }, { 8, 4 }, { 9, 4 }, { 10, 4 }, {9, 3} };
EXPECT_TRUE(_triangleRasterizationRules(canvas, triangle, pixels, false));
}
{
Triangle triangle(fVector2(11.5f, 1.5f), fVector2(11.5f, 3.5f), fVector2(12.5f, 2.5f));
PixelBuf pixels = { {11,2} };
EXPECT_TRUE(_triangleRasterizationRules(canvas, triangle, pixels, false));
}
{
Triangle triangle(fVector2(9.5f, 0.5f), fVector2(10.5f, 0.5f), fVector2(9.5f, -1.5f));
PixelBuf pixels = { { 9,0 } };
EXPECT_TRUE(_triangleRasterizationRules(canvas, triangle, pixels, false));
}
{
Triangle triangle(fVector2(13.5f, 0.5f), fVector2(13.5f, 2.5f), fVector2(15.5f, 2.5f));
PixelBuf pixels = { { 13,1 }, {13, 2}, {14, 2} };
EXPECT_TRUE(_triangleRasterizationRules(canvas, triangle, pixels, false));
}
{
Triangle triangle(fVector2(13.5f, 0.5f), fVector2(15.5f, 2.5f), fVector2(15.5f, 0.5f));
PixelBuf pixels = { { 14, 1 } };
EXPECT_TRUE(_triangleRasterizationRules(canvas, triangle, pixels, false));
}
{
Triangle triangle(fVector2(13.5f, 6.5f), fVector2(14.5f, 5.5f), fVector2(14.5f, 3.5f));
PixelBuf pixels = { };
EXPECT_TRUE(_triangleRasterizationRules(canvas, triangle, pixels, false));
}
{
Triangle triangle(fVector2(13.5f, 6.5f), fVector2(15, 8), fVector2(14.5f, 5.5f) );
PixelBuf pixels = { {13, 6}, {14, 6}, {14, 7} };
EXPECT_TRUE(_triangleRasterizationRules(canvas, triangle, pixels, false));
}
}
//-------------------------------------------------------------------------------------
TEST(Rasterizer, Delaunay)
{
//seed=1499743811, counts=5, range=0.8f;
//seed=1499670829, counts=5, range=1.f;
const int32_t width = 1024, height = 1024;
const int32_t verticesCounts = MathUtil::rangeRandom(5, 30);
float range = 0.8f;
std::vector<fVector2> vertices;
for (int32_t i = 0; i < verticesCounts; i++) {
float32_t x = MathUtil::rangeRandom(width * (1 - range) / 2.f, width * (1 + range) / 2.f);
float32_t y = MathUtil::rangeRandom(height * (1 - range) / 2.f, height * (1 + range) / 2.f);
vertices.push_back(fVector2(x, y));
}
vertices.push_back(fVector2(0, 0));
vertices.push_back(fVector2((float)width, 0));
vertices.push_back(fVector2((float)width, (float)height));
vertices.push_back(fVector2(0, (float)height));
std::vector<Triangle> triangles;
Delaunay::triangulate(vertices, triangles);
Canvas canvas;
canvas.init(width, height);
canvas.clear();
for (size_t i = 0; i < triangles.size(); i++) {
const Triangle& triangle = triangles[i];
uint32_t randCol = 0xFF000000 + ((uint32_t)(rand() / 240) << 16) + ((uint32_t)(rand() / 240) << 8) + ((uint32_t)(rand() / 240));
auto razFunc = std::bind(&Canvas::razFunction, &canvas, std::placeholders::_1, std::placeholders::_2, randCol);
Rasterizer::drawTriangleLarrabee(canvas.getWidth(), canvas.getHeight(),
triangle.p1, triangle.p2, triangle.p3,
razFunc, false);
}
EXPECT_TRUE(canvas.checkResult(true));
}
+268
View File
@@ -0,0 +1,268 @@
#include <math/dvc_vector2.h>
#include <gtest/gtest.h>
#include <glm/glm.hpp>
#include "dvt_unit_common.h"
using namespace davinci;
//-------------------------------------------------------------------------------------
TEST(Math_Vector2, Basic)
{
{
fVector2 v1;
EXPECT_EQ(v1.x, 0.f);
EXPECT_EQ(v1.y, 0.f);
}
{
float a = _randomFloat(), b = _randomFloat();
fVector2 v1(a, b), v2(v1);
EXPECT_EQ(v1.x, a);
EXPECT_EQ(v1.y, b);
EXPECT_EQ(v2.x, a);
EXPECT_EQ(v2.y, b);
}
{
float a = _randomFloat(), b = _randomFloat();
fVector2 v1;
v1[0] = a; v1[1] = b;
EXPECT_EQ(v1.x, a);
EXPECT_EQ(v1.y, b);
EXPECT_EQ(v1[0], a);
EXPECT_EQ(v1[1], b);
}
{
float a = _randomFloat();
fVector2 v2(a);
EXPECT_EQ(v2.x, a);
EXPECT_EQ(v2.y, a);
}
{
float a[2] = { TWO_RANDOM_FLOAT };
fVector2 v2(a);
EXPECT_EQ(v2.x, a[0]);
EXPECT_EQ(v2.y, a[1]);
}
{
int a[2] = { rand() - RAND_MAX/2, rand() - RAND_MAX / 2 };
fVector2 v2(a);
EXPECT_EQ(v2.x, (float)a[0]);
EXPECT_EQ(v2.y, (float)a[1]);
}
//operator
{
fVector2 v1(TWO_RANDOM_FLOAT), v2;
v2 = v1;
EXPECT_EQ(v1.x, v2.x);
EXPECT_EQ(v1.y, v2.y);
}
{
float a = _randomFloat();
fVector2 v1;
v1 = a;
EXPECT_EQ(v1.x, a);
EXPECT_EQ(v1.y, a);
}
{
fVector2 v1(TWO_RANDOM_FLOAT), v2(v1);
EXPECT_TRUE(v1 == v2);
v2.x += 1.f;
EXPECT_TRUE(v1 != v2);
}
{
float a = 0.f;
while (a == 0.f) { a = _randomFloat(); }
fVector2 v1(TWO_RANDOM_FLOAT);
fVector2 v2;// (_randomFloat(), _randomFloat());
while (v2.x == 0.f || v2.y == 0.f) {
v2 = fVector2(TWO_RANDOM_FLOAT);
}
fVector2 v3;
v3 = v1 + v2;
EXPECT_EQ(v3.x, v1.x + v2.x);
EXPECT_EQ(v3.y, v1.y + v2.y);
v3 = v1 - v2;
EXPECT_EQ(v3.x, v1.x - v2.x);
EXPECT_EQ(v3.y, v1.y - v2.y);
v3 = v1 * a;
EXPECT_EQ(v3.x, v1.x * a);
EXPECT_EQ(v3.y, v1.y * a);
v3 = v1 * v2;
EXPECT_EQ(v3.x, v1.x * v2.x);
EXPECT_EQ(v3.y, v1.y * v2.y);
v3 = v1 / a;
EXPECT_EQ(v3.x, v1.x / a);
EXPECT_EQ(v3.y, v1.y / a);
v3 = v1 / v2;
EXPECT_EQ(v3.x, v1.x / v2.x);
EXPECT_EQ(v3.y, v1.y / v2.y);
}
{
fVector2 v1(TWO_RANDOM_FLOAT), v2;
v2 = +v1;
EXPECT_TRUE(v1 == v2);
v2 = -v1;
EXPECT_EQ(v1.x, -v2.x);
EXPECT_EQ(v1.y, -v2.y);
}
{
float a = _randomFloat();
fVector2 v1, v2;
while (v1.x == 0.f || v1.y == 0.f) {
v1 = fVector2(TWO_RANDOM_FLOAT);
}
v2 = a * v1;
EXPECT_EQ(v2.x, a*v1.x);
EXPECT_EQ(v2.y, a*v1.y);
v2 = a / v1;
EXPECT_EQ(v2.x, a/v1.x);
EXPECT_EQ(v2.y, a/v1.y);
v2 = v1 + a;
EXPECT_EQ(v2.x, a + v1.x);
EXPECT_EQ(v2.y, a + v1.y);
v2 = a + v1;
EXPECT_EQ(v2.x, a + v1.x);
EXPECT_EQ(v2.y, a + v1.y);
v2 = v1 - a;
EXPECT_EQ(v2.x, v1.x - a);
EXPECT_EQ(v2.y, v1.y - a);
v2 = a + v1;
EXPECT_EQ(v2.x, a + v1.x);
EXPECT_EQ(v2.y, a + v1.y);
}
{
fVector2 v1(TWO_RANDOM_FLOAT), v2, v3;
while (v2.x == 0.f || v2.y == 0.f) {
v2 = fVector2(TWO_RANDOM_FLOAT);
}
float a = _randomFloat();
while (a == 0.f) { a = _randomFloat(); }
v3 = v1;
v3 += v2;
EXPECT_TRUE(v3 == v1+v2);
v3 = v1;
v3 += a;
EXPECT_TRUE(v3 == v1 + a);
v3 = v1;
v3 -= v2;
EXPECT_TRUE(v3 == v1 - v2);
v3 = v1;
v3 -= a;
EXPECT_TRUE(v3 == v1 - a);
v3 = v1;
v3 *= v2;
EXPECT_TRUE(v3 == v1 * v2);
v3 = v1;
v3 *= a;
EXPECT_TRUE(v3 == v1 * a);
v3 = v1;
v3 /= v2;
EXPECT_TRUE(v3 == v1 / v2);
v3 = v1;
v3 /= a;
EXPECT_TRUE(v3 == v1 / a);
}
{
fVector2 v1(TWO_RANDOM_FLOAT), v2(v1);
v2 += 1.f;
EXPECT_TRUE(v2 > v1);
v2 -= 2.f;
EXPECT_TRUE(v2 < v1);
}
}
//-------------------------------------------------------------------------------------
TEST(Math_Vector2, Algorithm)
{
//length
{
fVector2 v1(TWO_RANDOM_FLOAT);
glm::vec2 gv1(v1.x, v1.y);
EXPECT_EQ(v1.length(), glm::length(gv1));
}
//squaredLength
{
fVector2 v1(TWO_RANDOM_FLOAT);
glm::vec2 gv1(v1.x, v1.y);
EXPECT_EQ(v1.squaredLength(), glm::dot(gv1, gv1));
}
//distance
{
fVector2 v1(TWO_RANDOM_FLOAT), v2(TWO_RANDOM_FLOAT);
glm::vec2 gv1(v1.x, v1.y), gv2(v2.x, v2.y);
EXPECT_EQ(v1.distance(v2), glm::distance(gv1, gv2));
}
//squaredDistance
{
fVector2 v1(TWO_RANDOM_FLOAT), v2(TWO_RANDOM_FLOAT);
glm::vec2 gv1(v1.x, v1.y), gv2(v2.x, v2.y);
glm::vec2 dis = gv1 - gv2;
EXPECT_EQ(v1.squaredDistance(v2), glm::dot(dis, dis));
}
//dotProduct
{
fVector2 v1(TWO_RANDOM_FLOAT), v2(TWO_RANDOM_FLOAT);
glm::vec2 gv1(v1.x, v1.y), gv2(v2.x, v2.y);
EXPECT_EQ(v1.dotProduct(v2), glm::dot(gv1, gv2));
}
//crossProduct
{
fVector2 v1(TWO_RANDOM_FLOAT), v2(TWO_RANDOM_FLOAT);
glm::vec3 gv1(v1.x, v1.y, 0), gv2(v2.x, v2.y, 0);
EXPECT_EQ(v1.crossProduct(v2), glm::cross(gv1, gv2).z);
}
//normalise
{
fVector2 v1(TWO_RANDOM_FLOAT);
glm::vec2 gv1(v1.x, v1.y);
v1.normalise();
glm::vec2 gv1_normal = glm::normalize(gv1);
EXPECT_EQ(v1.x, gv1_normal.x);
EXPECT_EQ(v1.y, gv1_normal.y);
}
}
+322
View File
@@ -0,0 +1,322 @@
#include <math/dvc_vector2.h>
#include <math/dvc_vector3.h>
#include <gtest/gtest.h>
#include <glm/glm.hpp>
#include "dvt_unit_common.h"
using namespace davinci;
//-------------------------------------------------------------------------------------
TEST(Math_Vector3, Basic)
{
{
fVector3 v1;
EXPECT_EQ(v1.x, 0.f);
EXPECT_EQ(v1.y, 0.f);
EXPECT_EQ(v1.z, 0.f);
}
{
float a = _randomFloat(), b = _randomFloat(), c = _randomFloat();
fVector3 v1(a, b, c), v2(v1);
EXPECT_EQ(v1.x, a);
EXPECT_EQ(v1.y, b);
EXPECT_EQ(v1.z, c);
EXPECT_EQ(v2.x, a);
EXPECT_EQ(v2.y, b);
EXPECT_EQ(v2.z, c);
}
{
float a = _randomFloat(), b = _randomFloat(), c = _randomFloat();
fVector3 v1;
v1[0] = a; v1[1] = b; v1[2] = c;
EXPECT_EQ(v1.x, a);
EXPECT_EQ(v1.y, b);
EXPECT_EQ(v1.z, c);
EXPECT_EQ(v1[0], a);
EXPECT_EQ(v1[1], b);
EXPECT_EQ(v1[2], c);
fVector2 v1_xy = v1.xy();
EXPECT_EQ(v1_xy.x, a);
EXPECT_EQ(v1_xy.y, b);
fVector2 v1_xz = v1.xz();
EXPECT_EQ(v1_xz.x, a);
EXPECT_EQ(v1_xz.y, c);
fVector2 v1_yz = v1.yz();
EXPECT_EQ(v1_yz.x, b);
EXPECT_EQ(v1_yz.y, c);
}
{
float a = _randomFloat();
fVector3 v2(a);
EXPECT_EQ(v2.x, a);
EXPECT_EQ(v2.y, a);
EXPECT_EQ(v2.z, a);
}
{
float a[3] = { THREE_RANDOM_FLOAT };
fVector3 v2(a);
EXPECT_EQ(v2.x, a[0]);
EXPECT_EQ(v2.y, a[1]);
EXPECT_EQ(v2.z, a[2]);
}
{
int a[3] = { rand() - RAND_MAX / 2, rand() - RAND_MAX / 2, rand() - RAND_MAX / 2 };
fVector3 v2(a);
EXPECT_EQ(v2.x, (float)a[0]);
EXPECT_EQ(v2.y, (float)a[1]);
EXPECT_EQ(v2.z, (float)a[2]);
}
{
float a = _randomFloat(), b = _randomFloat(), c = _randomFloat();
fVector2 v1(a, b);
fVector3 v2(v1, c);
EXPECT_EQ(v2.x, a);
EXPECT_EQ(v2.y, b);
EXPECT_EQ(v2.z, c);
fVector2 v3(a, b);
fVector3 v4(c, v3);
EXPECT_EQ(v4.x, c);
EXPECT_EQ(v4.y, a);
EXPECT_EQ(v4.z, b);
}
//operator
{
fVector3 v1(THREE_RANDOM_FLOAT), v2;
v2 = v1;
EXPECT_EQ(v1.x, v2.x);
EXPECT_EQ(v1.y, v2.y);
EXPECT_EQ(v1.z, v2.z);
}
{
float a = _randomFloat();
fVector3 v1;
v1 = a;
EXPECT_EQ(v1.x, a);
EXPECT_EQ(v1.y, a);
EXPECT_EQ(v1.z, a);
}
{
fVector3 v1(THREE_RANDOM_FLOAT), v2(v1);
EXPECT_TRUE(v1 == v2);
v2.x += 1.f;
EXPECT_TRUE(v1 != v2);
}
{
float a = 0.f;
while (a == 0.f) { a = _randomFloat(); }
fVector3 v1(THREE_RANDOM_FLOAT);
fVector3 v2;
while (v2.x == 0.f || v2.y == 0.f || v2.z == 0.f) {
v2 = fVector3(THREE_RANDOM_FLOAT);
}
fVector3 v3;
v3 = v1 + v2;
EXPECT_EQ(v3.x, v1.x + v2.x);
EXPECT_EQ(v3.y, v1.y + v2.y);
EXPECT_EQ(v3.z, v1.z + v2.z);
v3 = v1 - v2;
EXPECT_EQ(v3.x, v1.x - v2.x);
EXPECT_EQ(v3.y, v1.y - v2.y);
EXPECT_EQ(v3.z, v1.z - v2.z);
v3 = v1 * a;
EXPECT_EQ(v3.x, v1.x * a);
EXPECT_EQ(v3.y, v1.y * a);
EXPECT_EQ(v3.z, v1.z * a);
v3 = v1 * v2;
EXPECT_EQ(v3.x, v1.x * v2.x);
EXPECT_EQ(v3.y, v1.y * v2.y);
EXPECT_EQ(v3.z, v1.z * v2.z);
v3 = v1 / a;
EXPECT_EQ(v3.x, v1.x / a);
EXPECT_EQ(v3.y, v1.y / a);
EXPECT_EQ(v3.z, v1.z / a);
v3 = v1 / v2;
EXPECT_EQ(v3.x, v1.x / v2.x);
EXPECT_EQ(v3.y, v1.y / v2.y);
EXPECT_EQ(v3.z, v1.z / v2.z);
}
{
fVector3 v1(THREE_RANDOM_FLOAT), v2;
v2 = +v1;
EXPECT_TRUE(v1 == v2);
v2 = -v1;
EXPECT_EQ(v1.x, -v2.x);
EXPECT_EQ(v1.y, -v2.y);
EXPECT_EQ(v1.z, -v2.z);
}
{
float a = _randomFloat();
fVector3 v1, v2;
while (v1.x == 0.f || v1.y == 0.f || v1.z == 0.f) {
v1 = fVector3(THREE_RANDOM_FLOAT);
}
v2 = a * v1;
EXPECT_EQ(v2.x, a*v1.x);
EXPECT_EQ(v2.y, a*v1.y);
EXPECT_EQ(v2.z, a*v1.z);
v2 = a / v1;
EXPECT_EQ(v2.x, a / v1.x);
EXPECT_EQ(v2.y, a / v1.y);
EXPECT_EQ(v2.z, a / v1.z);
v2 = v1 + a;
EXPECT_EQ(v2.x, a + v1.x);
EXPECT_EQ(v2.y, a + v1.y);
EXPECT_EQ(v2.z, a + v1.z);
v2 = a + v1;
EXPECT_EQ(v2.x, a + v1.x);
EXPECT_EQ(v2.y, a + v1.y);
EXPECT_EQ(v2.z, a + v1.z);
v2 = v1 - a;
EXPECT_EQ(v2.x, v1.x - a);
EXPECT_EQ(v2.y, v1.y - a);
EXPECT_EQ(v2.z, v1.z - a);
v2 = a + v1;
EXPECT_EQ(v2.x, a + v1.x);
EXPECT_EQ(v2.y, a + v1.y);
EXPECT_EQ(v2.z, a + v1.z);
}
{
fVector3 v1(THREE_RANDOM_FLOAT), v2, v3;
while (v2.x == 0.f || v2.y == 0.f || v2.z == 0.f) {
v2 = fVector3(THREE_RANDOM_FLOAT);
}
float a = _randomFloat();
while (a == 0.f) { a = _randomFloat(); }
v3 = v1;
v3 += v2;
EXPECT_TRUE(v3 == v1 + v2);
v3 = v1;
v3 += a;
EXPECT_TRUE(v3 == v1 + a);
v3 = v1;
v3 -= v2;
EXPECT_TRUE(v3 == v1 - v2);
v3 = v1;
v3 -= a;
EXPECT_TRUE(v3 == v1 - a);
v3 = v1;
v3 *= v2;
EXPECT_TRUE(v3 == v1 * v2);
v3 = v1;
v3 *= a;
EXPECT_TRUE(v3 == v1 * a);
v3 = v1;
v3 /= v2;
EXPECT_TRUE(v3 == v1 / v2);
v3 = v1;
v3 /= a;
EXPECT_TRUE(v3 == v1 / a);
}
{
fVector3 v1(THREE_RANDOM_FLOAT), v2(v1);
v2 += 1.f;
EXPECT_TRUE(v2 > v1);
v2 -= 2.f;
EXPECT_TRUE(v2 < v1);
}
}
//-------------------------------------------------------------------------------------
TEST(Math_Vector3, Algorithm)
{
//length
{
fVector3 v1(THREE_RANDOM_FLOAT);
glm::vec3 gv1(v1.x, v1.y, v1.z);
EXPECT_EQ(v1.length(), glm::length(gv1));
}
//squaredLength
{
fVector3 v1(THREE_RANDOM_FLOAT);
glm::vec3 gv1(v1.x, v1.y, v1.z);
EXPECT_EQ(v1.squaredLength(), glm::dot(gv1, gv1));
}
//distance
{
fVector3 v1(THREE_RANDOM_FLOAT), v2(THREE_RANDOM_FLOAT);
glm::vec3 gv1(v1.x, v1.y, v1.z), gv2(v2.x, v2.y, v2.z);
EXPECT_EQ(v1.distance(v2), glm::distance(gv1, gv2));
}
//squaredDistance
{
fVector3 v1(THREE_RANDOM_FLOAT), v2(THREE_RANDOM_FLOAT);
glm::vec3 gv1(v1.x, v1.y, v1.z), gv2(v2.x, v2.y, v2.z);
glm::vec3 len(gv1 - gv2);
EXPECT_EQ(v1.squaredDistance(v2), glm::dot(len, len));
}
//dotProduct
{
fVector3 v1(THREE_RANDOM_FLOAT), v2(THREE_RANDOM_FLOAT);
glm::vec3 gv1(v1.x, v1.y, v1.z), gv2(v2.x, v2.y, v2.z);
EXPECT_EQ(v1.dotProduct(v2), glm::dot(gv1, gv2));
}
//crossProduct
{
fVector3 v1(THREE_RANDOM_FLOAT), v2(THREE_RANDOM_FLOAT);
glm::vec3 gv1(v1.x, v1.y, v1.z), gv2(v2.x, v2.y, v2.z);
fVector3 v3 = v1.crossProduct(v2);
glm::vec3 gv1_cross = glm::cross(gv1, gv2);
EXPECT_EQ(v3.x, gv1_cross.x);
EXPECT_EQ(v3.y, gv1_cross.y);
EXPECT_EQ(v3.z, gv1_cross.z);
}
//normalise
{
fVector3 v1(THREE_RANDOM_FLOAT);
glm::vec3 gv1(v1.x, v1.y, v1.z);
v1.normalise();
glm::vec3 gv1_nor = glm::normalize(gv1);
EXPECT_EQ(v1.x, gv1_nor.x);
EXPECT_EQ(v1.y, gv1_nor.y);
EXPECT_EQ(v1.z, gv1_nor.z);
}
}
+262
View File
@@ -0,0 +1,262 @@
#include <math/dvc_vector4.h>
#include <gtest/gtest.h>
#include <glm/glm.hpp>
#include "dvt_unit_common.h"
using namespace davinci;
//-------------------------------------------------------------------------------------
TEST(Math_Vector4, Basic)
{
{
fVector4 v1;
EXPECT_EQ(v1.x, 0.f);
EXPECT_EQ(v1.y, 0.f);
EXPECT_EQ(v1.z, 0.f);
EXPECT_EQ(v1.w, 0.f);
}
{
float a = _randomFloat(), b = _randomFloat(), c = _randomFloat(), d = _randomFloat();
fVector4 v1(a, b, c, d), v2(v1);
EXPECT_EQ(v1.x, a);
EXPECT_EQ(v1.y, b);
EXPECT_EQ(v1.z, c);
EXPECT_EQ(v1.w, d);
EXPECT_EQ(v2.x, a);
EXPECT_EQ(v2.y, b);
EXPECT_EQ(v2.z, c);
EXPECT_EQ(v2.w, d);
}
{
float a = _randomFloat(), b = _randomFloat(), c = _randomFloat(), d = _randomFloat();
fVector4 v1;
v1[0] = a; v1[1] = b; v1[2] = c; v1[3] = d;
EXPECT_EQ(v1.x, a);
EXPECT_EQ(v1.y, b);
EXPECT_EQ(v1.z, c);
EXPECT_EQ(v1.w, d);
EXPECT_EQ(v1[0], a);
EXPECT_EQ(v1[1], b);
EXPECT_EQ(v1[2], c);
EXPECT_EQ(v1[3], d);
}
{
float a = _randomFloat();
fVector4 v2(a);
EXPECT_EQ(v2.x, a);
EXPECT_EQ(v2.y, a);
EXPECT_EQ(v2.z, a);
EXPECT_EQ(v2.w, a);
}
{
float a[4] = { FOUR_RANDOM_FLOAT };
fVector4 v2(a);
EXPECT_EQ(v2.x, a[0]);
EXPECT_EQ(v2.y, a[1]);
EXPECT_EQ(v2.z, a[2]);
EXPECT_EQ(v2.w, a[3]);
}
{
int a[4] = { rand() - RAND_MAX / 2, rand() - RAND_MAX / 2, rand() - RAND_MAX / 2, rand() - RAND_MAX / 2 };
fVector4 v2(a);
EXPECT_EQ(v2.x, (float)a[0]);
EXPECT_EQ(v2.y, (float)a[1]);
EXPECT_EQ(v2.z, (float)a[2]);
EXPECT_EQ(v2.w, (float)a[3]);
}
//operator
{
fVector4 v1(FOUR_RANDOM_FLOAT), v2;
v2 = v1;
EXPECT_EQ(v1.x, v2.x);
EXPECT_EQ(v1.y, v2.y);
EXPECT_EQ(v1.z, v2.z);
EXPECT_EQ(v1.w, v2.w);
}
{
float a = _randomFloat();
fVector4 v1;
v1 = a;
EXPECT_EQ(v1.x, a);
EXPECT_EQ(v1.y, a);
EXPECT_EQ(v1.z, a);
EXPECT_EQ(v1.w, a);
}
{
fVector4 v1(FOUR_RANDOM_FLOAT), v2(v1);
EXPECT_TRUE(v1 == v2);
v2.x += 1.f;
EXPECT_TRUE(v1 != v2);
}
{
float a = 0.f;
while (a == 0.f) { a = _randomFloat(); }
fVector4 v1(FOUR_RANDOM_FLOAT);
fVector4 v2;
while (v2.x == 0.f || v2.y == 0.f || v2.z == 0.f || v2.w == 0.f) {
v2 = fVector4(FOUR_RANDOM_FLOAT);
}
fVector4 v3;
v3 = v1 + v2;
EXPECT_EQ(v3.x, v1.x + v2.x);
EXPECT_EQ(v3.y, v1.y + v2.y);
EXPECT_EQ(v3.z, v1.z + v2.z);
EXPECT_EQ(v3.w, v1.w + v2.w);
v3 = v1 - v2;
EXPECT_EQ(v3.x, v1.x - v2.x);
EXPECT_EQ(v3.y, v1.y - v2.y);
EXPECT_EQ(v3.z, v1.z - v2.z);
EXPECT_EQ(v3.w, v1.w - v2.w);
v3 = v1 * a;
EXPECT_EQ(v3.x, v1.x * a);
EXPECT_EQ(v3.y, v1.y * a);
EXPECT_EQ(v3.z, v1.z * a);
EXPECT_EQ(v3.w, v1.w * a);
v3 = v1 * v2;
EXPECT_EQ(v3.x, v1.x * v2.x);
EXPECT_EQ(v3.y, v1.y * v2.y);
EXPECT_EQ(v3.z, v1.z * v2.z);
EXPECT_EQ(v3.w, v1.w * v2.w);
v3 = v1 / a;
EXPECT_EQ(v3.x, v1.x / a);
EXPECT_EQ(v3.y, v1.y / a);
EXPECT_EQ(v3.z, v1.z / a);
EXPECT_EQ(v3.w, v1.w / a);
v3 = v1 / v2;
EXPECT_EQ(v3.x, v1.x / v2.x);
EXPECT_EQ(v3.y, v1.y / v2.y);
EXPECT_EQ(v3.z, v1.z / v2.z);
EXPECT_EQ(v3.w, v1.w / v2.w);
}
{
fVector4 v1(FOUR_RANDOM_FLOAT), v2;
v2 = +v1;
EXPECT_TRUE(v1 == v2);
v2 = -v1;
EXPECT_EQ(v1.x, -v2.x);
EXPECT_EQ(v1.y, -v2.y);
EXPECT_EQ(v1.z, -v2.z);
EXPECT_EQ(v1.w, -v2.w);
}
{
float a = _randomFloat();
fVector4 v1, v2;
while (v1.x == 0.f || v1.y == 0.f || v1.z == 0.f || v1.w == 0.f) {
v1 = fVector4(FOUR_RANDOM_FLOAT);
}
v2 = a * v1;
EXPECT_EQ(v2.x, a*v1.x);
EXPECT_EQ(v2.y, a*v1.y);
EXPECT_EQ(v2.z, a*v1.z);
EXPECT_EQ(v2.w, a*v1.w);
v2 = a / v1;
EXPECT_EQ(v2.x, a / v1.x);
EXPECT_EQ(v2.y, a / v1.y);
EXPECT_EQ(v2.z, a / v1.z);
EXPECT_EQ(v2.w, a / v1.w);
v2 = v1 + a;
EXPECT_EQ(v2.x, a + v1.x);
EXPECT_EQ(v2.y, a + v1.y);
EXPECT_EQ(v2.z, a + v1.z);
EXPECT_EQ(v2.w, a + v1.w);
v2 = a + v1;
EXPECT_EQ(v2.x, a + v1.x);
EXPECT_EQ(v2.y, a + v1.y);
EXPECT_EQ(v2.z, a + v1.z);
EXPECT_EQ(v2.w, a + v1.w);
v2 = v1 - a;
EXPECT_EQ(v2.x, v1.x - a);
EXPECT_EQ(v2.y, v1.y - a);
EXPECT_EQ(v2.z, v1.z - a);
EXPECT_EQ(v2.w, v1.w - a);
v2 = a + v1;
EXPECT_EQ(v2.x, a + v1.x);
EXPECT_EQ(v2.y, a + v1.y);
EXPECT_EQ(v2.z, a + v1.z);
EXPECT_EQ(v2.w, a + v1.w);
}
{
fVector4 v1(FOUR_RANDOM_FLOAT), v2, v3;
while (v2.x == 0.f || v2.y == 0.f || v2.z == 0.f || v2.w == 0.f) {
v2 = fVector4(FOUR_RANDOM_FLOAT);
}
float a = _randomFloat();
while (a == 0.f) { a = _randomFloat(); }
v3 = v1;
v3 += v2;
EXPECT_TRUE(v3 == v1 + v2);
v3 = v1;
v3 += a;
EXPECT_TRUE(v3 == v1 + a);
v3 = v1;
v3 -= v2;
EXPECT_TRUE(v3 == v1 - v2);
v3 = v1;
v3 -= a;
EXPECT_TRUE(v3 == v1 - a);
v3 = v1;
v3 *= v2;
EXPECT_TRUE(v3 == v1 * v2);
v3 = v1;
v3 *= a;
EXPECT_TRUE(v3 == v1 * a);
v3 = v1;
v3 /= v2;
EXPECT_TRUE(v3 == v1 / v2);
v3 = v1;
v3 /= a;
EXPECT_TRUE(v3 == v1 / a);
}
{
fVector4 v1(FOUR_RANDOM_FLOAT), v2(v1);
v2 += 1.f;
EXPECT_TRUE(v2 > v1);
v2 -= 2.f;
EXPECT_TRUE(v2 < v1);
}
}
//-------------------------------------------------------------------------------------
TEST(Math_Vector4, Algorithm)
{
//dotProduct
{
fVector4 v1(FOUR_RANDOM_FLOAT), v2(FOUR_RANDOM_FLOAT);
glm::vec4 gv1(v1.x, v1.y, v1.z, v1.w), gv2(v2.x, v2.y, v2.z, v2.w);
EXPECT_EQ(v1.dotProduct(v2), glm::dot(gv1, gv2));
}
}