将偏航、俯仰和滚转转换为世界坐标中的 x,y,z 向量 [英] Convert yaw, pitch AND roll to x,y,z vector in world coordinates

查看:49
本文介绍了将偏航、俯仰和滚转转换为世界坐标中的 x,y,z 向量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在 OpenGL (java LWGJL) 中处理一些简单的 3d 图形,并且我试图弄清楚如何将偏航、俯仰和滚转转换为我的运动向量的 x、y 和 z 分量.我知道如何只用俯仰和偏航来做到这一点(如此处所述),但我没有找到任何解释如何将滚动整合到这个公式中.

I'm working on some simple 3d graphics in OpenGL (java LWGJL), and I'm trying to figure out how to convert yaw, pitch and roll to the x, y and z components of my movement Vector. I know how to do this with just pitch and yaw (as explained here), but I haven't found anything the explains how to integrate roll into this formula.

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

I am aware that yaw and pitch are all that is needed to define a vector in 3d space, but I also need roll in this instance. I have keys bound to different movements relative to the camera in a basic WASD configuration (A is local left, W is local forward, SPACE is local up), so the roll affects how the camera moves (eg pressing D with a roll of pi/2 (the default) moves the camera right (in world coords), but pressing D with a roll of pi moves the camera up in world coords)).

这是我目前的代码:

//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;

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

This works for a few rotations, but for many it produces incorrect results.

所以问题是:

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

How do I modify my code such that it successfully calculates the x, y, and z components of my motion vector based upon my desired direction (what key is pressed), accounting for my yaw, pitch, AND roll?

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

I'm fine with using raw trig (as I am attempting to do), a solution involving matrices, or pretty much anything.

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

Please don't answer by just linking to the Wikipedia article on Euler Angles. I've read it and I don't have a strong enough background in math to understand how to apply it to my situation.

编辑#2:

我只使用欧拉角来存储我在重新定向相机之间的方向.对于实际的相机操作,我使用旋转矩阵.如果需要,我可以去掉欧拉角,只使用矩阵.重要的是我可以将我的方向转换为向量.

I'm only using Euler angles to store my orientation in between re-orienting the camera. For the actual camera manipulations, I use rotational matrices. If needed, I can drop the euler angles and just use a matrix. All that matters is that I can convert from my orientation to a vector.

编辑 #3:

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

Found a solution by multiplying my forward vector by my rotation matrix as described in the comments:

//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);
}

仍然遇到这个的问题.

推荐答案

我不认为你会找到一个纯粹的答案.无论如何,这不是一个优雅的.

I don't think you're going to find an answer that's pure trig. Not an elegant one, anyway.

欧拉角(俯仰/偏航/滚动)不是这项工作的正确工具.万向节锁会是一个问题,以及操作顺序的模糊性.

Euler angles(Pitch/Yaw/Roll) are not the right tool for this job. Gimble-lock will be a problem, as well as the ambiguity of the order of operations.

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

I suggest storing your objects' current rotational state in either a Matrix or a Quaternion. Only use Euler angles for relatively small deltas.

这篇关于将偏航、俯仰和滚转转换为世界坐标中的 x,y,z 向量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆