了解投影矩阵 [英] Understanding the Projection Matrix

查看:256
本文介绍了了解投影矩阵的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图了解投影向量的值范围是多少。

I am trying to understand what the value range of projected vectors is. It seems at odds with what MSDN says.

下面的代码输出一个彩色三角形。三角形是完全可见的。我希望在预测了顶点之后,将满足下列条件:

The code below outputs a colored triangle. The triangle is fully visible. I would expect that after the verticies have been projected, the following would be true:

X和Y在-1到1的范围内。
Z的范围是0到1。

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

我从这里获得了以下信息: http://msdn.microsoft.com/en-us/library/bb195665.aspx

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

但是,当我使用视图和投影矩阵的乘积手动变换三角形的顶点时,它们具有以下值:

However, when I manually transform the verticies of the triangle using the product of view and projection matrix, they have the following values:

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

{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, yet the trinangle is 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);
        }
    }
}


推荐答案

不要忘记投影后的透视划分。这意味着在与投影矩阵相乘之后,将变换后的向量的 x y z w 值。因此,您必须处理4D同质矢量而不是3D矢量。您的初始向量只是(x,y,z,1),但是在应用投影矩阵(不是仿射变换)之后,它们的 w 可以(并且应该)为!= 1 ,因此您必须以此为出发点,以实现实际的透视失真:

Do not forget the perspective division after projection. This means after multiplying by the projection matrix, devide the transformed vector's x, y and z by their w values. So you have to work on 4D homogenous vectors instead of 3D vectors. Your initial vectors are just (x,y,z,1) but after the projection matrix (which is not an affine transformation) has been applied, their w can (and should) be != 1, so you have to devide by that, which realizes the actual perspective distortion:

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

请咨询一些有关3D变换,投影和同质坐标的入门资料,以获取更多见解。

Consult some introductory material on 3D transformations, projections and homogenous coordinates for some more insight.

编辑::我刚刚在您的代码中看到了另一个错误。 trans 必须为 _projection * _view ,这样 _view 首先将向量乘以 trans 来应用。除非XNA使用 row_vector * matrix 的数学错误约定。如果是这种情况,您的订单应该这样做。

I just saw another error in your code. trans has to be _projection * _view, so that _view gets applied first, when multiplying a vector by trans. Except if XNA uses the mathematically incorrect convention of row_vector * matrix. If that's the case, your order should do it.

这篇关于了解投影矩阵的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆