这是从 Austin Morlan 的 ECS 示例中获得的代码。
class Mat44
{
public:
Mat44()
{
//@formatter:off
m[0][0] = 1.0f; m[0][1] = 0.0f; m[0][2] = 0.0f; m[0][3] = 0.0f;
m[1][0] = 0.0f; m[1][1] = 1.0f; m[1][2] = 0.0f; m[1][3] = 0.0f;
m[2][0] = 0.0f; m[2][1] = 0.0f; m[2][2] = 1.0f; m[2][3] = 0.0f;
m[3][0] = 0.0f; m[3][1] = 0.0f; m[3][2] = 0.0f; m[3][3] = 1.0f;
//@formatter:on
}
Mat44 operator*(Mat44 const& rhs)
{
Mat44 result;
for (int row = 0; row < 4; ++row)
{
for (int col = 0; col < 4; ++col)
{
float sum = 0.0f;
for (int i = 0; i < 4; ++i)
{
sum += m[row][i] * rhs.m[i][col];
}
result.m[row][col] = sum;
}
}
return result;
}
Vec4 operator*(Vec4 const& rhs)
{
return Vec4(
(rhs.x * m[0][0]) + (rhs.y * m[0][1]) + (rhs.z * m[0][2]) + (rhs.w * m[0][3]),
(rhs.x * m[1][0]) + (rhs.y * m[1][1]) + (rhs.z * m[1][2]) + (rhs.w * m[1][3]),
(rhs.x * m[2][0]) + (rhs.y * m[2][1]) + (rhs.z * m[2][2]) + (rhs.w * m[2][3]),
(rhs.x * m[3][0]) + (rhs.y * m[3][1]) + (rhs.z * m[3][2]) + (rhs.w * m[3][3]));
}
float m[4][4];
};
问题:
请简单地向我解释一下 for 循环中发生了什么? (我的理解:对于每一行,列都被完全遍历,声明一个变量 sum 来存储乘法的结果,然后设置一个索引(多维数组的跟踪器)来跟踪遍历的每个索引,本质上是一种排序如果到目前为止我是正确的,我无法从这里开始,也许有更好的方法来帮助我理解这里发生的事情?
这些是 GLM 库隐藏的抽象吗?
我的CPP知识是中级的,我无法理解为什么操作符重载需要一个参数
最后,对于Vec4类,我什至不知道发生了什么?
对于运算符重载,如果声明为类成员的二元运算符隐式采用
*this
的一个参数,即对象本身,因此仅使用一个参数进行声明。例如。 Mat44 operator*(Mat44 const& rhs)
允许使用以下代码:
Mat44 a{}, b{};
Mat44 c = a * b; // Mat44::operator* is called for `a`
同样的情况也发生在
Vec4
。
以此类推,一元运算符(增量除外)作为成员声明时根本不带参数,因为它们显然只有一个。 运算符重载是C++中的一个基本主题,不是可选的。
Mat44::operator*
表示矩阵乘法。向量是矩阵的一种情况,其中一维等于 1(根据具体情况,它是向量列或向量行)。传统上将向量表示为单独的类,因为多种优化和规则会影响它,并且语义上向量列和向量行是等效的。
这些不是“隐藏的抽象”,而是部分常见的数学知识。在常规课程中,您将在实际学习编程之前了解这一点。由于
a*b
不等于b*a
,如果它们是矩阵,则运算符必须是成员以确保运算顺序。计算机图形学很大程度上依赖于“线性代数”,尤其是。向量数学。