快速旋转矩阵的当前位置

时间:2018-02-07 01:19:51

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

如果我有一个矩阵,那么点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;

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

2 个答案:

答案 0 :(得分: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来自未知来源而您需要事后修改,事实上,确实没有其他选择。

答案 1 :(得分:1)

通常,转换矩阵(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 ) );

enter image description here


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

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;