自定义视图矩阵的扩展问题

Stretching Issue with Custom View Matrix

我目前正在为我的项目开发我自己的 2D 数学库,以提高我对底层矩阵数学的理解。 过去我使用过诸如 GLM 之类的库,但我觉得将其作为一种学习经验可能值得研究。

其中大部分都很简单,我的大部分数学 类 都与 OpenGL 集成并很好地工作,但是我的视图矩阵似乎在 window 的边缘拉伸了我的四边形。

请注意,这不是透视问题,我不仅使用了正交矩阵,而且我已经将其与 MVP 分开,使用视图矩阵代替 MVP,但问题仍然存在。

下面是我的视图矩阵生成代码:

Matrix4x4 GenerateView(const Vector2f &cameraPosition)
{
    Matrix4x4 mat;

    //Right
    mat.elements[0][0] = 1;
    mat.elements[0][1] = 0;
    mat.elements[0][2] = 0;
    mat.elements[0][3] = -Dot(cameraPosition.x, cameraPosition.y, 10, 1, 0, 0);

    //Up
    mat.elements[1][0] = 0;
    mat.elements[1][1] = 1;
    mat.elements[1][2] = 0;
    mat.elements[1][3] = -Dot(cameraPosition.x, cameraPosition.y, 10, 0, 1, 0);

    //Look
    mat.elements[2][0] = cameraPosition.x;
    mat.elements[2][1] = cameraPosition.y;
    mat.elements[2][2] = -1;
    mat.elements[2][3] = -Dot(cameraPosition.x, cameraPosition.y, 10, cameraPosition.x, cameraPosition.y, -1);

    //Last Column
    mat.elements[3][0] = 0;
    mat.elements[3][1] = 0;
    mat.elements[3][2] = 0;
    mat.elements[3][3] = 1;
    return mat;
}

矩阵主要是列(如果我没理解错的话)。 我不清楚 'Look' 是否指的是前向单位向量,所以我尝试了 'center',但问题仍然存在。

//Look
    mat.elements[2][0] = 0;
    mat.elements[2][1] = 0;
    mat.elements[2][2] = -1;
    mat.elements[2][3] = -Dot(cameraPosition.x, cameraPosition.y, 10, 0, 0, -1);

最后,如果有人怀疑 Dot 产品实现不正确:

float Dot(float x1, float y1, float z1, float x2, float y2, float z2)
{
    return x1 * x2 + y1 * y2 + z1 * z2;
}

在视口上,X 轴指向左侧,Y 轴指向上方,Z 轴指向视图外(请注意,在右手系统中,Z 轴是 X 轴的叉积轴和 Y 轴)。

请注意,转换矩阵通常如下所示:

( X-axis.x, X-axis.y, X-axis.z, 0 )
( Y-axis.x, Y-axis.y, Y-axis.z, 0 )
( Z-axis.x, Z-axis.y, Z-axis.z, 0 )
( trans.x,  trans.y,  trans.z,  1 )

下面的代码定义了一个矩阵,它精确封装了计算场景外观所需的步骤:

  • 正在将模型坐标转换为视口坐标。
  • 旋转,看向视图的方向。
  • 移动到眼睛位置


Matrix4x4 LookAt( const Vector3f &pos, const Vector3f &target, const Vector3f &up )
{ 
    Vector3f mz( pos[0] - target[0], pos[1] - target[1], pos[2] - target[2] };
    Normalize( mz );
    Vector3f my( up[0], up[1], up[2] );
    Vector3f mx = Cross( my, mz );
    Normalize( mx );
    my = Cross( mz, mx );

    Matrix4x4 m;
    m.elements[0][0] = mx[0]; m.elements[0][1] = my[0]; m.elements[0][2] = mz[0]; m.elements[0][3] = 0.0f;
    m.elements[1][0] = mx[1]; m.elements[1][1] = my[1]; m.elements[1][2] = mz[1]; m.elements[1][3] = 0.0f;
    m.elements[2][0] = mx[2]; m.elements[2][1] = my[2]; m.elements[2][2] = mz[2]; m.elements[2][3] = 0.0f;

    m.elements[3][0] = Dot(mx, pos);
    m.elements[3][1] = Dot(my, pos);
    m.elements[3][2] = Dot(Vector3f(-mz[0], -mz[1], -mz[2]), pos);
    m.elements[3][3] = 1.0f;

    return m;
}

Vector3f Cross( const Vector3f &a, const Vector3f &b )
{ 
    return Vector3f( a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0] ); 
}

float Dot( const Vector3f &a, const Vector3f &b )
{ 
    return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
}

void Normalize( Vector3f &v )
{ 
    float len = sqrt( v[0] * v[0] + v[1] * v[1] + v[2] * v[2] );
    v = Vector3f( v[0] / len, v[1] / len, v[2] / len );
}