上一節中,我們認識了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 ——