2011-05-24 129 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%确定,但我认为这可能是因为它是投影视图,无论矩阵是什么,它总是会代表它。如果它是正交视图,则它将开始不显示完整的三角形。