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();
}
}
{
// 這邊使用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);
}
}
}
最後附上專案檔display3D.rar