码迷,mamicode.com
首页 > 其他好文 > 详细

3D 游戏控制

时间:2015-04-27 21:33:35      阅读:259      评论:0      收藏:0      [点我收藏+]

标签:

【转自】http://dev.10086.cn/cmdn/wiki/index.php?doc-view-6457.html

摘要

了解如何制作 XNA 游戏使用的 3D 模型,以及于 XNA 游戏中显示 3D 模型的基本做法之后,这一次我们将要为大家介绍 3D 模型的控制技巧,包括旋转、放大/缩小、平移、以及相机控制等游戏常见的操作。了解 3D 模型的显示与控制原理,以及如何建立将 3D 模型的物体空间转换成世界空间的 Matrix 结构,如何建立将世界空间转换成检视空间的 Matrix 结构,以及如何建立将检视空间投射在屏幕空间的 Matrix 结构。有关如何制作 XNA 游戏使用的 3D 模型,以及于 XNA 游戏中显示 3D 模型的基本做法可以参考 [3D 游戏设计] 一文的详细说明。

 3D 游戏设计基础

在执行控制与显示 3D 模型之前,首先我们必须了解以 XNA 为基础的 3D 游戏采用的坐标系统,表示坐标与控制坐标转换常用的数据型态,并认识 Object Space、World Space、View Space、和 Screen Space 四种空间代表的意义与用途。

以 XNA 为基础的 3D 游戏采用的是右手坐标系统 (Right-Handed System),其X轴往右递增,Y 轴往上递增,而 Z 轴则是往使用者的方向递增,如图1 所示:

图1:以 XNA 为基础的 3D 游戏采用的右手坐标系统

技术分享

控制或显示 3D 模型,我们需要用到描述坐标的 Vector2 和 Vector3 结构,以及用来协助坐标计算的 Vector4 结构与 Matrix 结构。有关 Vector2、Vector3、和 Vector4 等和坐标有关的结构型态的详细功能可以参考 [XNA Framework 常用的类别] 一文的说明。

除了描述坐标和进行坐标计算需要用到的结构型态以外,要显示和控制 3D 模型,我们还需要了解 3D 模型的 Object Space (亦称 Model Space)、World Space、View Space、和 Screen Space (亦称 Projection Space) 四种空间表示法的意义。

简单来说,3D 模型在 3D 的世界中有几种不同的空间表示法,3D 模型中的坐标点未经任何的转置处理前称为物体空间 (object space),当 3D 模型经过旋转,放大/缩小等转置处理之后就会得到世界空间 (world space),经过转置处理过的世界空间在显示给用户检视之前,还需要加入相机的位置和角度的处理,形成检视空间 (view space),最后的检视空间在显示之前必须投射到屏幕的2维空间,称为屏幕空间 (screen space),而屏幕空间显示的内容就是用户最终看到的结果。

要将 3D 模型的物体空间转换成世界空间、检视空间、和屏幕空间,我们需要借助于 Matrix 结构及其提供的属性和方法。Matrix 结构负责定义一个 4x4 的矩阵,其常用的属性可以参考表1 的说明:

表1:Matrix 结构常用的属性
属性名称 说明
Backward 描述后退的向量。
Down 描述下移的向量。
Forward 描述前进的向量。
Identity 传回单位矩阵。单位矩阵的定义就是任何矩阵和单位矩阵相乘之后的结果会得到原来的矩阵。
Left 描述左移的向量。
Right 描述右移的向量。
Translation 描述平移的向量。
Up 描述上移的向量。

[说明]

单位矩阵的定义是矩阵的元素中,除了列编号和栏编号内容值相同的元素的内容值为 1 以外,其他的元素的内容值皆为 0。例如 2x2 的单位矩阵的内容如下:

技术分享

3x3 的单位矩阵如下:

技术分享

而 n*n 的单位矩阵如下:

技术分享

Matrix 结构常用的方法请参考表2 的说明:

表2:Matrix 结构常用的方法
方法名称 说明
Add 支持矩阵相加的方法。
CreateBillboard 依据指定的物体的位置建立球形的广告牌。
CreateConstrainedBillboard 依据指定的轴建立圆柱体广告牌。
CreateFromAxisAngle 依据指定的旋转轴心和角度建立 Matrix 结构。
CreateFromQuaternion 依据 Quaternion 结构指定的向量和角度建立用来旋转物体的 Matrix 结构。
CreateFromYawPitchRoll 依据X轴旋转角度、Y 轴旋转角度、和 Z 轴旋转角度建立用来旋转物体的 Matrix 结构。
CreateLookAt 建立以相机为原点的 View Space,并表示成 Matrix 结构。
CreateOrthographic 建立直角的 Projection Space,并表示成 Matrix 结构。
CreateOrthographicOffCenter 建立可客制化的直角 Projection Space,并表示成 Matrix 结构。
CreatePerspective 建立透视的 Projection Space,并表示成 Matrix 结构。
CreatePerspectiveFieldOfView 依据视角 (Field of View-简称 FOV) 建立透视的 Projection Space,并表示成 Matrix 结构。
CreatePerspectiveOffCenter 建立可客制化的透视 Projection Space,并表示成 Matrix 结构。
CreateReflection 利用指定的平面的坐标系统的反射建立 Matrix 结构。
CreateRotationX 建立能够以 X 轴为轴心旋转指定角度的 Matrix 结构。
CreateRotationY 建立能够以 Y 轴为轴心旋转指定角度的 Matrix 结构。
CreateRotationZ 建立能够以 Z 轴为轴心旋转指定角度的 Matrix 结构。
CreateScale 建立可以用来执行放大/缩小 3D 模型的 Matrix 结构。
CreateShadow 依据指定的光源建立可以用来表示阴影的 Matrix 结构。
CreateTranslation 建立可以用来平移 3D 模型的 Matrix 结构。
CreateWorld 建立可以用来表示 World Space 的 Matrix 结构。
Decompose 从 Matrix 结构取出放大/缩小、平移、和旋转的成份值。
Determinant 计算 Matrix 结构的 determinant 值。以 2x2 的 Matrix 结构技术分享为例,其 determinant 值为 ad-bc。
Divide 计算 Matrix 结构除以一个数值或是另外一个 Matrix 结构的结果,并表示成 Matrix 结构。
Invert 取得反矩阵,并表示成 Matrix 结构。
Lerp 对两个 Matrix 结构对应的元素值执行线性内插。
Multiply 计算 Matrix 结构除以一个数值或是另外一个 Matrix 结构的结果,并表示成 Matrix 结构。
Negate 将 Matrix 结构每一个元素值改成负数,并将执行的结果表示成 Matrix 结构。
op_Addition 对两个 Matrix 结构执行加法,并将执行的结果表示成 Matrix 结构。
op_Division 将 Matrix 结构除以一个数值,或是另外一个 Matrix 结构的元素,并将执行的结果表示成 Matrix 结构。
op_Equality 判断两个 Matrix 结构是否相等。
op_Inequality 测试 Matrix 结构和另外一个 Matrix 结构是否不相等。
op_Multiply 将 Matrix 结构乘以一个数值,或是另外一个 Matrix 的元素,并将执行的结果表示成 Matrix 结构。
op_Subtraction 对两个 Matrix 结构执行减法,并将执行的结果表示成 Matrix 结构。
op_UnaryNegation 将 Matrix 结构的每一个元素都设定成负值。
Subtract 支持 Matrix 结构相减的方法。
Transform 依据 Quaternion 结构的内容对 Matrix 结构执行旋转。
Transpose 对 Matrix 结构执行转置 (Transpose) 运算,也就是列变成行,行变成列的转换。

[说明]

建立 3D 场景的时候,将 2D 的物体显示成 3D 的效果以得到较好的效能的做法称之为 Billboarding (广告牌),而 Matrix 结构提供的 CreateBillboard 方法与 CreateConstrainedBillboard 方法就是支持建立广告牌的方法。将 2D 的物体显示成 3D 的效果主要的概念就是由物体图案组成的纹理套用在矩形的元素上,由程序视需要旋转矩形的元素,使其面向使用者的目光。请注意物体的图案的形状可以不是矩形的形状,而且广告牌还可以允许某一部分形成透明的效果,以隐藏对象图案的内容。

许多游戏程序都是利用广告牌技巧显示 3D 动画,例如游戏的主角在 3D 的迷宫内走动,所看到,而且可以取用的武器和宝物都是由 2D 的图案套用在矩形元素形成的效果。3D 游戏显示树林、灌木丛、或是天空的云的时候,常常都是靠广告牌技术呈现的效果。当游戏程序将图案套用到广告牌的时候,矩形元素会先旋转至面对用户的视线,然后再执行套用纹理的动作。

广告牌的效果适合套用在对称的物体,特别是垂直对称的物体,但是物体的视角不可以太高,否则当物体由上往下审视广告牌的时候,其效果会变成 2D 的效果,而不再具有 3D 的视觉效果。

 3D 模型转置计算

Matrix 结构是游戏程序显示与控制 3D 模型极常用的型态,当游戏程序需要平移、旋转、或是放大/缩小 3D 模型时,就可以利用 Matrix 结构提供的功能建立可以将 3D 模型从 Object Space 转换到 World Space 的 World Matrix。例如游戏程序可以呼叫 Matrix 结构的 CreateTranslation 方法建立可以平移 3D 模型的 World Matrix,当您想将 3D 模型平移至 X 坐标为 10,Y 坐标为 0,Z 坐标为 50 的位置,就可以利用以下的程序代码建立 World Matrix:

  1. Matrix WorldTranslation = Matrix.CreateTranslation(new Vector3(10, 0, 50));

做好之后,游戏程序只要将所建立的 World Matrix 套用至 Mesh 的 Effect,就可以达到平移 3D 模型的效果。

如果游戏程序需要旋转 3D 模型,可以呼叫 Matrix 结构的 CreateRotationX 方法并传入旋转角度表示要依据 X 轴为轴心旋转指定的角度,呼叫 Matrix 结构的 CreateRotationY 方法并传入旋转角度表示要依据 Y 轴为轴心旋转指定的角度,或是呼叫 Matrix 结构的 CreateRotationZ 方法并传入旋转角度表示要依据 Z 轴为轴心旋转指定的角度。请注意 CreateRotationX、CreateRotationY、和 CreateRotationZ 方法需要的角度的单位是弪度量,游戏程序可以视需要先利用 MathHelper 类别的 ToRadians 方法将单位为度度量的角度转换成弪度量,以便执行旋转的动作。

以下的程序代码会建立可以将 3D 模型以 Y 轴为核心旋转 180 度的 Matrix:

  1. Matrix worldRotation=Matrix.CreateRotationY(MathHelper.Pi);

请注意上述的程序代码会利用 MathHelper 类别的 Pi 属性指定旋转的角度为 180 度。游戏程序除了可以利用 CreateRotationX、CreateRotationY、和 CreateRotationZ 方法来旋转 3D 模型以外,也可以利用 Matrix 结构提供的 CreateFromYawPitchRoll 方法指定以 X 轴、Y 轴、和 Z 轴为轴心的旋转角度,其中的 Yaw 代表以 Y 轴为轴心的旋转角度,Pitch 代表以 X 轴为轴心的旋转角度,而 Roll 代表以 Z 轴为轴心的旋转角度,如图2 所示:

图2:Pitch 代表以 X 轴为轴心的旋转角度,而 Roll 代表以 Z 轴为轴心的旋转角度

技术分享

例如以下的程序代码中呼叫 Matrix 结构的 CreateRotationX、CreateRotationY、和 CreateRotationZ 方法的语法:

  1. Matrix modelWorldMatrix = Matrix.CreateScale(2.0f) *
  2. Matrix.CreateRotationX(MathHelper.Pi) * Matrix.CreateRotationY(MathHelper.Pi) *
  3. Matrix.CreateRotationZ(MathHelper.Pi) *
  4. Matrix.CreateTranslation(10, 0, 50);

就可以改呼叫 Matrix 结构的 CreateFromYawPitchRoll 方法来代替,如下:

  1. Matrix modelWorldMatrix = Matrix.CreateScale(2.0f) *
  2. Matrix.CreateFromYawPitchRoll(MathHelper.Pi, MathHelper.Pi, MathHelper.Pi) *
  3. Matrix.CreateTranslation(10, 0, 50);

[提示]

游戏程序可以利用 XNA Framework 提供的 MathHelper 类别的方法完成常用的数*算,包括计算角度,例如游戏程序需要用到 180 度角,就可以利用 MathHelper.Pi 来取得,需要 360 度角,可以直接利用 MathHelper.TwoPi 来取得,不需要执行 MathHelper.Pi * 2,需要 90 度角的时候则使用 MathHelper.PiOver2 来取得,不需执行 MathHelper.Pi / 2,需要 45 度角时可以利用 MathHelper.PiOver4 来取得,不需要执行 MathHelper.Pi / 4,以获得最佳的执行效能。

除了可以协助游戏程序取得角度以外,MathHelper 类别也可以协助游戏程序执行度度量和弪度量之间的转换,例如 MathHelper 类别的 ToDegree 方法可以将弪度量转换成度度量,而 MathHelper 类别的 ToRadians 方法可以将度度量转换成弪度量,不需要游戏程序自行执行转换的动作。

如果游戏程序需要放大/缩小 3D 模型,可以善用 Matrix 结构提供的 CreateScale 方法,例如以下的程序代码便会建立可以将 3D 模型放大两倍的 Matrix 结构:

  1. Matrix worldSclae = Matrix.CreateScale(2.0f);

透过上述放大/缩小、旋转、和平移等操作,游戏程序能够将 3D 模型定位在指定的位置和角度。请注意 Matrix 结构进行乘法运算的时候必须按照 SRT (Scale * Rotation * Translation) 顺序来执行,也就是必须先执行放大/缩小的动作,再执行旋转的动作,最后再执行平移的动作,因为 Matrix 结构的乘法不会有累积的效果。

学会将 3D 模型的物体空间 (Object Space) 转换成世界空间 (World Space) 之后,接下来我们就要引入相机的位置,计算出 3D 模型的检视空间 (View Space),也就是从使用者的角度检视 3D 模型的位置。

游戏程序可以呼叫 Matrix 结构提供的 CreateLookAt 方法,依据包括相机位置在内的相关信息,建立可以将世界空间转换成检视空间的 Matrix 结构。例如以下的程序代码就会利用 Matrix 结构的 CreateLookAt 方法建立可以将 3D 模型世界空间转换成检视空间的 Matrix 结构:

  1. Matrix viewMatrix = Matrix.CreateLookAt(new Vector3(0, 3, 5), new Vector3(0, 0, 0),
  2. new Vector3(0, 1, 0));

请注意 CreateLookAt 方法的第一个参数代表相机的位置,第二个参数代表欲检视的物体的位置,而第三个参数则是代表 Up 向量,也就是相机旋转依据的轴心,传入 (0,1,0) 表示相机可以以 Y 轴为轴心旋转 (即图3 中的 UP 轴),传入 (0,0,-1) 表示相机可以以 Z 轴为轴心旋转 (即图3 中的 LOOK 轴),而传入 (1,0,0) 表示相机可以以 X 轴为轴心旋转 (即图3 中的 RIGHT 轴),如图3 所示:

技术分享

[提示]

X、Y、Z 三个元素值皆为 0 的 Vector3 结构可以表示成 Vector.Zero,而 X、Y、Z 三个元素值分别为 0,1,0 的 Vector3 结构可以表示成 Vector.Up,所以上述建立可以将 3D 模型的世界空间转换成检视空间的 Matrix 结构的程序代码可以简写成以下的样子:

  1. Matrix viewMatrix = Matrix.CreateLookAt(new Vector3(0, 3, 5), Vector3.Zero, Vector3.Up);

计算好 3D 模型的检视空间之后,游戏程序还需要将检视空间转换成屏幕空间,也就是将 3D 模型的检视空间投影到 2D 的平面空间的位置,完成呈现 3D 模型的动作,因此屏幕空间 (Screen Space) 又称为投影空间 (Projection Space)。要完成从检视空间至投影空间的转换,游戏程序可以利用 Matrix 结构提供的 CreatePerspectiveFieldOfView 方法,建立能够执行转换工作的 Matrix 结构 (即 Projection Matrix)。

例如以下的程序代码就会呼叫 Matrix 结构的 CreatePerspectiveFieldOfView 方法,建立可以将 3D 模型的检视空间投射到屏幕空称的 Matrix 结构:

  1. float aspect = (float)Window.ClientBounds.Width / (float)Window.ClientBounds.Height;
  2. Matrix projectionMatrix = Matrix.CreatePerspectiveFieldOfView(
  3. MathHelper.PiOver4, aspect, 1, 100);

Matrix 结构的 CreatePerspectiveFieldOfView 方法需要的第一个参数是单位为弪度量的视角,其角度必须介于 0~p (即 0~180 度) 之间,第二个参数是高宽比例,您可以将游戏窗口的寛度除以游戏窗口的高度当做高宽比例,或是直接使用 GraphicsDeviceManager 的 GraphicsDevice 属性的 Viewport 属性的 AspectRatio 属性的内容值当做高宽比例,第三个参数是与近平面 (Near Plane) 的距离,请注意距离比与近平面还近的内容都不会呈现在游戏窗口中,第四个参数是与远平面 (Far Plane) 的距离,请注意距离比与远平面还远的内容都不会呈现在游戏窗口中。

有关近平面与远平面在 3 度空间的意义可以参考图4:

图4:近平面与远平面在3度空间的意义

技术分享

[注意]

以 XNA 为基础的游戏程序必须为每一个欲显示的 3D 模型建立 World Matrix,每一次改变相机的位置或方向都必须重新计算 View Matrix,而 Projection Matrix 则只要在游戏程序开始的时候计算一次即可。

 

 

3D 游戏控制

标签:

原文地址:http://www.cnblogs.com/yyxt/p/4461281.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!