将物体从一个坐标系旋转到另一个坐标系

3

使用 glm 库进行计算。我有一个在本地坐标系中的网格,轴线如下:

meshUp =      glm::vec3(0, 1, 0);
meshForward = glm::vec3(0, 0, -1);
meshRight =   glm::vec3(1, 0, 0);

我需要一个矩阵,可以将其顶点旋转到任何具有3个给定轴的新坐标系中,例如:

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轴旋转网格。

有人知道如何做到这一点吗?


1
看起来你可能对基变换矩阵感兴趣:https://www.math.hmc.edu/calculus/tutorials/changebasis/. - user3256930
1个回答

7
你可以查阅数学知识。但仅供娱乐,我将在此推导它。
假设新的基向量在原始坐标系中表示为:
     [ 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中的矩阵通常以列优先顺序存储。


1
非常感谢您的回答,它运行得非常好,比我原来的方向简单得多! - acrmuui
非常好的答案,谢谢。对于还没有学过线性代数的人来说,非常易懂! - Ashwin Gupta

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接