将对象从一个坐标系旋转到另一个坐标系
Rotate object from one coordinate system to another
使用 glm
库进行计算。我有一个位于局部坐标系中的网格,其中轴为:
meshUp = glm::vec3(0, 1, 0);
meshForward = glm::vec3(0, 0, -1);
meshRight = glm::vec3(1, 0, 0);
我需要一个矩阵,它将其顶点旋转到具有 3 个给定轴的任何其他新坐标系,fx:
newUp = glm::vec3(-0.85, 0.51, -0.08);
newForward = glm::vec3(0.45, 0.65, -0.61);
newRight = glm::vec3(-0.26, -0.56, -0.79);
无需平移,坐标系共享原点。我可以做到一半,就像这样:
glm::vec3 rotationVecForUpAxis = glm::normalize(glm::cross(meshUp, newUp));
float rotationRadiansForUpAxis = acos(glm::dot(meshUp, newUp));
glm::mat4 rotationMatrix = glm::rotate(glm::mat4(),
rotationRadiansForUpAxis,
rotationVecForUpAxis);
这有效并旋转了网格,因此它的上轴与 newUp
轴对齐。但是,在网格的 meshForward
轴与 newForward
轴对齐之前,网格仍然需要绕 newUp
轴旋转。
有人知道怎么做吗?
你可以查一下数学。但只是为了好玩,我将在这里推导它。
假设在原始坐标系中表示的新基向量是:
[ xnx ] [ ynx ] [ znx ]
xn = [ xny ] yn = [ yny ] zn = [ zny ]
[ xnz ] [ ynz ] [ znz ]
您正在寻找将这些向量映射到新坐标系中的基向量的矩阵 M
:
[ xnx ] = [ 1 ] [ ynx ] = [ 0 ] [ znx ] = [ 0 ]
M * [ xny ] = [ 0 ] M * [ yny ] = [ 1 ] M * [ zny ] = [ 0 ]
[ xnz ] = [ 0 ] [ ynz ] = [ 0 ] [ znz ] = [ 1 ]
以矩阵形式写出:
[ xnx ynx znx ] = [ 1 0 0 ]
M * [ xny yny zny ] = [ 0 1 0 ]
[ xnz ynz znz ] = [ 0 0 1 ]
这又给出了 M
:
[ xnx ynx znx ]
M = inverse( [ xny yny zny ] )
[ xnz ynz znz ]
换句话说,矩阵是以新基向量作为列的矩阵的逆矩阵。
对于旋转,这变得特别容易。旋转矩阵的逆矩阵是矩阵的转置。所以 M
是以新的基向量作为其行的矩阵:
[ xnx xny xnz ]
M = [ ynx yny ynz ]
[ znx zny znz ]
这样,获得旋转矩阵所需要做的就是构建一个矩阵,将新基向量的值作为其行。例如,如果使用newRight
作为x轴,newUp
作为y轴,newForward
作为z轴,则变换矩阵为:
[ newRight.x newRight.y newRight.z ]
[ newUp.x newUp.y newUp.z ]
[ newForward.x newForward.y newForward.z ]
构建矩阵时,请记住 OpenGL 矩阵通常按列主顺序存储。
使用 glm
库进行计算。我有一个位于局部坐标系中的网格,其中轴为:
meshUp = glm::vec3(0, 1, 0);
meshForward = glm::vec3(0, 0, -1);
meshRight = glm::vec3(1, 0, 0);
我需要一个矩阵,它将其顶点旋转到具有 3 个给定轴的任何其他新坐标系,fx:
newUp = glm::vec3(-0.85, 0.51, -0.08);
newForward = glm::vec3(0.45, 0.65, -0.61);
newRight = glm::vec3(-0.26, -0.56, -0.79);
无需平移,坐标系共享原点。我可以做到一半,就像这样:
glm::vec3 rotationVecForUpAxis = glm::normalize(glm::cross(meshUp, newUp));
float rotationRadiansForUpAxis = acos(glm::dot(meshUp, newUp));
glm::mat4 rotationMatrix = glm::rotate(glm::mat4(),
rotationRadiansForUpAxis,
rotationVecForUpAxis);
这有效并旋转了网格,因此它的上轴与 newUp
轴对齐。但是,在网格的 meshForward
轴与 newForward
轴对齐之前,网格仍然需要绕 newUp
轴旋转。
有人知道怎么做吗?
你可以查一下数学。但只是为了好玩,我将在这里推导它。
假设在原始坐标系中表示的新基向量是:
[ xnx ] [ ynx ] [ znx ]
xn = [ xny ] yn = [ yny ] zn = [ zny ]
[ xnz ] [ ynz ] [ znz ]
您正在寻找将这些向量映射到新坐标系中的基向量的矩阵 M
:
[ xnx ] = [ 1 ] [ ynx ] = [ 0 ] [ znx ] = [ 0 ]
M * [ xny ] = [ 0 ] M * [ yny ] = [ 1 ] M * [ zny ] = [ 0 ]
[ xnz ] = [ 0 ] [ ynz ] = [ 0 ] [ znz ] = [ 1 ]
以矩阵形式写出:
[ xnx ynx znx ] = [ 1 0 0 ]
M * [ xny yny zny ] = [ 0 1 0 ]
[ xnz ynz znz ] = [ 0 0 1 ]
这又给出了 M
:
[ xnx ynx znx ]
M = inverse( [ xny yny zny ] )
[ xnz ynz znz ]
换句话说,矩阵是以新基向量作为列的矩阵的逆矩阵。
对于旋转,这变得特别容易。旋转矩阵的逆矩阵是矩阵的转置。所以 M
是以新的基向量作为其行的矩阵:
[ xnx xny xnz ]
M = [ ynx yny ynz ]
[ znx zny znz ]
这样,获得旋转矩阵所需要做的就是构建一个矩阵,将新基向量的值作为其行。例如,如果使用newRight
作为x轴,newUp
作为y轴,newForward
作为z轴,则变换矩阵为:
[ newRight.x newRight.y newRight.z ]
[ newUp.x newUp.y newUp.z ]
[ newForward.x newForward.y newForward.z ]
构建矩阵时,请记住 OpenGL 矩阵通常按列主顺序存储。