我在制作游戏的过程中在opengl中编写了一个小型2D引擎。我正在使用OpenGL ES 2,代码在iOS和Mac OSX上编译并运行。
现在我正在扩展它以支持3D,我在设置相机时遇到了问题 我已经检查了一百次代码并且我无法找到问题所在,所以也许有经验的人可以给出一个想法。
这是我的代码:我发布了我认为可能存在问题的部分代码,但如果需要其他东西,请问我。
Matrix4 _getFrustumMatrix(float left, float right, float bottom, float top, float near, float far){
Matrix4 res = Matrix4(2.0 * near / (right - left), 0, 0, 0,
0, 2.0 * near / (top - bottom), 0, 0,
(right + left) / (right - left), (top + bottom) / (top - bottom), -(far + near) / (far - near), -1.0,
0,0, -2.0 * far * near / (far - near), 0);
return res;
}
Matrix4 _getPerspectiveMatrix(float near, float far, float angleOfView){
static float aspectRatio = float(SCREENW)/float(SCREENH);
float top = near * tan(angleOfView * 3.1415927 / 360.0);
float bottom = -top;
float left = bottom * aspectRatio;
float right = top * aspectRatio;
return _getFrustumMatrix(left, right, bottom, top, near, far);
}
Matrix4 _getLookAtMatrix(Vector3 eye, Vector3 at, Vector3 up){
Vector3 forward, side;
forward = at - eye;
forward.normalize();
side = forward ^ up;
side.normalize();
up = side ^ forward;
Matrix4 res = Matrix4(side.x, up.x, -forward.x, 0,
side.y, up.y, -forward.y, 0,
side.z, up.z, -forward.z, 0,
0, 0, 0, 1);
res.translate(Vector3(0 - eye));
return res;
}
void Scene3D::_deepRender(){
cameraEye = Vector3(10,0,40);
cameraAt = Vector3(0,0,0);
cameraUp = Vector3(0,1,0);
MatrixStack::push();
Matrix4 projection = _getPerspectiveMatrix(1, 100, 45);
Matrix4 view = _getLookAtMatrix(cameraEye, cameraAt, cameraUp);
MatrixStack::set(projection * view);
Space3D::_deepRender();
MatrixStack::pop();
}
绘制的对象是轴的表示,其中x =红色,y =绿色,z =蓝色,它位于(0,0,0)。
如果我把眼睛放在(0,0,40),一切看起来都像预期的那样:
如果我把眼睛放在(10,0,40)处,那么物体不会在屏幕中间绘制,因为它应该是。
这是Matrix4 :: translate方法:
void Matrix4::translate(const Vector3& v) {
a14 += a11 * v.x + a12 * v.y + a13 * v.z;
a24 += a21 * v.x + a22 * v.y + a23 * v.z;
a34 += a31 * v.x + a32 * v.y + a33 * v.z;
a44 += a41 * v.x + a42 * v.y + a43 * v.z;
}
编辑:添加一些信息:
将_getLookAtMatrix()与此参数一起使用:
cameraEye = Vector3(40,40,40);
cameraAt = Vector3(0,0,0);
cameraUp = Vector3(0,1,0);
应该给我一个等效的矩阵吗?
Matrix4 view;
view.setIdentity();
view.translate(Vector3(0,0,-69.2820323)); // 69.2820323 is the length of Vector3(40,40,40)
view.rotate(45, Vector3(1,0,0));
view.rotate(-45, Vector3(0,1,0));
至少那些变换对我来说是有意义的,结果图像看起来像我期待的那样。 但是这个矩阵与我使用_getLookAtMatrix()的矩阵相比是非常不同的:
视图:
0.707106769, -0.49999997, 0.49999997, 0,
0, 0.707106769, 0.707106769, 0,
-0.707106769, -0.49999997, 0.49999997, 0,
0, 0, -69.2820358, 1
_getLookAtMatrix(cameraEye,cameraAt,cameraUp):
0.707106769, 0, -0.707106769, 0,
-0.408248276, 0.816496551, -0.408248276, 0,
0.577350259, 0.577350259, 0.577350259, 0,
-35.0483475, -55.7538719, 21.520195, 1
答案 0 :(得分:2)
你的矩阵类似乎有一些严重的排序不一致。
例如,我假设您的Matrix4
构造函数将其参数(矩阵元素)作为列专用,否则您的函数将与glFrustum
和gluLookAt
的参考实现不匹配,你会得到完全搞砸的结果。
您的translate
函数的代码看起来也正确,因为它必须修改矩阵的最后一列,即元素(a14
,a24
,{{1 }和a34
)。
但是,您打印出的a44
矩阵表明view
实际上修改了最后一行,除非您以列主格式打印矩阵并因此进行转置。但在这种情况下,_ translate
的打印表明getLookAtMatrix
构造函数以行主顺序获取其参数,这确实使其他事物无效。
当然所有这些还取决于你如何将矩阵发送到OpenGL以及如何在顶点着色器中使用它们(我假设ES 2.0,否则就不需要你自己的矩阵库)。如果你确实使用ES 1,那么你需要按列主要顺序将矩阵元素发送到OpenGL,但是翻译必须在最后一列而不是最后一行。
但无论您使用什么约定,矩阵代码中肯定存在严重的不一致。但是没有看到整个Matrix4
类,顶点着色器和将矩阵上传到OpenGL的代码,很难说这种不一致的地方。