矩阵 class 乘法产生不正确的结果

Matrix class multiplication yielding incorrect results

我为作业创建了一个基本的数学库,涉及 Matrix3 和 Matrix4 类以及其他一些类。对于 OpenGL,为了将立方体投影到屏幕上,我为 Projection * View * Model 算法创建了一个 lookAt 函数和一个 Perspective 函数,可以为场景生成正确的视图。它们旨在替代 GLM library/other 库中的相应函数,因为它们将来必须与我的 Matrix 类进行交互。

lookAt 函数产生了正确的结果,Projection 函数产生了接近的结果,通过一些临时的手动调整使其提供相同的结果。但是,当我将它们与 Projection * View (lookat) * Model(单位矩阵)相乘时,我的库产生与 GLM(MVP Matrix4)完全不同的结果。我的与图形计算器相匹配,而 GLM 则没有。 GLM 实际上在屏幕上正确显示了立方体,我的看起来好像立方体已经内爆了。矩阵本身几乎没有相似性。

GLM 库

        // Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
    glm::mat4 ProjectionGLM = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);
    // Camera matrix
    glm::mat4 ViewGLM = glm::lookAt(
        glm::vec3(4, 3, 3), // Camera is at (4,3,3), in World Space
        glm::vec3(0, 0, 0), // and looks at the origin
        glm::vec3(0, 1, 0)  // Head is up (set to 0,-1,0 to look upside-down)
        );
    // Model matrix : an identity matrix (model will be at the origin)
    glm::mat4 ModelGLM = glm::mat4(1.0f);  // Changes for each model !
                                        // Our ModelViewProjection : multiplication of our 3 matrices
    glm::mat4 MVP = ProjectionGLM * ViewGLM * ModelGLM; // Remember, matrix multiplication is the other way around
    glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);

输出矩阵(MVP Matrix4)

自定义库

    Vector3 vectornew1(4, 3, 3);
    Vector3 vectornew2(0, 0, 0); 
    Vector3 vectornew3(0, 1, 0);

    // Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
    Matrix4 Projection = Matrix4::Perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);
    Projection = Matrix4::Transpose(Projection);
    // Camera matrix
    Matrix4 View = Matrix4::lookAt(
        vectornew1, // Camera is at (4,3,3), in World Space
        vectornew2, // and looks at the origin
        vectornew3  // Head is up (set to 0,-1,0 to look upside-down)
        );
    // Model matrix : an identity matrix (model will be at the origin)
    Matrix4 Model = Matrix4::Identity();  // Changes for each model !
                                        // Our ModelViewProjection : multiplication of our 3 matrices
    Matrix4 MVP = Projection * View * Model; // Remember, matrix multiplication is the other way around
    glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP.data[0][0]);

自定义Matrix4乘法代码:

temp.data[0][0] = this->data[0][0] * Other.data[0][0] + this->data[0][1] * Other.data[1][0] + this->data[0][2] * Other.data[2][0] + this->data[0][3] * Other.data[3][0];
temp.data[0][1] = this->data[0][0] * Other.data[0][1] + this->data[0][1] * Other.data[1][1] + this->data[0][2] * Other.data[2][1] + this->data[0][3] * Other.data[3][1];
temp.data[0][2] = this->data[0][0] * Other.data[0][2] + this->data[0][1] * Other.data[1][2] + this->data[0][2] * Other.data[2][2] + this->data[0][3] * Other.data[3][2];
temp.data[0][3] = this->data[0][0] * Other.data[0][3] + this->data[0][1] * Other.data[1][3] + this->data[0][2] * Other.data[2][3] + this->data[0][3] * Other.data[3][3];

temp.data[1][0] = this->data[1][0] * Other.data[0][0] + this->data[1][1] * Other.data[1][0] + this->data[1][2] * Other.data[2][0] + this->data[1][3] * Other.data[3][0];
temp.data[1][1] = this->data[1][0] * Other.data[0][1] + this->data[1][1] * Other.data[1][1] + this->data[1][2] * Other.data[2][1] + this->data[1][3] * Other.data[3][1];
temp.data[1][2] = this->data[1][0] * Other.data[0][2] + this->data[1][1] * Other.data[1][2] + this->data[1][2] * Other.data[2][2] + this->data[1][3] * Other.data[3][2];
temp.data[1][3] = this->data[1][0] * Other.data[0][3] + this->data[1][1] * Other.data[1][3] + this->data[1][2] * Other.data[2][3] + this->data[1][3] * Other.data[3][3];

temp.data[2][0] = this->data[2][0] * Other.data[0][0] + this->data[2][1] * Other.data[1][0] + this->data[2][2] * Other.data[2][0] + this->data[2][3] * Other.data[3][0];
temp.data[2][1] = this->data[2][0] * Other.data[0][1] + this->data[2][1] * Other.data[1][1] + this->data[2][2] * Other.data[2][1] + this->data[2][3] * Other.data[3][1];
temp.data[2][2] = this->data[2][0] * Other.data[0][2] + this->data[2][1] * Other.data[1][2] + this->data[2][2] * Other.data[2][2] + this->data[2][3] * Other.data[3][2];
temp.data[2][3] = this->data[2][0] * Other.data[0][3] + this->data[2][1] * Other.data[1][3] + this->data[2][2] * Other.data[2][3] + this->data[2][3] * Other.data[3][3];

temp.data[3][0] = this->data[3][0] * Other.data[0][0] + this->data[3][1] * Other.data[1][0] + this->data[3][2] * Other.data[2][0] + this->data[3][3] * Other.data[3][0];
temp.data[3][1] = this->data[3][0] * Other.data[0][1] + this->data[3][1] * Other.data[1][1] + this->data[3][2] * Other.data[2][1] + this->data[3][3] * Other.data[3][1];
temp.data[3][2] = this->data[3][0] * Other.data[0][2] + this->data[3][1] * Other.data[1][2] + this->data[3][2] * Other.data[2][2] + this->data[3][3] * Other.data[3][2];
temp.data[3][3] = this->data[3][0] * Other.data[0][3] + this->data[3][1] * Other.data[1][3] + this->data[3][2] * Other.data[2][3] + this->data[3][3] * Other.data[3][3];

GLM 可以用矩阵乘法做什么来产生截然不同的结果?我的方法与图形计算器相匹配,并使用单位矩阵产生正确的结果。

我在我的引擎中尝试了你的乘法(也基于 glm,或者至少针对它进行了测试),当我交换这个和其他时,结果是正确的。所以这应该是正确的:

temp.data[0][0] = Other.data[0][0] * this->data[0][0] + Other.data[0][1] * this->data[1][0] + Other.data[0][2] * this->data[2][0] + Other.data[0][3] * this->data[3][0];
temp.data[0][1] = Other.data[0][0] * this->data[0][1] + Other.data[0][1] * this->data[1][1] + Other.data[0][2] * this->data[2][1] + Other.data[0][3] * this->data[3][1];
temp.data[0][2] = Other.data[0][0] * this->data[0][2] + Other.data[0][1] * this->data[1][2] + Other.data[0][2] * this->data[2][2] + Other.data[0][3] * this->data[3][2];
temp.data[0][3] = Other.data[0][0] * this->data[0][3] + Other.data[0][1] * this->data[1][3] + Other.data[0][2] * this->data[2][3] + Other.data[0][3] * this->data[3][3];
temp.data[1][0] = Other.data[1][0] * this->data[0][0] + Other.data[1][1] * this->data[1][0] + Other.data[1][2] * this->data[2][0] + Other.data[1][3] * this->data[3][0];
temp.data[1][1] = Other.data[1][0] * this->data[0][1] + Other.data[1][1] * this->data[1][1] + Other.data[1][2] * this->data[2][1] + Other.data[1][3] * this->data[3][1];
temp.data[1][2] = Other.data[1][0] * this->data[0][2] + Other.data[1][1] * this->data[1][2] + Other.data[1][2] * this->data[2][2] + Other.data[1][3] * this->data[3][2];
temp.data[1][3] = Other.data[1][0] * this->data[0][3] + Other.data[1][1] * this->data[1][3] + Other.data[1][2] * this->data[2][3] + Other.data[1][3] * this->data[3][3];
temp.data[2][0] = Other.data[2][0] * this->data[0][0] + Other.data[2][1] * this->data[1][0] + Other.data[2][2] * this->data[2][0] + Other.data[2][3] * this->data[3][0];
temp.data[2][1] = Other.data[2][0] * this->data[0][1] + Other.data[2][1] * this->data[1][1] + Other.data[2][2] * this->data[2][1] + Other.data[2][3] * this->data[3][1];
temp.data[2][2] = Other.data[2][0] * this->data[0][2] + Other.data[2][1] * this->data[1][2] + Other.data[2][2] * this->data[2][2] + Other.data[2][3] * this->data[3][2];
temp.data[2][3] = Other.data[2][0] * this->data[0][3] + Other.data[2][1] * this->data[1][3] + Other.data[2][2] * this->data[2][3] + Other.data[2][3] * this->data[3][3];
temp.data[3][0] = Other.data[3][0] * this->data[0][0] + Other.data[3][1] * this->data[1][0] + Other.data[3][2] * this->data[2][0] + Other.data[3][3] * this->data[3][0];
temp.data[3][1] = Other.data[3][0] * this->data[0][1] + Other.data[3][1] * this->data[1][1] + Other.data[3][2] * this->data[2][1] + Other.data[3][3] * this->data[3][1];
temp.data[3][2] = Other.data[3][0] * this->data[0][2] + Other.data[3][1] * this->data[1][2] + Other.data[3][2] * this->data[2][2] + Other.data[3][3] * this->data[3][2];
temp.data[3][3] = Other.data[3][0] * this->data[0][3] + Other.data[3][1] * this->data[1][3] + Other.data[3][2] * this->data[2][3] + Other.data[3][3] * this->data[3][3];