XNA-顯示3D模型

XNA-顯示3D模型

    將3D模型從3D軟體匯出之後,接下來就需要將它運用到程式中,程式中要顯示3D模型必須先將它加入到專案中,在方案總管中Content上按右鍵=>加入=>現有項目,然後你就可以選擇你要加入到專案中的模型檔案,XNA支援副檔名有X和FBX的檔案,選好後它就加入到你的專案中了,之後需在加入模型的檔案上按右鍵的屬性中命名,其中的Asset name這會在程式中使用到,所以必須命名,之後就是編寫程式碼讓3D模型顯示在螢幕上。

    在遊戲函數一開始就必須先宣告存放3D模型的變數。

Model 變數名稱;

    之後再到LoadContent函數中編寫要讀取專案中的哪個模型。

變數名稱 = content.load<Model>("名稱")=>名稱就是在模型上取的Asset name

    然後再到Draw函數裡撰寫程式讓它顯示出來,要在3D中顯示模型會需要使用到矩陣運算、攝影機(觀測點)、投影轉換、繪圖著色最後才是真正的畫出模型,以下以XNA內建的函數來幫助我們快速的顯示模型,往後會更詳細的介紹每個細節。

    3D模型是一群數值資料,紀錄一個3D物件的形狀,而一個模型可能是由好幾個子物件所組成,每個子物件都會有自己的模型網格(mesh),也就是用一群三角面來拼湊這個子物件的外觀形狀,所以要畫出一個模型就必須把它所有的模型網格畫出來。

    這邊需要先宣告一個儲存模型骨骼的變數。

Matrix[] 變數 = new Matrix[模型變數.Bones.Count];

    然後再將模型的骨骼資訊複製到剛剛宣告的矩陣變數裡。

模型變數.CopyAbsoluteBoneTransformsTo(矩陣變數);

    之後就必須使用迴圈將模型真正的畫出來,這邊需要注意的是因為我們使用的是XNA提供的基本效果,所以才會有Draw這個成員函數可以使用,如果要使用我們自行撰寫shader程式的話,就必須使用到DrawIndexedPrimitive這個函數來繪製模型。

foreach (ModelMesh 網格變數 in 模型變數.Meshes)
{
        // 這邊使用XNA提供的基本效果來繪製模型
        foreach (BasicEffect 效果變數 in 網格變數.Effects)
        {
                 // 使用XNA提供的打光方法,才不會一片漆黑
                效果變數.EnableDefaultLighting();
                // 將模型的位置傳給效果來繪製模型
                效果變數.World = 矩陣變數[網格變數.ParentBone.Index]*世界矩陣;
                效果變數.View = 觀看矩陣;
                效果變數.Projection = 投影矩陣;
                // 實際把模型畫出來
                網格變數.Draw();
        }

}

程式範例:


using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

namespace display3D
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Model robot;     //宣告存放機器人的變數

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            robot = Content.Load<Model>("playerRobot");
        }

        protected override void UnloadContent()
        {
        }

        protected override void Update(GameTime gameTime)
        {
            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            // 首先要求XNA Framework替我們清除螢幕成淺藍色的底色
            graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
            //將模型放置在遊戲世界的中心
            Matrix world = Matrix.CreateTranslation(0.0f, 0.0f, 0.0f);
            //從離Z軸50單位的地方向著原點看
            Matrix view = Matrix.CreateLookAt(new Vector3(0.0f, 0.0f, 50.0f), Vector3.Zero, Vector3.Up);
            //將3D到2D螢幕的投影轉換
            Matrix projection = Matrix.CreatePerspectiveFieldOfView((float)Math.PI / 4.0f, 800.0f / 600.0f, 1.0f, 1000.0f);

            //宣告變數儲存機器人的骨骼資訊
            Matrix[] temprobot = new Matrix[robot.Bones.Count];
            robot.CopyAbsoluteBoneTransformsTo(temprobot);

            //將機器人的每個部位畫出來
            foreach (ModelMesh mesh in robot.Meshes)
            {
                // 這邊使用XNA提供的基本效果來繪製模型
                foreach (BasicEffect effect in mesh.Effects)
                {
                    // 使用XNA提供的打光方法,才不會一片漆黑
                    effect.EnableDefaultLighting();
                    // 將模型的位置傳給效果來繪製模型
                    effect.World = temprobot[mesh.ParentBone.Index] * world;
                    effect.View = view;
                    effect.Projection = projection;
                    // 實際把模型畫出來
                    mesh.Draw();
                }
            }

            base.Draw(gameTime);
        }
    }
}

1

最後附上專案檔display3D.rar