如何建立透视投影矩阵(没有API) [英] How to build perspective projection matrix (no API)

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

问题描述

我开发了一个简单的3D引擎(没有任何使用API​​的),成功地改变了我的场景成为世界视点空间,但必须使用透视投影矩阵(OpenGL的风格)的麻烦伸出我的场景(在视图空间)。我不知道对FOV,远近值,我得到了现场失真。 我希望如果有人能指导我如何建立和正确使用透视投影矩阵,例如codeS。在此先感谢您的帮助。

该矩阵的构建:

 双F = 1 / Math.Tan(fovy / 2);
返回新的双[,] {

    {F /看点,0,0,0},
    {0中,f,0,0},
    {0,0,(远东+近)/(远 - 近),(2 * FAR *近)/(近 - 远)},
    {0,0,-1,0}
};
 

矩阵使用:

 的foreach(P点在T.Points)
{
    。
    。 //转变点到均质点矩阵,以世界空间,并查看空间(正常工作)
    。

    //突出并与在previous code指定getProjectionMatrix()点:

    双[,]矩阵= MatrixMultiply函数(GetProjectionMatrix(Fovy,宽度/高度,近,远),viewSpacePointMatrix);

    //转换到笛卡尔坐标(从均质):

    矩阵[0,0] / =矩阵[3,0]。
    矩阵[1,0] / =矩阵[3,0]。
    矩阵[2,0] / =矩阵[3,0]。
    矩阵[3,0] = 1;
    P = MatrixToPoint(矩阵);

    //调整屏幕Y轴:

    P.y = this.Height  -  P.y;

    //打印...
}
 

解决方案

以下是透视投影矩阵的一个典型的实行。 这里是说明一切 OpenGL的投影矩阵一个很好的链接

 无效ComputeFOVProjection(矩阵和放大器;因此,浮动FOV,浮动方面,浮nearDist,浮farDist,布尔是左手/ * = TRUE * /)
{
    //
    投影矩阵//一般形式
    //
    //呃= COT(FOV / 2)== 1 /谭(FOV / 2)
    // UW /呵= 1 /纵横
    //
    // UW 0 0 0
    // 0呃0 0
    // 0 0 F /(F-N)1
    // 0 0 -fn /(F-N)0
    //
    //使结果首先是身份

    //检查坏参数,以避免被零除:
    //如果发现,断言和返回单位​​矩阵。
    如果(FOV< = 0 ||方面== 0)
    {
        断言(FOV大于0&安培;&安培;!方面= 0);
        返回;
    }

    浮frustumDepth = farDist  -  nearDist;
    浮oneOverDepth = 1 / frustumDepth;

    结果[1] [1] = 1 /黄褐色(0.5F * FOV);
    结果[0] [0] =(是左手1:α-1)*导致[1] [1] /方面;
    结果[2] [2] = farDist * oneOverDepth;
    结果[3] [2] =(-farDist * nearDist)* oneOverDepth;
    结果[2] [3] = 1;
    结果[3] [3] = 0;
}
 

I develop a simple 3D engine (Without any use of API), successfully transformed my scene into world and view space but have trouble projecting my scene (from view space) using the perspective projection matrix (OpenGL style). I'm not sure about the fov, near and far values and the scene I get is distorted. I hope if someone can direct me how to build and use the perspective projection matrix properly with example codes. Thanks in advance for any help.

The matrix build:

double f = 1 / Math.Tan(fovy / 2);
return new double[,] { 

    { f / Aspect, 0, 0, 0 },
    { 0, f, 0, 0 },
    { 0, 0, (Far + Near) / (Near - Far),  (2 * Far * Near) / (Near - Far) }, 
    { 0, 0, -1, 0 } 
};

The matrix use:

foreach (Point P in T.Points)
{     
    .
    .     // Transforming the point to homogen point matrix, to world space, and to view space (works fine)
    .     

    // projecting the point with getProjectionMatrix() specified in the previous code :      

    double[,] matrix = MatrixMultiply( GetProjectionMatrix(Fovy, Width/Height, Near, Far) , viewSpacePointMatrix );

    // translating to Cartesian coordinates (from homogen):

    matrix [0, 0] /= matrix [3, 0];
    matrix [1, 0] /= matrix [3, 0];
    matrix [2, 0] /= matrix [3, 0];
    matrix [3, 0] = 1;
    P = MatrixToPoint(matrix);

    // adjusting to the screen Y axis:

    P.y = this.Height - P.y;

    // Printing...
}

解决方案

Following is a typical implemenation of perspective projection matrix. And here is a good link to explain everything OpenGL Projection Matrix

void ComputeFOVProjection( Matrix& result, float fov, float aspect, float nearDist, float farDist, bool leftHanded /* = true */ )
{
    //
    // General form of the Projection Matrix
    //
    // uh = Cot( fov/2 ) == 1/Tan(fov/2)
    // uw / uh = 1/aspect
    // 
    //   uw         0       0       0
    //    0        uh       0       0
    //    0         0      f/(f-n)  1
    //    0         0    -fn/(f-n)  0
    //
    // Make result to be identity first

    // check for bad parameters to avoid divide by zero:
    // if found, assert and return an identity matrix.
    if ( fov <= 0 || aspect == 0 )
    {
        Assert( fov > 0 && aspect != 0 );
        return;
    }

    float frustumDepth = farDist - nearDist;
    float oneOverDepth = 1 / frustumDepth;

    result[1][1] = 1 / tan(0.5f * fov);
    result[0][0] = (leftHanded ? 1 : -1 ) * result[1][1] / aspect;
    result[2][2] = farDist * oneOverDepth;
    result[3][2] = (-farDist * nearDist) * oneOverDepth;
    result[2][3] = 1;
    result[3][3] = 0;
}

这篇关于如何建立透视投影矩阵(没有API)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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