文斌的专栏

聊聊架构设计、软件工程、敏捷开发、移动应用的那些事

在Windows Phone中进行3D开发之二摄像机

       上一节中,我们认识了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个参数,也就把镜头的信息定义完了。

 

 

       同样的,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 ——

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/caowenbin/article/details/6871332
个人分类: Windows Phone
所属专栏: Windows Phone应用开发
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭