opengl - 将对象从一个坐标系旋转到另一个坐标系

标签 opengl 3d glm-math

使用 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 矩阵通常按列主要顺序存储。

关于opengl - 将对象从一个坐标系旋转到另一个坐标系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29754538/

相关文章:

c++ - 是否需要释放/释放 GL_TEXTURE?

c++ - QOpenGLWidget 纹理映射导致黑屏

Java/C++ - 从相机偏航(航向)和俯仰(无滚动)获取 3d 线

c++ - OpenGL 显示列表 block glEnable(GL_COLOR_MATERIAL)

java - 重写一个方法是行不通的

c++ - GL_Points 上的 gluUnproject 或从鼠标坐标中查找深度坐标

r - 在绘图表面上使用条件着色

c++ - 稳定级联阴影映射中的光 View 矩阵

c++ - 为什么 C++ 找不到 GLM header ?

c++ - GLM 是否与 GLload 和 GCC 兼容