坐标变换和投影的问题(Coordinate transformations and projecti

2019-10-21 20:21发布

我一直在尝试了一段时间,让我的鼠标坐标转换成三维空间坐标中的OpenGL场景。

目前,我的预测是一个烂摊子(我认为)的一点点,它似乎并没有充分考虑我的“相机”进去时,我周围的场景移动。 要检查这,我画一条线。

我调整大小功能:

    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())去如下:

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

并创建我的光芒:

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。

因此,要澄清:我试图将我的鼠标坐标转换成三维空间坐标。 到目前为止,似乎半的工作,它只是没有考虑到摄像头转动。 我证实,我的问题已经做的射线创作要么,或与坐标逆投影,而不是与我的实际射线采摘逻辑。

Answer 1:

这非常看起来像你被绊倒通过混合不同的功能组/水平。 您可以选择使用固定功能矩阵堆栈的某些方面。 例如,在绘图功能:

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();    
gluLookAt(cameraPosition.x(), cameraPosition.y(), cameraPosition.z(), camX, camY, 0, cameraUpDirection.x(), cameraUpDirection.y(), cameraUpDirection.z());

或在您未投影功能:

glGetDoublev(GL_MODELVIEW_MATRIX, modelViewMatrix);
glGetDoublev(GL_PROJECTION_MATRIX, projectionMatrix);

但在其他地方,你构建自己的矩阵,并将它们传递到着色器的制服:

vMatrix.lookAt(cameraPosition, QVector3D(camX, camY, 0), cameraUpDirection);
...
shaderProgram.setUniformValue("mvpMatrix", pMatrix * vMatrix * mMatrix);

这些是实现相同的功能的两种不同的方式。 但是,你不能只是随意混搭件他们。 如果你想保持干净的东西,可预测的,你应该选择一个,并坚持下去。 由于第一个是已被弃用旧功能,我建议你坚持建立自己的矩阵,并使用你的shader代码中定义的制服。

作为一个例子来说明为什么你当前的功能组合是失望配方:将您从固定功能矩阵堆栈与当前的投影矩阵glGetDoublev(GL_PROJECTION_MATRIX, ...) 但至少在这里的代码所示,你从来没有使用指定矩阵堆栈投影矩阵。 所以这只是想给你的身份矩阵。 至于OpenGL的而言, pMatrix你传递一个统一到您的着色器程序矩阵是完全无关的。

重写你的整个代码将是这个答案有点多,所以这里只是指针的关键部分:

  • 摆脱指矩阵堆栈的所有呼叫。 这包括像调用glMatrixMode() glLoadIdentity() gluLookAt()glGetDoublev()调用来获得当前的矩阵。
  • 使用您所有的渲染着色器(如果你没有的话),并确定你需要在你的GLSL代码制服所有矩阵。
  • 计算并自己管理矩阵,或者使用自己的代码,或广泛使用的矩阵/矢量的图书馆之一。
  • 通过这些矩阵作为制服的着色器。

现在,对于未投影,它看起来像你已经拥有你的模型,视图和投影矩阵( pMatrixvMatrixmMatrix )。 因此,有没有必要进行任何glGet*()调用从OpenGL的检索。 乘vMatrixmMatrix得到modelViewMatrix ,并使用pMatrix直接为你传递给投影矩阵gluUnProject()

严格地说,我也会考虑GLU弃用。 但是,如果你舒适的使用仍然gluUnProject()这可能是最简单的了。 否则,常用的矩阵库很可能有它的一个实现。 或者,如果你不害怕让你的手脏,这应该不难,如果你看一些规格/文档解释底层的计算来实现。



Answer 2:

在这里,我想我有一系列的问题。

  1. 我应该用-1我近平面,而不是0
  2. 我不同的数据类型为我的矩阵(QT的人而言,),使我不能直接将它们插入unproject功能。

我解决了这些通过执行以下操作:

  1. 我安装了GLM库规范化我的数据类型
  2. 我进行矩阵计算自己
    • 所以我把矩阵转换成我的创作射线的功能,然后通过逆模型矩阵相乘的逆视图矩阵,然后通过逆投影矩阵。
    • 该值随后将在屏幕的2个不同的矢量相乘坐标(其必须是在NDC空间)。 一个为-1 AZ,其他相应的窗口空间近及远的飞机+1的。 最后,那些载体还必须具有1的“W”的值,使得所得到的矩阵*矢量的计算可以通过其自身的最后点被划分。

我有一个系列的,因为我的射线的初始问题采摘导致我的代码揭示了一系列的错误在这里开幕的问题。 如果有人遇到张贴在这里的问题,它可能是值得一试我,我开了其他问题,从投影问题了我所有的问题都干:

  • 在这里 ,我才知道,其实我需要某种形式的计算,以便光线创作。
  • 在这里 ,我得知unProject是行不通的,因为我想拉使用OpenGL函数模型和视图矩阵,但我从来没有真正将它们摆在首位,因为我的手建造的矩阵。 我解决了这个问题在2倍:我手动做的数学,和我做了相同的数据类型的所有矩阵(它们是混合数据类型更早,导致问题为好)。
  • 最后,在这里 ,我才知道,我的操作顺序是稍微偏离(需由矢量,而不是相反乘矩阵),我的近平面需要是-1,不为0,而的最后一个值(值“W”),其需要将与矩阵相乘矢量为1。

由于我的问题延续了一段颇大篇幅,并采取了几个问题,我欠信贷少数几个人谁帮我一路上:

  • facepunch的srobins ,在这个线程
  • 从这里derhass , 在这个问题上 ,而这种讨论


文章来源: Coordinate transformations and projection issues