上一节中,我们认识了3D世界中最基础的一个概念——坐标系,并且了解了XNA中使用Vector3类型来表示。但是,由于引入了深度信息,所以在空间中的物体要想正确的投影出来,还缺少一个重要的道具——摄像机。
先来回想一下用摄像机或照相机的经历吧!对于同样的目标物体,有以下因素影响成像的结果:摄像机位置、摄像机方向、镜头参数。当摄像机所处的位置不同时,对物体的观察角度影响了成像的结果。当摄像机横向或竖向的角度不同时,成像也呈横向或竖向不同的角度。当使用不同焦距的镜头时,即使摄像机位置和方向都不变,成像的结果依然有差异。
由此可见,要想取得正确的成像结果,即正确的绘制渲染出3D空间中的物体,对摄像机的确定是非常重要的。换句话说,只有确定了摄像机和物体,才能得到确定的一个渲染结果。
那么对于如此复杂的摄像机信息,在XNA中要如何表示呢?这个还是得分两个部分来表述,一个部分用于表示摄像机的位置、朝向的目标位置、向上的方向这三个视点属性,相当于把摄像机固定下来;另一部分用于表示摄像机的视角、成像的长宽比、投影参数这三个属性,相当于把镜头和像纸信息固定下来。下面我们分别来看一下这两部分在XNA中的表示方法。
在计算机图形学中,我们知道3D世界实际上就是矩阵,以后在3D世界中的大量操作的实质全是矩阵运算,所以我们要先介绍一下矩阵。当然不是介绍数学概念,而是XNA中的Matrix类。
XNA提供了Matrix类用于表示矩阵,它是一个4X4矩阵,可以进行数学运算,还提供了一些方法用于创建矩阵。常用的构造方法有两种,一是构造单位矩阵:
Matrix matrix=Matrix. Identity;
另一种是创建特殊矩阵,Matrix类提供了一组以Create开头的静态方法用于创建需要的矩阵。
回到摄像机的表示当中来,对于摄像机的位置信息,实际上就利用了Matrix类的CreateLookAt()方法来创建一个视点的矩阵,方法原型是:
public static Matrix CreateLookAt(Vector3cameraPosition, Vector3 cameraTarget, Vector3 cameraUpVector);
三个参数分别对应前述的摄像机位置、朝向、向上的方向。
对于镜头信息,还要稍微复杂一点,我们需要先了解一下投影。看下面的投影示意图(注:图片来源于网络)。实际上我们要定义的不是真正镜头上的焦距、光圈,而是这个这平截头体的信息。这个平截头体就是投影矩阵,位于该体以外的物体将无法成像。对于这个平截头体,我们需要确定的参数包括:视角即可视范围,通常是45度角;长宽比;近平面;远平面。有了这4个参数,也就把镜头的信息定义完了。
![](https://box.kancloud.cn/2016-04-08_570727f9ea69d.gif)
同样的,Matrix类提供了CreatePerspectiveFieldOfView()方法来创建投影矩阵,该方法原型是:
public static MatrixCreatePerspectiveFieldOfView(float fieldOfView, float aspectRatio, floatnearPlaneDistance, float farPlaneDistance);
4个参数对应的就是平截头体的4个值。
至此,我们使用了两个矩阵才把摄像机信息确定下来,这两个矩阵也可以称为视图矩阵和投影矩阵。由于摄像机在3D开发中用得比较多,所以我们定义一个Camera类来简化摄像机的构造,在以后的代码中可以方便的使用。该类的代码如下:
~~~
public class Camera : Microsoft.Xna.Framework.GameComponent
{
public Matrix view{get;protected set;}
public Matrix projection { get; protected set; }
public Camera(Game game, Vector3 pos, Vector3 target, Vector3 up, float fieldOfView, float aspectRatio, float nearPlaneDistance,float farPlaneDistance)
: base(game)
{
view = Matrix.CreateLookAt(pos, target, up);
projection = Matrix.CreatePerspectiveFieldOfView(fieldOfView,aspectRatio,nearPlaneDistance,farPlaneDistance);
}
/// <summary>
/// Allows the game component to perform any initialization it needs to before starting
/// to run. This is where it can query for any required services and load content.
/// </summary>
public override void Initialize()
{
base.Initialize();
}
/// <summary>
/// Allows the game component to update itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
public override void Update(GameTime gameTime)
{
base.Update(gameTime);
}
}
~~~
好了,本节的内容就到这里吧,有了摄像机,后边就可以开始开发工作了。
——欢迎转载,请注明出处 [http://blog.csdn.net/caowenbin](http://blog.csdn.net/caowenbin) ——
- 前言
- Windows Phone 7开发环境初体验
- Windows Phone 7 3D开发中使用纹理贴图
- 在Windows Phone中进行3D开发之一坐标系
- 在Windows Phone中进行3D开发之二摄像机
- 在Windows Phone中进行3D开发之三空间
- 在Windows Phone中进行3D开发之四三角形
- 在Windows Phone中进行3D开发之五平移缩放
- 在Windows Phone中进行3D开发之六旋转
- 在Windows Phone中进行3D开发之七纹理
- 在Windows Phone中进行3D开发之八光照
- 在Windows Phone中进行3D开发之九模型
- 在Windows Phone中进行3D开发之十组件
- 在Windows Phone中进行3D开发之十一天空
- 在Windows Phone中进行3D开发之十二飞行
- 在Windows Phone中进行3D开发之十三阳光
- 在Windows Phone中进行3D开发之后记(附源码)