我在C ++中使用自己的类和数学函数,我犯了一个可怕的错误但却看不到它的位置。我代表一个带线性阵列的4x4矩阵,这是我的矩阵生成器函数:
float& Mat4x4::getRef(unsigned int row, unsigned int column)
{
return this->data[(4 * (column)) + row];
}
void Mat4x4::set(unsigned int row, unsigned int column, float value)
{
this->getRef(row, column) = value;
}
Mat4x4 Mat4x4::getRotationalXMatrix(Vec3 rot, bool oglform)
{
/*
| 1 0 0 0 |
M = | 0 cos(A) -sin(A) 0 |
| 0 sin(A) cos(A) 0 |
| 0 0 0 1 |
standard mathematical format -- opengl wants the transposed.
*/
Mat4x4 res = Mat4x4::identity();
res.set(1, 1, cos(rot.getX()));
res.set(2, 1, (-sin(rot.getX())));
res.set(1, 2, sin(rot.getX()));
res.set(2, 2, cos(rot.getX()));
return oglform ? res.transposed() : res;
}
Mat4x4 Mat4x4::getRotationalYMatrix(Vec3 rot, bool oglform)
{
/*
| cos(A) 0 sin(A) 0 |
M = | 0 1 0 0 |
| -sin(A) 0 cos(A) 0 |
| 0 0 0 1 |
standard mathematical format -- opengl wants the transposed.
*/
Mat4x4 res = Mat4x4::identity();
res.set(0, 0, cos(rot.getY()));
res.set(2, 0, sin(rot.getY()));
res.set(0, 2, -sin(rot.getY()));
res.set(2, 2, cos(rot.getY()));
return oglform ? res.transposed() : res;
}
Mat4x4 Mat4x4::getRotationalZMatrix(Vec3 rot, bool oglform)
{
/*
| cos(A) -sin(A) 0 0 |
M = | sin(A) cos(A) 0 0 |
| 0 0 1 0 |
| 0 0 0 1 |
standard mathematical format -- opengl wants the transposed.
*/
Mat4x4 res = Mat4x4::identity();
res.set(0, 0, cos(rot.getZ()));
res.set(1, 0, -sin(rot.getZ()));
res.set(0, 1, sin(rot.getZ()));
res.set(1, 1, cos(rot.getZ()));
return oglform ? res.transposed() : res;
}
Mat4x4 Mat4x4::getRotationalMatrix(Vec3 pos, bool oglform)
{
return getRotationalXMatrix(pos, oglform) * getRotationalYMatrix(pos, oglform) * getRotationalZMatrix(pos, oglform);
}
Mat4x4 Mat4x4::getTranslationMatrix(Vec3 pos, bool oglform)
{
Mat4x4 res = Mat4x4::identity();
res.set(3, 0, pos.getX());
res.set(3, 1, pos.getY());
res.set(3, 2, pos.getZ());
return oglform ? res.transposed() : res;
}
Mat4x4 Mat4x4::getScaleMatrix(Vec3 scale, bool oglform)
{
Mat4x4 res = Mat4x4::identity();
res.set(0, 0, scale.getX());
res.set(1, 1, scale.getY());
res.set(2, 2, scale.getZ());
return oglform ? res.transposed() : res;
}
Mat4x4 Mat4x4::lookatOGL(Vec3 eye, Vec3 centre, Vec3 up)
{
Vec3 zaxis = (centre - eye).normalised();
Vec3 xaxis = (up.cross(zaxis)).normalised();
Vec3 yaxis = zaxis.cross(xaxis);
float orient[16] = {0.0f};
orient[0] = xaxis.getX();
orient[1] = yaxis.getX();
orient[2] = zaxis.getX();
orient[3] = 0.0f;
orient[4] = xaxis.getY();
orient[5] = yaxis.getY();
orient[6] = zaxis.getY();
orient[7] = 0.0f;
orient[8] = xaxis.getZ();
orient[9] = yaxis.getZ();
orient[10] = zaxis.getZ();
orient[11] = 0.0f;
orient[12] = 0.0f; orient[13] = 0.0f; orient[14] = 0.0f; orient[15] = 1.0f;
Mat4x4 orientation(orient);
float trans[16] = {0.0f};
trans[0] = 1.0f;
trans[1] = 0.0f;
trans[2] = 0.0f;
trans[3] = 0.0f;
trans[4] = 0.0f;
trans[5] = 1.0f;
trans[6] = 0.0f;
trans[7] = 0.0f;
trans[8] = 0.0f;
trans[9] = 0.0f;
trans[10] = 1.0f;
trans[11] = 0.0f;
trans[12] = -eye.getX();
trans[13] = -eye.getY();
trans[14] = -eye.getZ();
trans[15] = 1.0f;
Mat4x4 translation(trans);
return (translation * orientation);
}
五个重要的OpenGL矩阵:
Mat4x4 Mat4x4::getModelMatrix(Vec3 pos, Vec3 rot, Vec3 scale, bool oglform)
{
return Mat4x4::getTranslationMatrix(pos, oglform) * Mat4x4::getRotationalMatrix(rot, oglform) * Mat4x4::getScaleMatrix(scale, oglform);
}
Mat4x4 Mat4x4::getViewMatrix(Vec3 eye, Vec3 centre, Vec3 up, bool oglform)
{
return Mat4x4::lookatOGL(eye, centre, up);
}
Mat4x4 Mat4x4::getProjectionMatrix(float fovRad, float aspectRatio, float near, float far, bool oglformat)
{
float tanHalfFOV = tan(fovRad / 2);
float data[16] = {0.0f};
Mat4x4 res(data);
res.set(0, 0, (1/(aspectRatio * tanHalfFOV)));
res.set(1, 1, (1/tanHalfFOV));
res.set(2, 3, -1);
float twotwo = -(far + near) / (far - near);
float threetwo = -(2 * far * near) / (far - near);
res.set(2, 2, twotwo);
res.set(3, 2, threetwo);
return res;
}
Mat4x4 Mat4x4::getMVMatrixOGL(Vec3 pos, Vec3 rot, Vec3 scale, Vec3 eye, Vec3 centre, Vec3 up)
{
Mat4x4 m = Mat4x4::getModelMatrix(pos, rot, scale, true);
Mat4x4 v = Mat4x4::getViewMatrix(eye, centre, up, true);
return v * m;
}
Mat4x4 Mat4x4::getMVPMatrixOGL(Vec3 pos, Vec3 rot, Vec3 scale, Vec3 eye, Vec3 centre, Vec3 up, float fovRad, float aspectRatio, float near, float far)
{
Mat4x4 m = Mat4x4::getModelMatrix(pos, rot, scale, true);
Mat4x4 v = Mat4x4::getViewMatrix(eye, centre, up, true);
Mat4x4 p = Mat4x4::getProjectionMatrix(fovRad, aspectRatio, near, far, true);
return p * v * m;
}
我看到了由此产生的矩阵的几个观察问题。当相机非常靠近模型时,它看起来相当正常,在正常情况下在y轴上旋转。然而,随着相机越来越远离模型,模型围绕y轴以圆形方式旋转,半径增加。此外,模型看起来在旋转的顶点看起来略微平坦,但这可能是由于视图矩阵的性质造成的?
这个观察是使用MV矩阵而不是投影矩阵。当我使用MVP矩阵时,事情变得更糟。该模型看起来几乎完全平坦,有些顶点与我的远剪辑一样长,通常为1000.0f。我的第一个想法是我有一些转置问题,但我知道我的转置功能正常工作。我的Mat4x4类本身是行专业,因为数学建议是正常的格式。 oglformat booleans转换为专业。我做错了什么?