将偏航,俯仰和滚动转换为世界坐标中的x,y,z向量

App*_*ish 5 opengl 3d camera lwjgl euler-angles

我正在研究OpenGL中的一些简单的3D图形(java LWGJL),我正在试图弄清楚如何将偏航,俯仰和滚动转换为我的运动Vector的x,y和z分量.我知道如何通过俯仰和偏航来做到这一点(如这里所解释的),但是我没有找到任何解释如何将滚动整合到这个公式中.

我知道偏航和俯仰是在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;
Run Code Online (Sandbox Code Playgroud)

这适用于几个旋转,但对许多人来说,它会产生不正确的结果.

所以问题是:

如何修改我的代码,这样就成功计算出我的运动矢量的基于我所希望的方向(按什么键)在x,y和z分量,占我的偏航,俯仰滚动?

我使用原始trig(我试图这样做),包含矩阵或几乎任何东西的解决方案都没问题.

编辑:

请不要仅通过链接到关于Euler Angles的维基百科文章来回答.我已经阅读过了,我没有足够强的数学背景来理解如何将它应用到我的情况中.

编辑#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);
}
Run Code Online (Sandbox Code Playgroud)

但是仍然有这个问题.

小智 3

我认为你不会找到纯三角的答案。无论如何,这不是一个优雅的人。

欧拉角(俯仰角/偏航角/横滚角)不是适合这项工作的工具。万向锁以及操作顺序的模糊性都会成为一个问题。

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