Coordinate transformations and projection issues
我已经尝试了一段时间让我的鼠标坐标转换成OpenGL场景中的三维空间坐标。
目前,我的投影有点混乱(我认为),而且当我在一个场景中移动时,它似乎没有完全考虑到我的"相机"。为了检查这个,我画了一条线。
我的调整大小功能:
1 2 3 4 5 6 7 8 9 | void oglWidget::resizeGL(int width, int height) { if (height == 0) { height = 1; } pMatrix.setToIdentity(); pMatrix.perspective(fov, (float) width / (float) height, -1, 1); glViewport(0, 0, width, height); } |
我的渲染函数(paintgl())如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); QMatrix4x4 mMatrix; QMatrix4x4 vMatrix; QMatrix4x4 cameraTransformation; cameraTransformation.rotate(alpha, 0, 1, 0); cameraTransformation.rotate(beta, 1, 0, 0); QVector3D cameraPosition = cameraTransformation * QVector3D(camX, camY, distance); QVector3D cameraUpDirection = cameraTransformation * QVector3D(0, 1, 0); vMatrix.lookAt(cameraPosition, QVector3D(camX, camY, 0), cameraUpDirection); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(cameraPosition.x(), cameraPosition.y(), cameraPosition.z(), camX, camY, 0, cameraUpDirection.x(), cameraUpDirection.y(), cameraUpDirection.z()); shaderProgram.bind(); shaderProgram.setUniformValue("mvpMatrix", pMatrix * vMatrix * mMatrix); shaderProgram.setUniformValue("texture", 0); for (int x = 0; x < tileCount; x++) { shaderProgram.setAttributeArray("vertex", tiles[x]->vertices.constData()); shaderProgram.enableAttributeArray("vertex"); shaderProgram.setAttributeArray("textureCoordinate", textureCoordinates.constData()); shaderProgram.enableAttributeArray("textureCoordinate"); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, tiles[x]->image.width(), tiles[x]->image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tiles[x]->image.bits()); glDrawArrays(GL_TRIANGLES, 0, tiles[x]->vertices.size()); } shaderProgram.release(); |
创建我的光线:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | GLdouble modelViewMatrix[16]; GLdouble projectionMatrix[16]; GLint viewport[4]; GLfloat winX, winY, winZ; glGetDoublev(GL_MODELVIEW_MATRIX, modelViewMatrix); glGetDoublev(GL_PROJECTION_MATRIX, projectionMatrix); glGetIntegerv(GL_VIEWPORT, viewport); winX = (float)x; winY = (float)viewport[3] - (float)y; glReadPixels( winX, winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ ); GLdouble nearPlaneLocation[3]; gluUnProject(winX, winY, 0, modelViewMatrix, projectionMatrix, viewport, &nearPlaneLocation[0], &nearPlaneLocation[1], &nearPlaneLocation[2]); GLdouble farPlaneLocation[3]; gluUnProject(winX, winY, 1, modelViewMatrix, projectionMatrix, viewport, &farPlaneLocation[0], &farPlaneLocation[1], &farPlaneLocation[2]); QVector3D nearP = QVector3D(nearPlaneLocation[0], nearPlaneLocation[1], nearPlaneLocation[2]); QVector3D farP = QVector3D(farPlaneLocation[0], farPlaneLocation[1], farPlaneLocation[2]); |
我觉得我在使用相互冲突的系统或其他东西。
我应该使用不同的变量来管理我的相机吗?我看到了关于投影视图、模型视图等的讨论,但我不知道如何使用它,也不知道如何使用着色程序。说到OpenGL,我还是个新手。
所以要澄清:我正在尝试将鼠标坐标转换为三维空间坐标。到目前为止,它似乎是半工作的,只是不考虑摄像机的旋转。我确认了我的问题与光线的创建或坐标的取消投影有关,而与实际光线选择逻辑无关。
它非常像你被混合不同的功能组/级别绊倒了。使用固定函数矩阵堆栈有一些方面。例如,在绘图功能中:
1 2 3 | glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(cameraPosition.x(), cameraPosition.y(), cameraPosition.z(), camX, camY, 0, cameraUpDirection.x(), cameraUpDirection.y(), cameraUpDirection.z()); |
或者在你的非投影函数中:
1 2 | glGetDoublev(GL_MODELVIEW_MATRIX, modelViewMatrix); glGetDoublev(GL_PROJECTION_MATRIX, projectionMatrix); |
但在其他地方,你正在构建自己的矩阵,并将它们作为制服传递到材质球中:
1 2 3 | vMatrix.lookAt(cameraPosition, QVector3D(camX, camY, 0), cameraUpDirection); ... shaderProgram.setUniformValue("mvpMatrix", pMatrix * vMatrix * mMatrix); |
这是实现相同功能的两种不同方法。但是你不能随意地混合和匹配它们。如果你想保持事情的干净和可预测性,你应该选择一个,并坚持下去。由于第一个功能是过时的遗留功能,我建议您继续构建自己的矩阵,并使用在您的明暗器代码中定义的制服。
举个例子来说明为什么您当前的功能组合会让人失望:您将从带有
对于这个答案来说,重写整个代码有点困难,所以这里只是关键部分的指针:
- 去掉所有引用矩阵堆栈的调用。这包括诸如
glMatrixMode() 、glLoadIdentity() 、gluLookAt() 和glGetDoublev() 等调用以获取当前矩阵。 - 在所有渲染中使用着色器(如果还没有),并在glsl代码中将所需的所有矩阵定义为制服。
- 自己计算和管理矩阵,可以使用自己的代码,也可以使用广泛使用的矩阵/向量库之一。
- 将这些矩阵作为统一格式传递给着色器。
现在,对于非投影,您似乎已经拥有了模型、视图和投影矩阵(
严格地说,我也会认为格鲁不赞成。但是,如果您仍然可以轻松使用
在这里,我想我遇到了一系列的问题。
我通过以下步骤解决了这些问题:
- 所以我把这些矩阵拉到光线创建函数中,然后将逆视图矩阵乘以逆模型矩阵,再乘以逆投影矩阵。
- 然后将该值乘以屏幕坐标的两个不同向量(必须在ndc空间中)。一个Z为-1,另一个Z为+1,对应于窗空间的近平面和远平面。最后,这些向量还必须有一个"w"值1,这样矩阵*向量的计算结果就可以除以它自身的最后一个点。
我在这里打开了一系列的问题,因为我最初的光线选择问题导致代码中出现了一系列错误。如果有人遇到了这里发布的问题,那么可能值得检查我打开的其他问题,因为我所有的问题都源于投影问题:
- 在这里,我了解到我实际上需要某种形式的计算才能创建光线。
- 在这里,我了解到unproject不起作用,因为我试图使用OpenGL函数提取模型和视图矩阵,但实际上我从未在第一个地方设置它们,因为我手工构建了矩阵。我用两种方法解决了这个问题:我手工计算,并制作了相同数据类型的所有矩阵(之前它们是混合数据类型,也导致了问题)。
- 最后,在这里,我了解到我的操作顺序稍微有点偏离(需要用一个向量来乘以矩阵,而不是相反),我的近平面需要是-1,而不是0,向量的最后一个值将与矩阵相乘(值"w")需要是1。
由于我的问题持续了相当长的时间,并且回答了几个问题,我要归功于在这一过程中帮助过我的几个人:
- 在这条线中,脸上的皱纹
- 德哈斯从这里,在这个问题和这个讨论中