Understanding Projection Matrix

I am trying to understand what a range of values ​​of predicted vectors is. This is similar to what MSDN says.

The code below displays a colored triangle. The triangle is fully visible. I would expect the following to be done after projecting the vertices:

X and Y are in the range of -1 to 1. Z is in the range of 0 to 1.

I got this information from here: http://msdn.microsoft.com/en-us/library/bb195665.aspx

However, when I manually transform the vertices of the triangle using the product of the matrix of representations and forecasts, they have the following meanings:

{X: 1.8 Y: 0 Z: 3.991996} {X: 0 Y: 3 Z: 3.991996} {X: -1.8 Y: 0 Z: 3.991996}

Why do the values ​​fall out of the visible range, but is the trinangle fully visible?

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); } } } 
+1
source share
2 answers

Do not forget about dividing perspectives after projection. This means that after multiplying by the projection matrix, divide the transformed vector x , y and z by their values ​​of w . Thus, you need to work on 4D homogeneous vectors instead of 3D vectors. Your initial vectors are just (x,y,z,1) , but after the projection matrix has been applied (which is not an affine transformation), their w can (and should) be != 1 , so you need to divide on what implements the actual distortion of perspective:

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

Consult some introductory materials about 3D transforms, projections, and uniform coordinates for a deeper understanding.

EDIT: I just saw one more error in your code. trans must be _projection * _view , so _view is applied first when multiplying the vector by trans . row_vector * matrix XNA uses a mathematically incorrect row_vector * matrix convention. If this is the case, your order should do it.

+2
source

Not 100% sure, but I think it could be because it is a projection representation that no matter what the matrix is, will always represent it. If it were an orthogonal view, then it would not display a complete triangle.

0
source

All Articles