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

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

问题描述

我试图了解投影向量的值范围是多少.这似乎与 MSDN 所说的不一致.

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

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

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);
        }
    }
}

推荐答案

不要忘记投影后的透视分割.这意味着在乘以投影矩阵后,将转换后的向量的 xyz 除以它们的 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,以便在向量乘以 trans 时首先应用 _view.除非 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天全站免登陆