如果我有一个矩阵,那么点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 :(得分:1)
-T
和T
的顺序:
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 ) );
这意味着如果要围绕其原点旋转矩阵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;