python - 为什么我的 FPS 相机滚动?在 Python 中使用欧拉角(不是四元数)实现
问题描述
我正在尝试生成一个可以充当 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
解决方案
抽象地说,您的问题是由俯仰和偏航引起的旋转在合成下没有闭合。
更具体地说:想象一下控制第一人称相机。往下看,然后向左和向右转。您的视线将以一种非常不同的方式移动,而不是您在直视前方时转身。但是,您的计算就像相机会表现得一样。
每个刻度,你view
从右边乘以一个偏航矩阵,然后是一个俯仰矩阵。这意味着一段时间后,您的视图矩阵将成为大量俯仰和偏航矩阵的交替乘积。但是,俯仰和偏航矩阵不可以交换。您真正想要的是将所有俯仰矩阵放在所有偏航矩阵的左侧(或右侧,这取决于您是让您的视图矩阵从左侧还是右侧操作,以及您的矩阵是否代表视图-global 或 global-to-view 转换)。
因此,快速解决此问题的方法是编写view = yrot @ view @ xrot
. 这样,你所有的 y 旋转最终都在你的 x 旋转的左边,一切都会好起来的。好吧,至少在一段时间内,但是您的视图矩阵最终可能会累积舍入误差,并且视图可能会滚动或倾斜或更糟。
我建议您根本不要重用视图矩阵。相反,只需存储玩家当前的俯仰和偏航,在鼠标移动时更新它,然后每次都直接从俯仰和偏航重新计算视图矩阵。通过这种方式,您还可以以其他方式使用俯仰和偏航(例如,您需要将俯仰限制在一定范围内以防止玩家进行倒立或翻筋斗),并且您也不会在矩阵中累积错误。
推荐阅读
- javascript - 如何在javascript中循环?
- python - 用于从 S3 解析 json 并存储在 DynamoDB 中的 AWS Lambda python 函数
- flutter - Dart/Flutter:当作为参数传递时,List 中的元素字符串变为空(为什么??)
- python-3.x - 如何为在python3中获取用户输入的代码编写单元测试
- php - ChartJS 未从 MySQL 显示
- reactjs - 致命:无法创建工作树目录:权限被拒绝(在部署反应应用程序时)
- javascript - NextJS API – 使用动态路由的中间件 [...]
- android - Android 9:使用具有指定 minLayer 和 maxLayer 的 SurfaceControl 截屏时获取“黑色图像”
- java - 什么是“这个数组名后面没有'['”?
- html - 如何在使用 CSS 网格时调整图像大小以完全适合其容器?