我正在OpenGL(java LWGJL)中处理一些简单的3d图形,并且试图弄清楚如何将偏航,俯仰和横滚转换为运动矢量的x,y和z分量。我知道如何仅通过俯仰和偏航来做到这一点(如here所述),但是我还没有找到任何有关如何将roll集成到此公式中的解释。

我知道在3d空间中定义矢量仅需要偏航和俯仰,但是在这种情况下我也需要滚动。在基本的WASD配置中,我有一些键绑定(bind)到相对于相机的不同运动(A是本地向左,W是本地向前,SPACE是本地向上),因此横摇会影响相机的移动方式(例如,用pi滚动按D/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分量,并考虑了我的偏航,俯仰和横滚?

我可以使用原始触发(如我正在尝试做的那样),涉及矩阵的解决方案或几乎任何东西都可以。

编辑:

请不要仅仅链接到有关Euler Angles的Wikipedia文章来回答。我已经读过它,并且我在数学方面没有足够的背景知识,无法理解如何将其应用于我的情况。

编辑#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感到麻烦。

最佳答案

我认为您不会找到纯粹的答案。无论如何,这都不是一个优雅的选择。

欧拉角(俯仰/偏航/滚动)不是此作业的正确工具。万向锁以及操作顺序的含糊不清将是一个问题。

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

10-06 12:41