how does GLM handle translation

后端 未结 2 1816
爱一瞬间的悲伤
爱一瞬间的悲伤 2021-01-15 09:41

The OpenGL maths library(GLM) uses the following algorithm to compute the translation matrix:

//taken from source code
template

        
相关标签:
2条回答
  • 2021-01-15 10:04

    OpenGL Mathematics (GLM) is based on the OpenGL Shading Language (GLSL). What glm::translate actually does is to set up a translation matrix and multiply the input matrix by the translation. It computes m*t in the meaning of GLSL Vector and Matrix Operations:

    mat<4, 4, T, Q> Result(m);
    Result[3] = m[0] * v[0] + m[1] * v[1] + m[2] * v[2] + m[3];
    

    (In the following Result is substituted by R)

    Note, m[0] * v[0] multiplies each component of the column m[0] by the scalar v[0]. The result is the vector (m[0][0]*v[0], m[0][1]*v[0], m[0][2]*v[0], m[0][3]*v[0]).

    So R[3] = m[0]*v[0] + m[1]*v[1] + m[2]*v[2] + m[3] is the same as

    R[3][0] = m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2] + m[3][0]
    R[3][1] = m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2] + m[3][1]
    R[3][2] = m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2] + m[3][2]
    R[3][3] = m[0][3] * v[0] + m[1][3] * v[1] + m[2][3] * v[2] + m[3][3]
    

    glm::translate actually calculates:

    vh = (v[0], v[1], v[2], 1)
    R = m
    R[3][0] = dot( (m[0][0], m[1][0], m[2][0], m[3][0]), vh )
    R[3][1] = dot( (m[0][1], m[1][1], m[2][1], m[3][1]), vh )
    R[3][2] = dot( (m[0][2], m[1][2], m[2][2], m[3][2]), vh )
    R[3][3] = dot( (m[0][3], m[1][3], m[2][3], m[3][3]), vh )
    

    The code above computes the Dot product of the rows from m, by vh. vh is the 4th column of the translation t. Note the translation matrix t is defined as:

         c0  c1  c2  c3 
    ---------------------  
    r0:   1   0   0  v[0]  
    r1:   0   1   0  v[1]
    r2:   0   0   0  v[2]
    r3:   0   0   0  1  
    

    A concatenation of 4x4 matrices (R = m*t) is the Dot product of the rows of m and the columns of t and can be expressed as: (See OpenGL Shading Language 4.60 Specification - 5.10. Vector and Matrix Operations)

    for i from 0 to 3
        for j fro 0 to 3
            R[i][j] = dot( (m[0][j], m[1][j], m[2][j], m[3][j]), t[i] )
    

    Where dot(a, b) == a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3],
    (m[0][j], m[1][j], m[2][j], m[3][j]) is the j-th row of m and
    t[i] is i-th column of t.

    For glm::translate it is sufficient to copy R[0], R[1] and R[2] from m[0], m[1] and m[2].

    e.g. for (i=0, j=0):

    R[0][0] = dot( (m[0][0], m[1][0], m[2][0], m[3][0]), t[0] )
    R[0][0] = dot( (m[0][0], m[1][0], m[2][0], m[3][0]), (1, 0, 0, 0) )
    R[0][0] = m[0][0] * 1 + m[1][0] * 0 + m[2][0] * 0 + m[3][0]) * 0
    R[0][0] = m[0][0]
    

    GLM matrices (as OpenGL matrices) are stored in column major order. If you investigate matrices in the debugger that may lead to confusions.

    If you have the matrix

         c0  c1  c2  c3 
    -------------------  
    r0:  Xx  Yx  Zx  Tx  
    r1:  Xy  Yy  Zy  Ty 
    r2:  Xz  Yz  Zz  Tz  
    r3:   0   0   0   1  
    

    then the memory image of a 4*4 OpenGL matrix looks like this:

    Xx, Xy, Xz, 0, Yx, Yy, Yz, 0, Zx, Zy, Zz, 0, Tx, Ty, Tz, 1
    

    If you investigate it in a debugger, it may look like:

    [ [ Xx, Xy, Xz, 0 ],
      [ Yx, Yy, Yz, 0 ],
      [ Zx, Zy, Zz, 0 ],
      [ Tx, Ty, Tz, 1 ] ]
    
    0 讨论(0)
  • 2021-01-15 10:14

    The technical details of as to how the math is done is magnificiently done in @Rabbid76's answer, but if anyone would like to understand why m*t is computed instead of t*m then here's the answer: Computing the matrix tm like this:

    here, you're taking the standard basis as the basis vectors for linear combination, so, essentially you're transforming in world space coordinates. but

    doing it the other way around and computing mt means now you're essentially taking the basis as the m[0], m[1] and m[2] respectively, so you're transforming in the local space given by the basis, and since this is essentially a model matrix, we just call it model space.

    That is probably one way to view it if you're only considering translation, but what if you're handling composite transformations like below:

    M=glm::translate(M,T);
    R=glm::rotate(M,angle,Rot_axis);  
    

    Here the model matrix is M(initialized to identity at first), T is the translation matrix, R the rotation matrix and others are straightforward above.

    So the transformation sequence that happens in the above code is:
    M.T.R
    and say this is applied to the vector v=[x, y, z, 1], the vector undergoes first a rotation, then a translation and then only the model transformation is done, if it helps, you may see it like this:
    M.(T.R.v)

    0 讨论(0)
提交回复
热议问题