【发布时间】:2019-01-11 03:45:22
【问题描述】:
我正在使用 OpenGL,我决定做的一件事是创建自己的 Matrix 类,而不是使用 glm 的矩阵。 Matrix 类具有平移、旋转和缩放对象的方法,如下所示:
Matrix4 Matrix4::translate(Matrix4& matrix, Vector3& translation)
{
Vector4 result(translation, 1.0f);
result.multiply(matrix);
matrix.mElements[3 * 4 + 0] = result.x;
matrix.mElements[3 * 4 + 1] = result.y;
matrix.mElements[3 * 4 + 2] = result.z;
return matrix;
}
Matrix4 Matrix4::rotate(Matrix4& matrix, float angle, Vector3& axis)
{
if (axis.x == 0 && axis.y == 0 && axis.z == 0)
return matrix;
float r = angle;
float s = sin(r);
float c = cos(r);
float omc = 1.0f - cos(r);
float x = axis.x;
float y = axis.y;
float z = axis.z;
matrix.mElements[0 + 0 * 4] = c + x * x * omc;
matrix.mElements[1 + 0 * 4] = x * y * omc - z * s;
matrix.mElements[2 + 0 * 4] = z * x * omc + y * s;
matrix.mElements[0 + 1 * 4] = x * y * omc + z * s;
matrix.mElements[1 + 1 * 4] = c + y * y * omc;
matrix.mElements[2 + 1 * 4] = z * y * omc - x * s;
matrix.mElements[0 + 2 * 4] = x * z * omc - y * s;
matrix.mElements[1 + 2 * 4] = y * z * omc + x * s;
matrix.mElements[2 + 2 * 4] = c + z * z * omc;
return matrix;
}
Matrix4 Matrix4::scale(Matrix4& matrix, Vector3& scaler)
{
matrix.mElements[0 + 0 * 4] *= scaler.x;
matrix.mElements[1 + 0 * 4] *= scaler.x;
matrix.mElements[2 + 0 * 4] *= scaler.x;
matrix.mElements[0 + 1 * 4] *= scaler.y;
matrix.mElements[1 + 1 * 4] *= scaler.y;
matrix.mElements[2 + 1 * 4] *= scaler.y;
matrix.mElements[0 + 2 * 4] *= scaler.z;
matrix.mElements[1 + 2 * 4] *= scaler.z;
matrix.mElements[2 + 2 * 4] *= scaler.z;
matrix.mElements[3 + 3 * 4] = 1;
return matrix;
}
当我在 while 循环中调用 translate、rotate 和 scale 方法时(按此特定顺序),它会执行我想要的操作,即平移对象,然后围绕其本地原点旋转并缩放它。但是,当我想切换顺序所以我先调用旋转然后平移时,我希望它这样做:
但我的代码并没有这样做。相反,它这样做:
我该怎么做才能让我的对象只围绕屏幕中心旋转,而不是围绕它的本地原点旋转? 我唯一的猜测是我在转换矩阵上添加旋转计算时做错了,但我仍然不知道它是什么。
编辑:我需要指出的一件事是,如果我忽略了旋转方法,而我只处理平移和缩放,它们会按照我期望的方式进行,首先是平移,其次是旋转,然后是旋转,其次是平移顺序。
编辑 2:这是我在 while 循环中调用这些函数的方式。
Matrix4 trans = Matrix4(1.0f);
trans = Matrix4::rotate(trans, (float)glfwGetTime(), Vector3(0.0f, 0.0f, 1.0f));
trans = Matrix4::translate(trans, Vector3(0.5f, -0.5f, 0.0f));
trans = Matrix4::scale(trans, Vector3(0.5f, 0.5f, 1.0f));
shader.setUniformMatrix4f("uTransform", trans);
【问题讨论】:
-
您是否尝试过将最原始的操作写成矩阵,然后手动将它们相乘以获得结果矩阵?直接输入很容易出错。顺便说一句,您使用 3D 坐标(“z 轴”)但您只有 3x3 矩阵 - 为什么不是齐次坐标?没有这些你怎么做?
-
我不认为你的矩阵乘法是正确的。一般来说,旋转和缩放也会修改存储平移的元素。
-
@Aziuth,是的,我已经尝试过两个矩阵的简单乘法,我知道我的矩阵乘法方法是正确的。
-
@BDL,我确保所有的平移、旋转和缩放计算都存储在一个矩阵中。
-
添加主代码,调用这两个函数的地方。
标签: c++ opengl matrix transformation coordinate-transformation