透视投影

时间:2012-06-20 20:58:14

标签: c# 3d perspectivecamera

几天前,我决定开始进行3D编程并遇到透视投影。 我使用以下代码来获取矩阵:

public static Matrix3D ProjectionMatrix(double angle, double aspect, double near, double far)
{
    double size = near * Math.Tan(MathUtils.DegreeToRadian(angle) / 2.0);
    double left = -size, right = size, bottom = -size / aspect, top = size / aspect;
    Matrix3D m = new Matrix3D(new double[,] {
    {2*near/(right-left),0,(right + left)/(right - left),0},
    {0,2*near/(top-bottom),(top+bottom)/(top-bottom),0},
    {0,0,-(far+near)/(far-near),-(2 * far * near) / (far - near)},
    {0,0,-1,0}
    });
    return m;
}

我对相机使用以下代码:

Matrix3D Camera
{
    get
    {
        Vector3D cameraZAxis = -this.LookDirection;
        cameraZAxis.Normalize();

        Vector3D cameraXAxis = Vector3D.CrossProduct(this.UpDirection, cameraZAxis);
        cameraXAxis.Normalize();

        Vector3D cameraYAxis = Vector3D.CrossProduct(cameraZAxis, cameraXAxis);

        Vector3D cameraPosition = (Vector3D)this.Position;
        double offsetX = -Vector3D.DotProduct(cameraXAxis, cameraPosition);
        double offsetY = -Vector3D.DotProduct(cameraYAxis, cameraPosition);
        double offsetZ = -Vector3D.DotProduct(cameraZAxis, cameraPosition);

        return new Matrix3D(new double[,]{{cameraXAxis.X, cameraYAxis.X, cameraZAxis.X, 0},
                            {cameraXAxis.Y, cameraYAxis.Y, cameraZAxis.Y, 0},
                            {cameraXAxis.Z, cameraYAxis.Z, cameraZAxis.Z, 0},
                            {offsetX, offsetY, offsetZ, 1}});
    }
}

但是,我不知道如何获取模型或世界矩阵,以前的代码也有什么问题吗?

1 个答案:

答案 0 :(得分:0)

Matrix用于将对象从一个“空间”转换为另一个“空间”。想象一个模型,它是一个立方体,模型中心是0,0,0,每个角都是5个。现在要将它转换成你的世界,你可以应用Worldmatrix进行转换,将这些模型坐标放入你的世界。

例如,应该将模型“移动”到5,5,5的翻译。现在只需考虑将此位置添加到模型及其所有点,现在这些新坐标称为“在世界空间中”。现在,模型是通过您的世界矩阵放置在世界的第5,5,5位(您的前模型中心现在位于您的世界中此位置)。

视图矩阵有点难以理解,但最容易想到的是“我们无法移动相机,因此我们将所有对象移向相反的方向,因此看起来我们移动了相机”。这听起来很难,但事实上它就像从模型空间转换到世界空间一样。

现在我们从世界空间转变为视野空间。最后,我们需要在屏幕上显示它。显然,您的屏幕是2D并且您仍然拥有3D场景,现在您需要一种方法将3D对象转换为视图空间。这可以通过不同种类的投影来实现。两个重要的是正交投影和透视投影。事实上,这使用Z组件(我们在2D表面上没有像屏幕一样)和屏幕分辨率将我们的可见世界“投影”到我们的屏幕空间中。

所有这些都可以使用矩阵轻松完成。每次转型都是一个良好的开端。公平地说,你不需要任何它,你可以在屏幕空间直接提供你的数据,但这是不切实际的。如果您不需要World矩阵,例如,如果您的模型被建模以便可以直接使用,则会使用Matrix.Identity,大致可以解释为将数字乘以1,这样就可以得到相同的号码。此外,视图的标识矩阵就像将相机放在0,0,0的世界中并向下看Z轴(哪个轴很大程度上取决于您使用的坐标系)

要获取着色器的最终矩阵,您通常会将所有这些矩阵(或通过乘法组合的矩阵)传递给着色器。如果使用固定功能管道,通常有提供它们的方法。投影通常是固定的,但可以改变以应用一些视觉效果,如缩放狙击步枪或鱼眼效果。摄像机矩阵当然用于移动和旋转摄像机。世界矩阵用于在场景中定位对象,移动玩家,旋转门等。

免责声明:这就是我自己理解整个事情的方式,所以它绝不是一个数学正确的解释,但也许对OP有任何帮助。

为了更好地了解整个主题,您可以阅读this