c++ - 自定义 View 矩阵的扩展问题

标签 c++ opengl matrix coordinate-transformation

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

其中大部分都很简单,我的大部分数学课都与 OpenGL 集成并配合良好,但是我的 View 矩阵似乎在窗口边缘拉伸(stretch)了四边形。

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

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

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

矩阵主要是列(如果我理解正确的话)。 我不清楚“外观”是否指的是前向单位 vector ,所以我尝试了它以及“中心”,但问题仍然存在。

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

最佳答案

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

view coordinate system

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

( 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 )

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

  • 将模型坐标转换为视口(viewport)坐标。
  • 旋转,看向 View 的方向。
  • 眼睛位置的移动


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

关于c++ - 自定义 View 矩阵的扩展问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45645746/

相关文章:

C++ 重载运算符<<和运算符>>

c++ - 尝试在 Eclipse CDT 中提取函数时出现 "Too many declarations in selection"错误消息

c++ - 比较指向不同数组的指针是否相等是未指定的行为吗?

c++ - 使用 OpenGL 的 C++ 代码中未解析的外部

c++ - ODB C++实例中sqlite数据库文件存放在哪里

opengl - 如何在 OpenGL 中使用多个视口(viewport)?

c++ - 编写一个函数来分配上三角矩阵

python - 使用稀疏矩阵与 numpy 数组

sql - 计算 postgresql 矩阵中列的组合

opengl - 纹素中心坐标处的textureGather()行为