【问题标题】:fast way to rotate a matrix about its current position围绕当前位置旋转矩阵的快速方法
【发布时间】:2018-07-17 04:41:25
【问题描述】:

如果我有一个矩阵,那么点 O(0,0,0) 将被转换为某个点 P(x, y, z)。因此,围绕当前位置旋转矩阵实际上是将矩阵乘以围绕 P 的旋转矩阵。

所以我想要一个类似的函数:

mat4 rotate(mat4 matrix, vec3 axis, float angle);

我目前的想法是:

vec4 p = {0, 0, 0, 1};

p = p * matrix;

generate translation matrix T, from point p

generate rotation matrix R, from axis and angle

return matrix * T * R * -T;

但我觉得应该有更有效的方法来做到这一点......

【问题讨论】:

  • 不是真的,我就是这样做的。
  • 矩阵乘以 (0,0,0) 得到 (0,0,0)。
  • @beta 但它不是 (0, 0, 0) 它是 (0, 0, 0, 1),因为它是一个点

标签: c++ opengl matrix linear-algebra coordinate-transformation


【解决方案1】:

是的,我就是这样做的。但是一个微妙的更正,颠倒-TT的顺序:

  return matrix * -T * R * T

您想首先“撤消”matrix 的平移原点,然后旋转,然后重新做平移原点。这更容易看到,例如,将传统的缩放/旋转/平移矩阵 (S * R2 * T) 展开,然后您可以更轻松地看到:

  (S * R2 * T) * -T * R * T

正在做你想做的事。

编辑:关于效率,完全取决于使用情况。不,这不是“很好”——通常你有更多关于matrix 的信息,可以让你以一种不那么迂回的方式做到这一点。例如,如果矩阵是从上面的S * R * T 构造的,显然我们可以简单地改变矩阵的构造方式——S * R2 * R * T,将旋转注入它应该的位置,而不必“撤消”任何东西.

但除非您在 10K+ 矩阵上实时执行此操作每次都需要重新计算,否则这应该不是问题。

如果matrix 来自未知来源,您需要事后修改它,确实,真的没有其他选择。

【讨论】:

    【解决方案2】:

    通常,转换矩阵 (OpenGL/glsl/glm) 是这样定义的:

    mat4 m44 = mat4(
        vec4( Xx, Xy, Xz, 0.0),   // x-axis
        vec4( Yx, Xy, Yz, 0.0),   // y-axis
        vec4( Zx  Zy  Zz, 0.0),   // z-axis
        vec4( Tx, Ty, Tz, 1.0) ); // translation
    

    翻译矩阵如下所示:

    mat4 translate = mat4(
        vec4( 0.0, 0.0, 0.0, 0.0),
        vec4( 0.0, 0.0, 0.0, 0.0),   
        vec4( 0.0  0.0  0.0, 0.0),  
        vec4( Tx,  Ty,  Tz,  1.0) );
    

    旋转矩阵(例如围绕 Y 轴)如下所示:

    float angle;
    mat4 rotate = mat4(
        vec4( cos(angle),  0, sin(angle), 0 ),
        vec4( 0,           1, 0,          0 ),
        vec4( -sin(angle), 0, cos(angle), 0 ),
        vec4( 0,           0, 0,          1 ) )
    

    矩阵乘法C = A * B 的工作原理如下:

    mat4 A, B, C;
    
    // C = A * B
    for ( int k = 0; k < 4; ++ k )
        for ( int j = 0; j < 4; ++ j )
            C[k][j] = A[0][l] * B[k][0] + A[1][j] * B[k][1] + A[2][j] * B[k][2] +  A[3][j] * B[k][3];
    

    这意味着translate * rotate的结果是:

    mat4 m = mat4(
        vec4( cos(angle),  0,  sin(angle), 0 ),
        vec4( 0,           1,  0,          0 ),
        vec4( -sin(angle), 0,  cos(angle), 0 ),
        vec4( tx,          ty, tz,         1 ) );
    


    这意味着如果要围绕其原点旋转矩阵M,则必须将矩阵拆分为“方向”矩阵和“平移”矩阵。旋转方向矩阵,再次添加平移矩阵:

    mat4 M, R;
    
    float Tx = M[3][0];
    float Ty = M[3][1];
    float Tz = M[3][2];
    
    M[3][0] = 0.0; M[3][1] = 0.0; M[3][2] = 0.0;
    
    mat4 MR = R * M;
    MR[3][0] = Tx; MR[3][1] = Ty; M[3][2] = Tz;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-05-02
      • 1970-01-01
      • 2013-03-26
      • 1970-01-01
      • 2016-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多