我目前正在为我的项目开发我自己的 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 轴)。
请注意,转换矩阵通常如下所示:
( 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/