Search code examples
c++mathmatrixeigenglm-math

Eigen and glm products produce different results


I am trying to replace glm with eigen in an application I am writing, but I am running into an esoteric problem.

This would be the relevant code:

glm::mat4 EigenToGlmMat(const Eigen::Matrix4f& v)
{
    glm::mat4 ret;
    ret[0][0] = v(0,0);
    ret[0][1] = v(0,1);
    ret[0][2] = v(0,2);
    ret[0][3] = v(0,3);

    ret[1][0] = v(1,0);
    ret[1][1] = v(1,1);
    ret[1][2] = v(1,2);
    ret[1][3] = v(1,3);

    ret[2][0] = v(2,0);
    ret[2][1] = v(2,1);
    ret[2][2] = v(2,2);
    ret[2][3] = v(2,3);

    ret[3][0] = v(3,0);
    ret[3][1] = v(3,1);
    ret[3][2] = v(3,2);
    ret[3][3] = v(3,3);

    return ret;
}


    Eigen::Matrix4f mp = camera->GetProjectionMatrix();
    Eigen::Matrix4f mv = camera->GetViewMatrix();

    mat4 vp_mat = EigenToGlmMat(mp) * EigenToGlmMat(mv);
    mat4 tmp =  EigenToGlmMat(mp * mv);
    cout << glm::to_string(vp_mat) << endl << endl;
    cout << glm::to_string(tmp) << endl << endl;

Now consider the lines:

    auto mp = camera->GetProjectionMatrix();
    auto mv = camera->GetViewMatrix();

    mat4 vp_mat = EigenToGlmMat(mp) * EigenToGlmMat(mv);
    mat4 tmp =  EigenToGlmMat(mp * mv);

Those 2 results should be equivalent, after all they are merely computing a product of matrices and the matrix inputs are the same. However this is the output:

mat4x4(
(2.414213, 0.000000, 0.000000, 0.000000), 
(0.000000, -2.414213, 0.000000, 0.000000), 
(0.000000, 0.000000, 1.002002, 1.000000), 
(0.000000, 0.000000, 4.308809, 4.500000))

mat4x4(
(2.414213, 0.000000, -0.000000, 0.000000), 
(0.000000, -2.414213, -0.000000, 0.000000), 
(0.000000, 0.000000, 5.502002, -1.000000), 
(0.000000, 0.000000, 0.200200, 0.000000))

The only functional difference is that computes the product using glm and the other eigen. How is it possible I am getting different results? Is this an error in Eigen?

It is not a transposition problem btw, this is the output of the 2 matrices before and after being cast by EigenToGlmMat

2.41421       0       0       0
      0 2.41421       0       0
      0       0  -1.002      -1
      0       0 -0.2002       0


  1  0 -0  0
  0 -1 -0  0
 -0  0 -1  0
 -0 -0 -6  1

mat4x4(
(2.414213, 0.000000, 0.000000, 0.000000), 
(0.000000, 2.414213, 0.000000, 0.000000), 
(0.000000, 0.000000, -1.002002, -1.000000), 
(0.000000, 0.000000, -0.200200, 0.000000))

mat4x4(
(1.000000, 0.000000, -0.000000, 0.000000), 
(0.000000, -1.000000, -0.000000, 0.000000), 
(-0.000000, 0.000000, -1.000000, 0.000000), 
(-0.000000, -0.000000, -6.000000, 1.000000))

Solution

  • You are unknowingly transposing matrices. When accessing an Eigen::Matrix4f using (i, j), you are accessing row i and column j. glm::mat4's subscript operator returns you a column, so with [i][j] you are accessing column i and row j.

    Here's the solution:

    glm::mat4 EigenToGlmMat(const Eigen::Matrix4f& v)
    {
        glm::mat4 result;
        for (size_t i = 0; i < 4; ++i) {
            for (size_t j = 0; j < 4; ++j) {
                result[i][j] = v(j, i);
            }
        }
    
        return result;
    }