关于 3D 模型的坐标变换

更新页 :
页面创建日期 :

物质

首先

您可能经常在电视屏幕上看到 3D 图像,在游戏中看到显示器,但如何在 2D 屏幕上显示存在于 3D 空间中的对象,例如在屏幕上移动的角色和建筑物?

在 2D 游戏中,只有 “X 和 Y” 的二维元素作为坐标值,显示也是 2D的,所以如果你通过指定 X 和 Y 的坐标位置来绘制一个物体,你会直观地理解它将如何在哪个位置绘制。

然而,在 3D 中,这并不是那么容易。 顾名思义,3D 是 “3 维” ,具有三个坐标信息:“X、Y 和 Z”。 由于坐标与 2D 显示不同,因此无法按原样绘制对象。

那么,要做的就是“把三维信息转换成二维信息”。 这通常称为 “坐标转换”。 请记住,此坐标转换对于 3D 编程至关重要。

将 3D 转换为 2D 的坐标变换有多种类型,但程序员处理的坐标变换主要有三种类型:“世界变换”、“视图变换”和“投影变换”。 在这里,我们将解释与坐标变换相关的所有内容。

左手和右手坐标系

在 3D 中,有两个坐标系,即“左手坐标系”和“右手坐标系”,每个坐标的方向不同,如下图所示。

Direct3D 主要使用左手坐标系,但也有用于计算右手坐标系的函数。 但是,XNA 仅提供右手坐标系的计算方法。 这似乎与其他应用程序经常使用右手坐标系的事实一致。

此站点上的所有 XNA 提示都使用右手坐标系。

局部坐标系 (Model Coordinate System)

每个模型都有一个以原点为中心的坐标系。 使用建模软件创建模型时,我认为如果您想象以原点为中心创建模型,则更容易理解。

世界坐标系

世界坐标系允许您将模型放置在任何位置。 如果在此世界变换中不执行任何操作,则模型将以与本地坐标相同的方式放置在原点处。 放置不仅要从原点移动,还要旋转和缩放。

视图坐标系

将模型放置在世界坐标中后,您需要有关您正在查看的位置以及您在 3D 空间中查看的位置的信息。 这就是我们所说的 “视图转换”。 视图变换通常表示为摄像机。

此转换所需的参数是 “camera position”(摄像机位置)、“Camera point of interest”(摄像机目标点)和 “camera upward direction”(摄像机向上方向)。 相机的方向由这三个参数决定。 下图显示了第三方视角的摄像头。

下图实际上是从相机的角度看到的,上面图所示的排列方式(此时我们还没有将坐标转换到屏幕上,所以只是一个图像)。

在前面的解释中,看起来是相机定位,坐标被变换,但在实际计算中,世界坐标是根据相机的位置和方向进行转换的。 因此,原点是相机的位置,如下图所示。

投影坐标系

确定从哪个位置查看 3D 空间后,下一步是处理“远处的小对象”和“附近的大对象”的显示。 这称为投影变换。 投影变换有两种方法,“透视投影”和“正交投影”,但常用的“透视投影”图像如下。

透视投影使用以下参数:Viewing Angle、Aspect Ratio、Forward Clip Position 和 Rear Clip Position。 上图中标记为 “frustum” 的区域最终将出现在屏幕上。

“Viewing Angle” 指定从摄像机可见的 view 范围。 减小角度可放大,增加角度可缩小。 视角将是视锥体的垂直值。

纵横比 用于确定水平视角,而视角是垂直角度。 水平角度通常由 “视角×纵横比” 决定,纵横比基本上是你要显示的屏幕的 “宽 ÷ 高 ”的值。 如果更改此值,则显示的 3D 对象将显示为水平或垂直拉伸。

指定 Forward Clip Position 和 Rear Clip Position 以确定对象是显示在前部还是后部范围内。 由于计算机的性质,不可能显示到无穷大,因此我们将设置一个限制。 此值也会影响 Z 缓冲区的精度,因此不建议将其包含在绘图区域中,超出不需要显示的范围。

透视变换的对象将转换为如下所示的空间。 靠近摄像机的对象被放大,而远离的对象被缩小。

这在下面的易于理解的图表中进行了说明。

如果你真的从相机的角度来看,它看起来像下面。

投影变换的另一种方法是正交投影,它投影一个可见区域,如下所示。 由于宽度和高度是恒定的,而与深度无关,因此对象的大小不会随深度而变化。

屏幕坐标系

投影转换后,它将转换为实际屏幕的坐标。 即使它是一个屏幕,显示的位置和范围也会根据设备上设置的视口设置而变化。 但是,在游戏的情况下,窗口的客户端坐标通常是视区,因此我认为您无需太担心。

屏幕的坐标 (0, 0) 是从投影坐标 (-1, 1, z) 转换而来的。 同样,屏幕坐标 (width, height) 是从投影坐标 (1, -1 ,z) 转换而来的。