【问题标题】:Convert yaw, pitch AND roll to x,y,z vector in world coordinates将偏航、俯仰和滚动转换为世界坐标中的 x、y、z 向量
【发布时间】:2013-09-16 20:11:40
【问题描述】:

我正在 OpenGL (java LWGJL) 中处理一些简单的 3d 图形,并且试图弄清楚如何将偏航、俯仰和滚动转换为我的运动矢量的 x、y 和 z 分量。我知道如何只用俯仰和偏航来做到这一点(如here 解释的那样),但我还没有找到任何解释如何将滚动集成到这个公式中的东西。

我知道在 3d 空间中定义矢量只需要偏航和俯仰,但在这种情况下我还需要滚动。在基本 WASD 配置中,我将键绑定到相对于相机的不同运动(A 是本地左侧,W 是本地前进,SPACE 是本地向上),因此滚动会影响相机的移动方式(例如,按 D 并滚动 pi/2(默认)将相机向右移动(在世界坐标中),但按 D 使用一卷 pi 将相机在世界坐标中向上移动))。

这是我目前的代码:

//b = back
//f = forward
//r = right
//l = left
//u = up
//d = down

    private void move()
    {
        double dX = 0, dY = 0, dZ = 0;


        if (f ^ b)
        {
            dZ += cos(yaw) * cos(pitch) * (b ? 1 : -1);
            dX += sin(yaw) * cos(pitch) * (b ? 1 : -1);
            dY += -sin(pitch) * (b ? 1 : -1);
        }

        if (l ^ r)
        {
            dZ += sin(yaw) * sin(roll) * (l ? 1 : -1);
            dX += cos(yaw) * - sin(roll) * (l ? 1 : -1);
            dY += cos(roll) * (l ? 1 : -1);
        }

        if (u ^ d) //this part is particularly screwed up
        {
            dZ += sin(pitch) * sin(roll) * (u ? 1 : -1);
            dX += cos(roll) * (u ? 1 : -1);
            dY += cos(pitch) * sin(roll) * (u ? 1 : -1);
        }



        motion.x = (float) dX;
        motion.y = (float) dY;
        motion.z = (float) dZ;

        if (motion.length() != 0)
        {
            motion.normalise();
            motion.scale(2);
        }

        x += motion.x;
        y += motion.y;
        z += motion.z;

这适用于几次旋转,但对于许多旋转会产生不正确的结果。

所以问题是:

如何修改我的代码,以便它根据我想要的方向(按下什么键)成功计算我的运动矢量的 x、y 和 z 分量,并考虑我的偏航、俯仰、AND滚动?

我可以使用 raw trig(正如我正在尝试做的那样)、涉及矩阵的解决方案或几乎任何东西。

编辑:

请不要仅仅通过链接到关于欧拉角的维基百科文章来回答。我读过它,但我没有足够强大的数学背景来理解如何将它应用到我的情况中。

编辑#2:

我只使用欧拉角在重新定位相机之间存储我的方向。对于实际的相机操作,我使用旋转矩阵。如果需要,我可以删除欧拉角并只使用矩阵。重要的是我可以从我的方向转换为矢量。

编辑#3:

通过将我的前向向量乘以我的旋转矩阵找到了一个解决方案,如 厘米:

//b = back
//f = forward
//r = right
//l = left
//u = up
//d = down

private Vector3f motion;

protected void calcMotion()
{
    //1 for positive motion along the axis, -1 for negative motion, 0 for no motion
    motion.x = r&&!l ? -1 : l ? 1 : 0; 
    motion.y = u&&!d ? 1 : d ? -1 : 0;
    motion.z = f&&!b ? 1 : b ? -1 : 0;

    if (motion.length() == 0)
    {
        return;         
    }

    motion.normalise();

    //transform.getRotation() returns a Matrix3f containing the current orientation
    Matrix3f.transform(transform.getRotation(), motion, motion);
}

不过,this 仍然有问题。

【问题讨论】:

    标签: opengl 3d camera lwjgl euler-angles


    【解决方案1】:

    我认为您不会找到纯粹的触发答案。无论如何,不​​是一个优雅的人。

    欧拉角(俯仰/偏航/滚动)不是这项工作的正确工具。 Gimbble-lock 将是一个问题,以及操作顺序的模糊性。

    我建议将对象的当前旋转状态存储在矩阵或四元数中。仅对相对较小的增量使用欧拉角。

    【讨论】:

    • 我只使用欧拉角来存储我的方向,因为矩阵修改起来很麻烦。在实际瞄准相机时,我将它们转换为旋转矩阵。
    • 欧拉角很容易修改,但是如果你同时使用这三个角,那么得到的转换就会出错。
    • 在这种情况下,假设我将我的方向存储在一个矩阵中。那我该如何回答我原来的问题呢?
    • 您可以将单位向量与旋转矩阵相乘,得到前向向量。 (或者向上或向左的向量,就此而言。)
    • @ValekHalfHeart:矩阵不应该是繁琐的修改,它们真正的美妙之处在于,您可以对它们应用所有基本变换,只需要矩阵乘法。同样,使用矩阵变换向量也可以通过乘法来完成。
    【解决方案2】:

    您可以使用广泛用于计算所有旋转后的最终位置的齐次变换矩阵方法。

    【讨论】:

      猜你喜欢
      • 2015-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-18
      • 2019-03-27
      相关资源
      最近更新 更多