java - 基于鼠标移动旋转四元数(OpenGL 和 Java)

标签 java opengl lwjgl quaternions

我正在使用 OpenGL(具体来说是 LWJGL 绑定(bind))用 Java 编写游戏。每个实体,包括相机,都有一个代表它的旋转的四元数。我已经弄清楚如何将四元数应用于当前的 OpenGL 矩阵并且一切都旋转得很好。我遇到的问题是让相机随鼠标旋转。

现在,在每一帧,游戏都会获取鼠标在一个轴上移动的量,然后将该量应用到相机旋转的四元数上。这是旋转四元数的代码,我将其发布,因为我认为这是问题所在(尽管我总是对这类事情是错误的):

    public void rotateX(float amount){
        Quaternion rot = new Quaternion(1.0f, 0.0f, 0.0f, (float)Math.toRadians(amount));
        Quaternion.mul(rot, rotation, rotation);
        rotation.normalise();
    }

此方法应该围绕 X 轴旋转四元数。 'rotation' 是表示实体旋转的四元数。 'amount' 是我想要旋转四元数的量(也就是鼠标移动的量)。 'rot' 是沿 X 轴的归一化 vector ,其 w 值为转换为弧度的量(我想这里的目标是给它一个角度 - 比如 10 度 - 并让它沿给定轴旋转四元数角度)。使用 Quaternion.mul 获取新的四元数,将其乘以旋转四元数,然后将结果存储为旋转四元数。我不知道是否需要标准化,因为“rot”是正常的,“rotation”应该已经标准化了。

rotateY 和 rotateZ 方法执行相同的操作,除了更改“rot”的 vector (y 为 0.0、1.0、0.0,z 为 0.0、0.0、1.0)。

当游戏开始并且相机向下看负 Z 轴时,代码似乎可以正常工作。您可以围绕 Y 轴一直旋转一直围绕 X 轴旋转。但是,一旦您尝试在不向下看 Z 轴的情况下旋转相机,一切都会变得真的怪异(我什至无法描述它,它旋转得非常奇怪)。

我在这里的最终目标是有一些东西可以用来在没有向上 vector 的空间中控制一艘船。所以当你在 Y 轴上移动鼠标时,无论船在什么角度,它都会改变船的俯仰(沿 X 轴旋转)。同样,当您在 X 轴上移动鼠标时,它会改变偏航(沿 Y 轴旋转)。我可能会以错误的方式解决这个问题,我可能只需要朝正确的方向插入(或插入)。

如果您需要有关任何内容的更多详细信息(我的渲染是如何完成的,我正在尝试做的任何其他数学运算),请直接询问,我会提供。当我使用欧拉角时,我明白了一切(这显然是 3D 应用程序开发的一个大禁忌......希望在我花费大量时间让它们工作之前有人会告诉我)但是一旦我切换到四元数,我很快就真的了。在过去的几个月里,我一直在玩弄这段代码,并阅读有关四元数的内容,试图让它发挥作用,但我一无所获:'(

非常非常沮丧...开始后悔尝试制作 3D 东西>_<

最佳答案

Quaternion rot = new Quaternion(1.0f, 0.0f, 0.0f, (float)Math.toRadians(amount));

好吧,这是完全错误的。

constructor that takes four floats假设它们代表一个实际的四元数。你给那个构造函数的是不是四元数;它是一个 vec3 轴和一个您希望围绕其旋转的角度。

您不能将它们插入四元数类并期望从中获得合法的四元数。

您的四元数类应该有一个构造函数或其他一些从角度和旋转轴创建四元数的方法。但是根据您链接到的文档,它没有。所以你必须自己做。

四元数不是第四个值是角度的 vec3 轴。单位四元数表示方向的变化是一个 vec3,它是旋转轴 * 旋转角度的 half 的正弦值,以及一个标量分量,它是 half 的余弦值em> 旋转角度。这假设旋转角度被限制在 [-pi/2, pi/2] 范围内。

因此,你想要的是:

float radHalfAngle = ... / 2.0; //See below
float sinVal = Math.Sin(radHalfAngle);
float cosVal = Math.Cos(radHalfAngle);
float xVal = 1.0f * sinVal;
float yVal = 0.0f * sinVal;  //Here for completeness.
float zVal = 0.0f * sinVal;  //Here for completeness.
Quaternion rot = new Quaternion(xVal, yVal, zVal, cosVal);

此外,将 amount 直接转换为弧度没有意义,尤其是当 amount 只是鼠标移动的像素坐标增量时。您需要在鼠标移动的距离和您想要旋转的距离之间进行某种转换。 toRadians 不是您想要的那种比例。

还有一件事。左乘 rot,正如您在此处所做的那样,将围绕相机空间 X 轴执行旋转。如果你想绕世界空间 X 轴旋转,你需要右乘它。

关于java - 基于鼠标移动旋转四元数(OpenGL 和 Java),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7842408/

相关文章:

java - ScheduledExecutorService 可抛出丢失

C#:创建图形屏幕保护程序

java - 在 Java Pong 中同时更新两个实体

java - 在 Windows 8.1 上使用 lwjgl 渲染时闪烁

java - 像这样创建 Java Frame 是一个好习惯吗?

java - 相当于 C 的 StAX

java - 如何在 onCreate 中使用 glide 获取位图?

c++ - 如何使用opengl将颜色应用于三角形

c - OpenGL(在 Ubuntu 中): glGetError() returns GL_INVALID_OPERATION

java - 2D map 创建