在很早之前的文章,有針對XNA 1.0的版本做3D模型顯像的範例程式說明。

使用著還是可以參考之前的說明,然後對照看一下即可。

兩著不會差異太多。

要將模型顯像出來,首先需要宣告一個Model的物件

可以在類別中空白位置宣告一個變數

EX: Model mModel;    (變數名字隨個人喜好,不過這邊建議各位可以使用匈牙利命名法則來做命名)

在LoadContent函數中,將檔案載入

mModel = this.Game.Content.Load<Model>("tank");

在Draw的函數中,使用basicEffect來將模型繪製(Camera的部分使用這可以依據自己的喜好設定,也可以直接使用右邊側欄位的Camera程式碼)

void fBasicEffectRendering()
{
     Matrix[] transforms = new Matrix[mModel.Bones.Count];
     mModel.CopyAbsoluteBoneTransformsTo(transforms);
     foreach (ModelMesh mesh in mModel.Meshes)
    {
           foreach (BasicEffect effect in mesh.Effects)
          {
              effect.EnableDefaultLighting();
              effect.World = transforms[mesh.ParentBone.Index] * Matrix.Identity;
              effect.View = view;
              effect.Projection = projection;
          }
     mesh.Draw();
     }
}

------------------------------------------------------------------------------

比較需要特別說明的就是

Matrix[] transforms = new Matrix[mModel.Bones.Count];
mModel.CopyAbsoluteBoneTransformsTo(transforms);

....

effect.World = transforms[mesh.ParentBone.Index] * Matrix.Identity;

如果沒有這三行程式碼,我們得到的結果會是

加入三行程式碼以後得到的結果為

這三行程式碼主要是做矩陣的轉換,因為這個tank的模型是由很多不同的零件(part)組成。

每個零件的在模型製作期間都是在原點的位置上,所以如果我們不乘上他們各自的轉換矩陣(transform matrix)就會出現第一張圖片的問題。

而轉換矩陣就像是基本的平移旋轉等等。

所以下次你看到模型顯像的結果有些問題,可以先看看這樣處理有沒有效果。

 

有時候我們會需要顯示一些2D文字訊息在上面。

會使用spriteBatch的DrawString方法來繪製字串。

如果你將3D模型畫出來再加上2D文字,你會發現你的模型變得很詭異...像這樣 (主要是深度測試出錯才會這樣,因為在畫2Dsprite的時候會關閉深度測試)

要解決的方式如下

1. 可以在spriteBatch.begin的地方設定:

spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.NonPremultiplied,SamplerState.LinearWrap,DepthStencilState.Default,RasterizerState.CullCounterClockwise);

最主要的參數就是DepthStencilState,這部分在draw sprite的時候是被關閉的,我們需要把他打開設定成Default,這樣才會保有原來的3D深度測試。

2. 除了上述方法,還可以再spriteBatch.Begin();之前加入

GraphicsDevice.BlendState = BlendState.AlphaBlend;
GraphicsDevice.DepthStencilState = DepthStencilState.None;
GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
GraphicsDevice.SamplerStates[0] = SamplerState.LinearClamp;

畫玩2D圖片以後,再加入

GraphicsDevice.BlendState = BlendState.Opaque;
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;

這樣也可以獲得正確的結果。

2D+ 3D兩個並存方式,在XNA 3.1以前是使用設定SaveState的方式,將當下的flag狀態全部儲存起來,在4.0則是將裡面的flag分解成很多小小的物件。

所以我們可以針對不同的物件去做設定,而非將整個狀態全部儲存起來。

創作者介紹

StreamWhite

teexit1224 發表在 痞客邦 PIXNET 留言(0) 人氣()