在前文中,我們初步瞭解了在Windows Phone 7的XNA架構下實現3D情境的基礎知識,能夠進行3D空間下物體的變換,並且增加了紋理貼圖和光照用於表現更加真實的世界。通過這些操作,我們已經進入了3D的世界。接下來,我們將使用真實的3D物體模型來進行複雜的情境實現,形成一個飛船在天空中飛行的效果。現在,讓我們開始吧。
任何複雜的3D物體模型都是由若干個三角形組成,無論是一個立方體,還是一艘宇宙飛船。此前用到的三角形,需要定義它的三個頂點。如果是一個立方體,每個面由兩個三角形拼成,6個面共需要12個三角形,即需要36個頂點。假如是更複雜的物體,需要幾萬甚至更多的三角形才能表示的話,那麼開發人員定義頂點的工作量肯定是巨大的。
為瞭解決這一問題,通常在團隊開發中,會有負責3D建模的同事,利用專業的3D建模工具如Autodesk公司的3DS Max、Maya等製作複雜的3D物體模型,製作好後匯出為.x或.fbx格式的3D模型檔案可供開發時使用。
下面,我們就借用一個經過這樣製作現成的宇宙飛船模型檔案來開始一個複雜情境的製作。
首先,也是最重要的,就是需要把這種模型檔案渲染出來。為此,需要先在Content項目中增加一個新的檔案夾,不妨就命名為Models,專門用於存放模型檔案及其關的貼圖等。然後將wedge_player1.x和wedge_p1_diff_v1.tga兩個檔案複製到該檔案夾下,並將wedge_player1.x檔案添加到Content項目中。這兩個檔案前者是模型檔案,後者是該模型對應的貼圖,由於在載入模型時會自動處理貼圖,所以貼圖檔案無需添加到Content項目中。
在完成了模型資源的添加以後,就可以寫代碼進行渲染的工作。XNA中提供了Model類用於處理這種3D模型,用法如下:
model =Content.Load<Model>(@"Models/wedge_player1");
這樣,在LoadContent()方法中就可以進行模型的載入了。
接下來,在進入Draw()方法之前,思考一個問題,那就是座標怎麼辦?試想,一個大量三角形組成的模型檔案,如何把它的座標正確的映射到我們自己的座標系中?這裡其實是用到了骨骼的形象表示。
在3D模型檔案中存在著骨骼資料,就像人體的骨骼一樣,只要骨骼被確定,附著於骨骼之上的關聯部分的座標也就確定了。如果對骨骼座標進行變換,則對應的關聯部分也會做出變換。因此,在繪製模型之前,需要一個矩陣數組,用於儲存模型的骨骼座標資訊。
下面,為類添加一個成員變數用於儲存骨骼座標:
Matrix[] modelTransforms;
在model載入之後,對該變數進行構造:
modelTransforms=newMatrix[model.Bones.Count];
接下來,該到Draw()方法了,是渲染輸出的時候了。
protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); model.CopyAbsoluteBoneTransformsTo(modelTransforms); foreach (ModelMesh mesh in model.Meshes) { foreach (BasicEffect effect in mesh.Effects) { effect.EnableDefaultLighting(); effect.World = modelTransforms[mesh.ParentBone.Index] * scaleMatrix * translateMatrix * rotateMatrix; effect.View = camera.view; effect.Projection = camera.projection; } mesh.Draw(); } base.Draw(gameTime); }
在這段代碼中,首先通過Model.CopyAbsoluteBoneTransformsTo()方法將模型的骨骼資料複製到我們的數組中,然後對模型中的每一個網格地區的每一個渲染效果進行應用,為其指定全局座標、視圖變換和投影變換,從而將模型按照我們的攝像機參數進行渲染輸出。
在這裡,使用了如下的LoadContent()方法,以取得較好的輸出效果。
protected override void LoadContent() { rotateMatrix = Matrix.Identity; translateMatrix = Matrix.CreateTranslation(10, 0, 0); scaleMatrix = Matrix.CreateScale(0.01f, 0.01f, 0.01f); camera = new Camera(this, new Vector3(0, 30, 30), Vector3.Zero, Vector3.Up, MathHelper.PiOver4, (float)GraphicsDevice.Viewport.Width / (float)GraphicsDevice.Viewport.Height, 1.0f, 50.0f); basicEffect = new BasicEffect(GraphicsDevice); model = Content.Load<Model>(@"Models/wedge_player1"); modelTransforms=new Matrix[model.Bones.Count]; }
即向x軸正方向移動了10個座標單位,縮放0.01倍。
運行結果。
由於在Update()函數中加入了點擊螢幕時調整rotateMatrix的代碼,因此當點擊螢幕時會發現模型可以正確的旋轉。
怎麼樣,是不是很興奮呢?一個如此複雜的3D物體就這樣出現了。通過上述的代碼可以發現,載入並渲染一個3D模型在XNA架構下還是很容易實現的,我們盡可以把前文中對三角形的所有操作都搬到這裡,還有更多的驚喜在等著我們創造。
——歡迎轉載,請註明出處 http://blog.csdn.net/caowenbin ——