如何建立透视投影矩阵(没有API)矩阵、透视、API

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

我开发了一个简单的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;
}

阅读全文

相关推荐

最新文章