xcal
基于 C++23 的现代图形渲染引擎
载入中...
搜索中...
未找到
test_perspective_camera.cc
浏览该文件的文档.
1#include <gtest/gtest.h>
2
3#include <cmath>
5
11namespace xcal::camera {
12
16TEST(TestPerspectiveCamera, CreateWithDefaultValues) {
17 auto camera =
18 std::make_unique<PerspectiveCamera>(60.0f, 16.0f / 9.0f, 0.1f, 100.0f);
19
20 // 验证初始值
21 EXPECT_FLOAT_EQ(camera->fov().value(), 60.0f);
22 EXPECT_FLOAT_EQ(camera->aspect().value(), 16.0f / 9.0f);
23 EXPECT_FLOAT_EQ(camera->near().value(), 0.1f);
24 EXPECT_FLOAT_EQ(camera->far().value(), 100.0f);
25
26 // 验证默认位置和方向
27 EXPECT_FLOAT_EQ(camera->position().value()[0], 0.0f);
28 EXPECT_FLOAT_EQ(camera->position().value()[1], 0.0f);
29 EXPECT_FLOAT_EQ(camera->position().value()[2], -1.0f);
30
31 EXPECT_FLOAT_EQ(camera->target().value()[0], 0.0f);
32 EXPECT_FLOAT_EQ(camera->target().value()[1], 0.0f);
33 EXPECT_FLOAT_EQ(camera->target().value()[2], 0.0f);
34
35 EXPECT_FLOAT_EQ(camera->up().value()[0], 0.0f);
36 EXPECT_FLOAT_EQ(camera->up().value()[1], 1.0f);
37 EXPECT_FLOAT_EQ(camera->up().value()[2], 0.0f);
38}
39
43TEST(TestPerspectiveCamera, CreateWithCustomValues) {
44 auto camera =
45 std::make_unique<PerspectiveCamera>(45.0f, 4.0f / 3.0f, 1.0f, 1000.0f);
46
47 EXPECT_FLOAT_EQ(camera->fov().value(), 45.0f);
48 EXPECT_FLOAT_EQ(camera->aspect().value(), 4.0f / 3.0f);
49 EXPECT_FLOAT_EQ(camera->near().value(), 1.0f);
50 EXPECT_FLOAT_EQ(camera->far().value(), 1000.0f);
51}
52
56TEST(TestPerspectiveCamera, ProjectionMatrixCalculation) {
57 auto camera =
58 std::make_unique<PerspectiveCamera>(90.0f, 1.0f, 0.1f, 100.0f);
59
60 // 获取投影矩阵
61 const auto& P = camera->projection_matrix();
62
63 // 验证矩阵的基本属性
64 EXPECT_NE(P[0][0], 0.0f);
65 EXPECT_NE(P[1][1], 0.0f);
66 EXPECT_NE(P[2][2], 0.0f);
67 EXPECT_NE(P[2][3], 0.0f);
68 EXPECT_EQ(P[3][2], -1.0f);
69
70 // 验证透视投影矩阵的特定值
71 // 对于 90° FOV, aspect=1, near=0.1, far=100
72 float expected_f = 1.0f / tan(90.0f * 3.14159265358979323846f / 360.0f);
73 EXPECT_NEAR(P[0][0], expected_f, 1e-5f);
74 EXPECT_NEAR(P[1][1], expected_f, 1e-5f);
75}
76
80TEST(TestPerspectiveCamera, ViewMatrixLookAt) {
81 auto camera =
82 std::make_unique<PerspectiveCamera>(60.0f, 16.0f / 9.0f, 0.1f, 100.0f);
83
84 // 设置标准相机位置和方向
85 camera->position().value() = {0.0f, 0.0f, -5.0f};
86 camera->target().value() = {0.0f, 0.0f, 0.0f};
87 camera->up().value() = {0.0f, 1.0f, 0.0f};
88
89 // 获取视图矩阵
90 const auto& V = camera->view_matrix();
91
92 // 验证视图矩阵的基本属性
93 // 对于标准look-at,Z轴应该指向相机前方
94 EXPECT_NEAR(V[0][2], 0.0f, 1e-5f);
95}
96
97TEST(TestPerspectiveCamera, VPTransformWholeVectors_Strict) {
98 auto cam = std::make_unique<PerspectiveCamera>(60.0f, // fovY
99 16.0f / 9.0f, // aspect
100 0.1f, // near
101 100.0f); // far
102
103 cam->set_position(0, 0, -5)->set_target(0, 0, 0)->set_up(0, 1, 0);
104
105 const auto& V = cam->view_matrix();
106 const auto& P = cam->projection_matrix();
107 const auto VP = P ^ V;
108 const auto VP_inv = VP.inv();
109
110 // 预计算常用量
111 const float n = 0.1f;
112 const float f = 100.0f;
113 const float a = 16.0f / 9.0f;
114 const float tanHalf = std::tan(60.0f * 0.5f * float(xcmath::PI) / 180.0f);
115 const float halfH = n * tanHalf;
116 const float halfW = a * halfH;
117
118 auto worldFromNDC = [&](float x_ndc, float y_ndc,
119 float z_ndc) -> xcmath::vec<float_t, 3> {
120 // Compute clip_w from depth value
121 float clip_w = (2.0f * f * n) / (f + n - z_ndc * (f - n));
122
123 // Reconstruct clip space coordinates
124 float clip_x = x_ndc * clip_w;
125 float clip_y = y_ndc * clip_w;
126 float clip_z = z_ndc * clip_w;
127
128 // Transform clip space to world space using inverse VP matrix
129 xcmath::vec<float_t, 4> clip{clip_x, clip_y, clip_z, clip_w};
130 xcmath::vec<float_t, 4> world4 = VP_inv ^ clip;
131 return world4.xyz() / world4.w();
132 };
133
134 // 27 点格网测试
135 for (int iz = -1; iz <= 1; ++iz) {
136 for (int iy = -1; iy <= 1; ++iy) {
137 for (int ix = -1; ix <= 1; ++ix) {
138 xcmath::vec<float_t, 3> ndc{float(ix), float(iy), float(iz)};
139 auto world = worldFromNDC(ndc.x(), ndc.y(), ndc.z());
140
141 // 正向再变换一次
143 VP ^ xcmath::vec<float_t, 4>{world.x(), world.y(),
144 world.z(), 1.0f};
145 xcmath::vec<float_t, 3> back = clip.xyz() / clip.w();
146
147 EXPECT_NEAR(back.x(), ndc.x(), 1e-4f);
148 EXPECT_NEAR(back.y(), ndc.y(), 1e-4f);
149 EXPECT_NEAR(back.z(), ndc.z(), 1e-4f);
150 }
151 }
152 }
153}
154
155} // namespace xcal::camera
Vector class template
Definition vec.hpp:206
constexpr const vec< _Tp, 3 > & xyz() const
Definition vec.hpp:570
constexpr _Tp & x()
Get the item at index 0
Definition vec.hpp:454
constexpr _Tp & w()
Get the item at index 3
Definition vec.hpp:487
constexpr _Tp & y()
Get the item at index 1
Definition vec.hpp:465
constexpr _Tp & z()
Get the item at index 2
Definition vec.hpp:476
PerspectiveCamera 测试套件
TEST(TestPerspectiveCamera, CreateWithDefaultValues)
测试默认构造函数
constexpr long double PI
Pi constant
透视相机类