为什么我的FPS相机滚动?在Python中使用欧拉角(不是四元数)实现

时间:2019-02-26 13:05:34

标签: python opengl camera rotation

我正在尝试生成一个可作为FPS相机使用的视图矩阵,但实际上我正在滚动。共享我的python代码,以防有人发现问题所在。

import numpy as np

class Camera():
    def __init__(self):
        self.sens = np.array([0.002, 0.002])  # mouse sensitivity (x, y)
        self.angpos = np.array([0.0, 0.0])  # (pitch, yaw)

    def mouse_move(self, pos, rel):
        self.angpos = rel[::-1]*self.sens  # mouse relative motion (delta-x, delta-y)
        ya = self.angpos[1]
        yrot = np.array([
            [ np.cos(ya),  0.0,    np.sin(ya),   0.0],
            [ 0.0,         1.0,    0.0,          0.0],
            [-np.sin(ya),  0.0,    np.cos(ya),   0.0],
            [0.0,          0.0,    0.0,          1.0]
        ])

        xa = self.angpos[0]
        xrot = np.array([
            [ 1.0,    0.0,          0.0,          0.0 ],
            [ 0.0,    np.cos(xa),  -np.sin(xa),   0.0 ],
            [ 0.0,    np.sin(xa),   np.cos(xa),   0.0 ],
            [ 0.0,    0.0,          0.0,          1.0 ],
        ])

        return yrot @ xrot  # view matrix


# this is the callback for mouse movement. `pos` is absolute mouse 
# position in the screen and `rel` is the position relative to previous call
# def mouseMotionEvent(self, pos, rel):
#     view = self.cam.mouse_move(pos, rel)  # self.cam is an instance of Camera
#     self.view = view @ self.view
#     return True

跟随我所得到的行为的gif图像: enter image description here

1 个答案:

答案 0 :(得分:5)

抽象地,您的问题是俯仰和偏航引起的旋转在构图下不会闭合。

更具体地说:想象一下控制第一人称相机。往下看,然后向左和向右旋转。您的视线将以与您直视前方时转向不同的方式移动。但是,您的计算就像相机会表现得一样。

每个刻度,将view从右边乘以偏航矩阵,再乘以音调矩阵。这意味着一段时间后,您的视图矩阵将是许多俯仰和偏航矩阵的交替乘积。但是,俯仰和偏航矩阵不会上下班。您真正想要的是使所有俯仰矩阵位于所有偏航矩阵的左侧(或向右),具体取决于您是让视图矩阵从左还是从右进行操作,以及矩阵是否代表-global或global-to-view转换)。

因此,解决此问题的快速方法是编写view = yrot @ view @ xrot。这样,您所有的y旋转都结束于您的x旋转的左侧,一切都会好起来的。好吧,至少有一段时间,但是您的视图矩阵可能最终会累积舍入误差,并且视图可能会滚动或倾斜或变得更糟。

我建议您完全不要重用视图矩阵。取而代之的是,只需存储玩家当前的俯仰和偏航,并根据鼠标的运动对其进行更新,然后每次直接根据俯仰和偏航重新计算视图矩阵。这样,您还可以通过其他方式使用俯仰和偏航(例如,您希望将俯仰限制在一定范围内,以防止播放器倒立或翻筋斗),并且您也不会在矩阵中累积误差。 / p>

相关问题