CG3 - 数学库与测试

07 Jul 2015

0、概述

数学库是软件渲染器的核心部分之一,没有数学库的支持,甚至无法完成基本的 3D 物体坐标转换与显示。

数学库由多个文件构成:

点、线、面相关介绍在上一节已基本涵盖,本节主要介绍矩阵和四元数的库支持。数学库需要编写大量容易出错的代码,从点线面到矩阵运算,前一步产生的错误很可能在后一步累加放大成更大的错误,所以需要有尽可能完备的测试去保证数学库的正确性。

1、矩阵

矩阵常用于数据变换,如平移、缩放、旋转等。在设计实现矩阵是,我既使用了重载运算符,也使用了成员运算函数。重载运算符只限于对同一类型的数据结构使用,而成员运算函数则重载了多个版本对应于不同的数据结构。以下的运算中,均以 Matrix4x4 矩阵为例。

1)平移

$$ p' = p * M_t \\ = \begin{bmatrix}x & y & z & 1\end{bmatrix} * \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ \Delta_x & \Delta_y & \Delta_z & 1 \end{bmatrix} \\ = \begin{bmatrix}x + \Delta_x & y + \Delta_y & z + \Delta_z & 1\end{bmatrix} $$

2)缩放

$$ p' = p * M_s \\ = \begin{bmatrix}x & y & z & 1\end{bmatrix} * \begin{bmatrix} sx & 0 & 0 & 0 \\ 0 & sy & 0 & 0 \\ 0 & 0 & sz & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \\ = \begin{bmatrix}sx*x & sy*y & sz*z & 1\end{bmatrix} $$

3)旋转

旋转可以绕 x 轴、y 轴、z 轴进行,绕任何轴时,该分量保持不变。以下以绕 z 轴旋转为例:

$$ p' = p * M_z \\ = \begin{bmatrix}x & y & z & 1\end{bmatrix} * \begin{bmatrix} \cos(\theta) & \sin(\theta) & 0 & 0 \\ -\sin(\theta) & \cos(\theta) & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \\ = \begin{bmatrix} x*\cos(\theta) - y*\sin(\theta) & x*\sin(\theta) + y*\cos(\theta) & z & 1 \end{bmatrix} $$

2、四元数

pass

3、测试

测试是系统功能性的保证,设计完备的测试并不比实现功能简单,测试的目标不仅仅是覆盖 API,更多地是尽可能提供实际场景中的数据与环境,及早地发现每个部分元功能的错误。

实现测试时,我并没有使用 assert.h 中的 assert,而是自己定义了一个函数 UT_ASSERT,在检测条件的同时,将错误信息打印并写入文件。C++ 中的 assert 功能比较单一,仅具有比较功能,相对来说 Python 中的 unittest 就很好用。如果要在 C++ assert 中实现更详细的信息反馈,还是需要自己实现或者使用一些单元测试框架,例如 gtest。 (在学习制作这一部分时,我阅读了《Effective C++》的部分章节,导致前后编码风格发生了一定的变化。)

1
2
3
4
5
6
7
8
inline void UT_ASSERT(bool condition, std::string output)
{
    if (condition)
    {
        std::cout << output << std::endl;
        TestLog << output << std::endl;
    }
}

如果你发现我文章中的问题或希望与我交流,可以给我发邮件:plinux@qq.com

如果你读后有些许收获,也可以到我的 Github 点赞支持

© 2015 plinx