4x4矩阵预乘和后乘

时间:2013-07-22 10:06:14

标签: c++ math opengl matrix

我有以下功能:

void Matrix::Scale(const float xScale, const float yScale, const float zScale)
{
    Matrix scaleMatrix;
    scaleMatrix.m_data[M11] = xScale;
    scaleMatrix.m_data[M22] = yScale;
    scaleMatrix.m_data[M33] = zScale;
    *this *= scaleMatrix;
}

void Matrix::Translate(const float xTranslation, const float yTranslation, const float zTranslation)
{
    Matrix translationMatrix;
    translationMatrix.m_data[M14] = xTranslation;
    translationMatrix.m_data[M24] = yTranslation;
    translationMatrix.m_data[M34] = zTranslation;
    *this *= translationMatrix;
}

我不确定这两个功能的最后几行。我应该进行预乘法还是后乘法(即我现在正在做的事情)。它对这个类的使用有什么影响?我在OpenGL中使用该类,因此任何相似之处都可能有用。

修改

我的着色器代码如下所示:

void main()
{
    gl_Position = vec4(v_xy, 0.0, 1.0) * v_ModelMatrix * v_ViewMatrix * v_ProjectionMatrix;
    f_uv = v_uv;
}

我的矩阵乘法函数如下所示:

// Row 1
result[M11] = lhs[M11] * rhs[M11]   +   lhs[M12] * rhs[M21]   +   lhs[M13] * rhs[M31]   +   lhs[M14] * rhs[M41];    // Column 1
result[M12] = lhs[M11] * rhs[M12]   +   lhs[M12] * rhs[M22]   +   lhs[M13] * rhs[M32]   +   lhs[M14] * rhs[M42];    // Column 2
result[M13] = lhs[M11] * rhs[M13]   +   lhs[M12] * rhs[M23]   +   lhs[M13] * rhs[M33]   +   lhs[M14] * rhs[M43];    // Column 3
result[M14] = lhs[M11] * rhs[M14]   +   lhs[M12] * rhs[M24]   +   lhs[M13] * rhs[M34]   +   lhs[M14] * rhs[M44];    // Column 4

// Row 2
result[M21] = lhs[M21] * rhs[M11]   +   lhs[M22] * rhs[M21]   +   lhs[M23] * rhs[M31]   +   lhs[M24] * rhs[M41];    // Column 1
result[M22] = lhs[M21] * rhs[M12]   +   lhs[M22] * rhs[M22]   +   lhs[M23] * rhs[M32]   +   lhs[M24] * rhs[M42];    // Column 2
result[M23] = lhs[M21] * rhs[M13]   +   lhs[M22] * rhs[M23]   +   lhs[M23] * rhs[M33]   +   lhs[M24] * rhs[M43];    // Column 3
result[M24] = lhs[M21] * rhs[M14]   +   lhs[M22] * rhs[M24]   +   lhs[M23] * rhs[M34]   +   lhs[M24] * rhs[M44];    // Column 4

// Row 3
result[M31] = lhs[M31] * rhs[M11]   +   lhs[M32] * rhs[M21]   +   lhs[M33] * rhs[M31]   +   lhs[M34] * rhs[M41];    // Column 1
result[M32] = lhs[M31] * rhs[M12]   +   lhs[M32] * rhs[M22]   +   lhs[M33] * rhs[M32]   +   lhs[M34] * rhs[M42];    // Column 2
result[M33] = lhs[M31] * rhs[M13]   +   lhs[M32] * rhs[M23]   +   lhs[M33] * rhs[M33]   +   lhs[M34] * rhs[M43];    // Column 3
result[M34] = lhs[M31] * rhs[M14]   +   lhs[M32] * rhs[M24]   +   lhs[M33] * rhs[M34]   +   lhs[M34] * rhs[M44];    // Column 4

// Row 4
result[M41] = lhs[M41] * rhs[M11]   +   lhs[M42] * rhs[M21]   +   lhs[M43] * rhs[M31]   +   lhs[M44] * rhs[M41];    // Column 1
result[M42] = lhs[M41] * rhs[M12]   +   lhs[M42] * rhs[M22]   +   lhs[M43] * rhs[M32]   +   lhs[M44] * rhs[M42];    // Column 2
result[M43] = lhs[M41] * rhs[M13]   +   lhs[M42] * rhs[M23]   +   lhs[M43] * rhs[M33]   +   lhs[M44] * rhs[M43];    // Column 3
result[M44] = lhs[M41] * rhs[M14]   +   lhs[M42] * rhs[M24]   +   lhs[M43] * rhs[M34]   +   lhs[M44] * rhs[M44];    // Column 4

我的印象是,如果你对你的矩阵进行后乘(即viewMatrix = transform * viewMatrix;),那么你的着色器代码需要按照我现在的相反顺序应用MVP?

EDIT2:

http://scratchapixel.com/lessons/3d-basic-lessons/lesson-4-geometry/conventions-again-row-major-vs-column-major-vector/上的摘要表让我感到困惑,因为我使用OpenGL后复制(表示列主要),但我的矩阵在内存中显示为行主?

2 个答案:

答案 0 :(得分:2)

矩阵是关联的,这意味着

ABC = (AB)C = A(BC)

因此,只要您保持订单相同,首先将(AB vs BC)实际乘以哪个矩阵并不重要。预乘与后乘是ABBA的关系。

话虽如此,this question解释了如果您希望转换按照您想要的方式出现,您应该将缩放/旋转/翻译相乘的顺序。如果使用行矩阵而不是列矩阵,则可以反转顺序并转置每个元素。 Here's a slideshow给出了更好的解释(跳转到幻灯片19)。

严格地说,矩阵的列矩阵是 T * R * S ,或者是Translate * Rotate * Scale。因此,如果你从身份开始,后乘(你正在做的)是正确的。如果您更改为预乘,则 X L 的转换将最终为 L * X ,所以为了获得 T * R * S ,您可以按顺序执行调用。

答案 1 :(得分:0)

创建一个类矩阵,以保存4x1大小矩阵的实数。保持 数组中的数字。在main中,创建两个对象,A和B. 由用户填写。创建另一个对象C. C实际上是A的总和 和B.你应该有一个函数,add,它接收两个矩阵 对象并将它们作为单独的矩阵返回。 矩阵C = add(A,B); 在屏幕上以适当的格式显示三个对象.in c ++