根据相机的方向在 HUD 上移动 3d 点
Have a 3d point move on HUD depending the direction of the camera
我的问题如下:
假设我在 (x, y, z) 位置并且我有几个点 (xn, yn, zn) 并且取决于我的视角方向,假设我有垂直、水平和滚动的角度值,我希望我的 HUD 能够识别这些点,如果它们在我的视角中,并在任何角度发生变化时四处移动。基本上把它变成屏幕上的一个 (x, y) 坐标。
喜欢以下游戏中的任务点以下行为:https://www.youtube.com/watch?v=I_LlEC-xB50
我该怎么做?
编辑:
我使用以下方法获取坐标:
def convert_to_xyz(point):
# Lat / Lon / Alt -> point[0] / point[1] / point[2]
# Note: point[2] = earth circumference + altitude
point[2] += _earth_radius
x = math.cos(point[0]) * math.cos(point[1]) * point[2]
y = math.cos(point[0]) * math.sin(point[1]) * point[2]
z = math.sin(point[0]) * point[2] # z is 'up'
return numpy.array([x, y, z])
获取相机矩阵:
def get_camera_matrix(fovx, fovy, height, width):
# FOVX is the horizontal FOV angle of the camera
# FOVY is the vertical FOV angle of the camera
x = width / 2
y = height / 2
fx = x / math.tan(fovx)
fy = y / math.tan(fovy)
return np.array([[fx, 0, x],
[0, fy, y],
[0, 0, 1]])
转换为相机 space:
def transform_to_camera_space(point, camera_matrix):
return np.dot(point, camera_matrix)
然后我使用@spug 答案,我得到的值如下:
array([ 133.99847154, 399.15007301])
第 1 步:
将点从worldspace转换为cameraspace,方法是将其乘以相机矩阵.您应该仔细阅读有关构建它的内容 - 有无数的网络资源。在 (pitch, yaw, roll) 坐标中,旋转必须按照 roll -> pitch -> yaw 的顺序发生,对应于:
绕X轴旋转过角度roll
-> 矩阵R
绕Y轴旋转过角度pitch
-> 矩阵P
绕Z轴旋转过角度yaw
-> 矩阵Y
相机矩阵的旋转部分由(YPR)T给出, 乘法顺序。本页给出了 XYZ 旋转矩阵:https://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations.
相机 space 中的点由 q = transpose(YPR) * (p - c)
给出,其中 p = (xn, yn, zn)
是世界 space 中的点,c = (x, y, z)
是您的相机位置.另一种方法是构建一个 4x4 矩阵并用 -(YPR)*c
填充第 4 列 - 同样,可在互联网上获得。
此时,如果点 q
的 X 值低于某个限制(称为近裁剪平面 - 将其设置为某个正值),则丢弃该点。这样可以确保不显示相机后面的点。
第 2 步:
下图说明了透视投影背后的过程:
- Theta 是 FOV 的一半
- p 是点的深度值 = 相机框架中的 X 坐标)
- s 是相机坐标系中的 Y 坐标
- X 是屏幕坐标
同样适用于 Y:
- t 是相机坐标系中的 Z 坐标
- A 是您的纵横比(高度/宽度)
我的问题如下:
假设我在 (x, y, z) 位置并且我有几个点 (xn, yn, zn) 并且取决于我的视角方向,假设我有垂直、水平和滚动的角度值,我希望我的 HUD 能够识别这些点,如果它们在我的视角中,并在任何角度发生变化时四处移动。基本上把它变成屏幕上的一个 (x, y) 坐标。
喜欢以下游戏中的任务点以下行为:https://www.youtube.com/watch?v=I_LlEC-xB50
我该怎么做?
编辑: 我使用以下方法获取坐标:
def convert_to_xyz(point):
# Lat / Lon / Alt -> point[0] / point[1] / point[2]
# Note: point[2] = earth circumference + altitude
point[2] += _earth_radius
x = math.cos(point[0]) * math.cos(point[1]) * point[2]
y = math.cos(point[0]) * math.sin(point[1]) * point[2]
z = math.sin(point[0]) * point[2] # z is 'up'
return numpy.array([x, y, z])
获取相机矩阵:
def get_camera_matrix(fovx, fovy, height, width):
# FOVX is the horizontal FOV angle of the camera
# FOVY is the vertical FOV angle of the camera
x = width / 2
y = height / 2
fx = x / math.tan(fovx)
fy = y / math.tan(fovy)
return np.array([[fx, 0, x],
[0, fy, y],
[0, 0, 1]])
转换为相机 space:
def transform_to_camera_space(point, camera_matrix):
return np.dot(point, camera_matrix)
然后我使用@spug 答案,我得到的值如下:
array([ 133.99847154, 399.15007301])
第 1 步:
将点从worldspace转换为cameraspace,方法是将其乘以相机矩阵.您应该仔细阅读有关构建它的内容 - 有无数的网络资源。在 (pitch, yaw, roll) 坐标中,旋转必须按照 roll -> pitch -> yaw 的顺序发生,对应于:
绕X轴旋转过角度
roll
-> 矩阵R绕Y轴旋转过角度
pitch
-> 矩阵P绕Z轴旋转过角度
yaw
-> 矩阵Y
相机矩阵的旋转部分由(YPR)T给出, 乘法顺序。本页给出了 XYZ 旋转矩阵:https://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations.
相机 space 中的点由 q = transpose(YPR) * (p - c)
给出,其中 p = (xn, yn, zn)
是世界 space 中的点,c = (x, y, z)
是您的相机位置.另一种方法是构建一个 4x4 矩阵并用 -(YPR)*c
填充第 4 列 - 同样,可在互联网上获得。
此时,如果点 q
的 X 值低于某个限制(称为近裁剪平面 - 将其设置为某个正值),则丢弃该点。这样可以确保不显示相机后面的点。
第 2 步:
下图说明了透视投影背后的过程:
- Theta 是 FOV 的一半
- p 是点的深度值 = 相机框架中的 X 坐标)
- s 是相机坐标系中的 Y 坐标
- X 是屏幕坐标
同样适用于 Y:
- t 是相机坐标系中的 Z 坐标
- A 是您的纵横比(高度/宽度)