2011-05-24 130 views
1

我想了解投影向量的值範圍。這似乎與MSDN所說的不一致。瞭解投影矩陣

下面的代碼輸出一個彩色的三角形。三角形完全可見。我希望的是,verticies已發射後,下面將是真實的:

X和Y是在-1到1範圍內 Z是在0到1

我的範圍得到從這裏該信息:http://msdn.microsoft.com/en-us/library/bb195665.aspx

然而,當我手動變換使用的視圖和投影矩陣的產品的三角形的verticies,它們具有以下的值:

{X:1,8 Y:0 Z:3,991996} {X:0 Y:3 Z:3,991996} {X:-1,8 Y:0 Z:3,991996}

爲什麼值掉出可見光範圍內的,然而trinangle是完全可見?

using Microsoft.Xna.Framework; 
using Microsoft.Xna.Framework.Graphics; 
using System; 
using Microsoft.Xna.Framework.Input; 

namespace WasMachtDieProjektion 
{ 
    public class Game1 : Microsoft.Xna.Framework.Game 
    { 
     GraphicsDeviceManager graphics; 

     Matrix _view; 
     Matrix _projection; 
     VertexPositionColor[] _verticies; 
     Vector3[] _vectors; 
     BasicEffect _effect; 

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

     protected override void LoadContent() 
     { 
      _vectors = new Vector3[] { 
       new Vector3(-3,0,0), 
       new Vector3(0,3,0), 
       new Vector3(3,0,0) 
      }; 

      _verticies = new VertexPositionColor[] { 
       new VertexPositionColor(_vectors[0], Color.AliceBlue), 
       new VertexPositionColor(_vectors[1], Color.Yellow), 
       new VertexPositionColor(_vectors[2], Color.Red) 
      }; 

      _effect = new BasicEffect(graphics.GraphicsDevice); 
      _effect.VertexColorEnabled = true; 

      GraphicsDevice.RasterizerState = new RasterizerState() { CullMode = CullMode.None }; 
     } 

     protected override void Update(GameTime gameTime) 
     { 
      _view = Matrix.CreateLookAt(new Vector3(0, 0, -4f), new Vector3(0, 0, 0), Vector3.Up); 
      _projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver2, GraphicsDevice.Viewport.AspectRatio, 0.01f, 20f); 

      Vector3[] transformed = new Vector3[3]; 
      Matrix trans = _view * _projection; 
      Vector3.Transform(_vectors, ref trans, transformed); 

      foreach (var v in transformed) 
      { 
       Console.WriteLine(v); 
      } 
      Console.WriteLine("---"); 

      if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) 
       this.Exit(); 

      base.Update(gameTime); 
     } 

     protected override void Draw(GameTime gameTime) 
     { 
      GraphicsDevice.Clear(Color.CornflowerBlue); 

      _effect.View = _view; 
      _effect.Projection = _projection; 

      foreach (var pass in _effect.CurrentTechnique.Passes) 
      { 
       pass.Apply(); 
       GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleList, _verticies, 0, 1); 
      } 

      base.Draw(gameTime); 
     } 
    } 
} 
+0

您是否嘗試過按照MSDN文章中的建議顯示BoundingFrustrum?它應該更好地解釋事情。 – jv42 2011-05-24 14:46:35

回答

2

不要忘記投影后的透視除法。這意味着由所述投影矩陣相乘之後,devide的變換矢量的xyz通過w值。所以你必須研究4D同質矢量而不是3D矢量。您的初始向量只是(x,y,z,1),但在應用了投影矩陣(它不是仿射變換)之後,它們的w可以(也應該)爲!= 1,因此您必須按照此設置來實現實際透視失真:

(x', y', z', w') = trans * (x, y, z, 1); 
(x'', y'', z'') = (x'/w', y'/w', z'/w'); 

請教關於3D變換,預測和齊次座標一些介紹材料對於一些更深入的瞭解。

編輯:我剛纔看到另一個錯誤在你的代碼。 trans必須是_projection * _view,使得_view被首先施加,通過trans乘以一個向量時。除非XNA使用數學上不正確的約定row_vector * matrix。如果是這樣的話,你的訂單應該這樣做。

+0

你是對的,那就是訣竅。我使用的轉換方法似乎只是扔掉第四個組件。關於你的編輯,XNA確實使用了row_vector *矩陣。 – TheFogger 2011-05-24 15:12:24

+0

沒有「數學正確的順序」,這只是約定。在這種情況下,如果您轉換所有內容並將事情從左向右進行,結果將是相同的。 – datenwolf 2011-05-26 08:14:13

+0

@datenwolf是的我在實踐中知道沒有區別。但是我在數學課程中用列向量長大。行向量實際上是一個轉置向量:Mv =(vTMT)T(我在我的回答中看到了使用行向量的諷刺意味)。 – 2011-05-26 13:18:56

0

不是100%確定,但我認爲這可能是因爲它是投影視圖,無論矩陣是什麼,它總是會代表它。如果它是正交視圖,則它將開始不顯示完整的三角形。