为什么QMatrix4x4::lookAt()会导致相机颠倒

时间:2021-12-08 05:00:33

I have a got a simple OpenGL program which sets up the camera as follows :

我有一个简单的OpenGL程序,设置摄像头如下:

void
SimRenderer::render() {
glDepthMask(true);

glClearColor(0.5f, 0.5f, 0.7f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

glFrontFace(GL_CW);
glCullFace(GL_FRONT);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);

QMatrix4x4 mMatrix;
QMatrix4x4 vMatrix;

QMatrix4x4 cameraTransformation;
cameraTransformation.rotate(mAlpha, 0, 1, 0); // mAlpha = 25
cameraTransformation.rotate(mBeta, 1, 0, 0);  // mBeta = 25

QVector3D cameraPosition = cameraTransformation * QVector3D(0, 0, mDistance);
QVector3D cameraUpDirection = cameraTransformation * QVector3D(0, 1, 0);

vMatrix.lookAt(cameraPosition, QVector3D(0, 0, 0), cameraUpDirection);

mProgram.bind();
mProgram.setUniformValue(mMatrixUniformLoc, mProjMatrix *  vMatrix * mMatrix );

// render a grid....
}

But the result is an upside down camera !!

但结果是一个颠倒的相机!

为什么QMatrix4x4::lookAt()会导致相机颠倒!1

1 !

When I change the view matrix to be set up as: QVector3D cameraUpDirection = cameraTransformation * QVector3D(0, -1, 0);

将视图矩阵设置为:QVector3D cameraUpDirection = cameraTransformation * QVector3D(0,1, 0);

It works ! But why should I need to set my up direction as negative Y when my real up direction is positive Y ?

它的工作原理!但是为什么我要把向上的方向设为- Y呢?

Complete class here : https://code.google.com/p/rapid-concepts/source/browse/trunk/simviewer/simrenderer.cpp

完整的类:https://code.google.com/p/rapid-concepts/source/browse/trunk/simviewer/simrenderer.cpp

Other info: I am rendering to a QQuickFramebufferObject which binds a FBO to a widgets surface before calling the rendering function. Dont think that would be an issue but anyway. And this is not a texturing issue at all, there arent any textures to be flipped etc. Seems the camera is interpreting the up direction in the opposite way !!

其他信息:我正在渲染一个QQuickFramebufferObject,它在调用呈现函数之前将FBO绑定到一个小部件表面。别以为那是个问题,但无论如何。而且这根本不是一个纹理问题,没有任何纹理可以翻转等等。看起来相机正在用相反的方式解释向上的方向!

http://doc.qt.digia.com/qt-maemo/qmatrix4x4.html#lookAt

http://doc.qt.digia.com/qt-maemo/qmatrix4x4.html之外


Update :

更新:

So since using lookat and cameraTransformations both together may not work I am trying :

因此,既然同时使用lookat和cameratransformation可能不会奏效,我正在尝试:

QMatrix4x4 mMatrix;
QMatrix4x4 vMatrix;

QMatrix4x4 cameraTransformation;
cameraTransformation.rotate(mAlpha, 0, 1, 0); // 25
cameraTransformation.rotate(mBeta, 1, 0, 0);  // 25

cameraTransformation.translate(0, 0, mDistance);  

vMatrix = cameraTransformation.inverted();

That produces exactly the same result :)

产生完全相同的结果:

I think the camera up axis needs to be accounted for in some way.

我认为相机上升轴需要在某种程度上解释。

2 个解决方案

#1


2  

It is actually not the camera that upside down but the texture was rendered to QML surface upside down. That is really confusing because you do get the correct direction (Y up) if you are using widget based stacks (QOpenGLWidget) or simply QOpenGLWindow.

其实倒着的不是相机,而是画质被倒过来呈现给QML的表面。这确实令人困惑,因为如果您使用基于小部件的栈(QOpenGLWidget)或简单的QOpenGLWindow,那么您确实得到了正确的方向(Y向上)。

Basically the same as this question. some explanation can be found on the forum or in the bug tracker.

基本上和这个问题一样。可以在论坛或bug跟踪器中找到一些解释。

I think the best solution is the one in bug tracker which requires no additional transformation on either the QML item or in matrix: overriding updatePaintNode to setTextureCoordinatesTransform to vertically mirrored.

我认为最好的解决方案是bug tracker,它不需要对QML项或matrix:覆盖updatePaintNode到setTextureCoordinatesTransform以垂直镜像。

QSGNode *MyQQuickFramebufferObject::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNodeData *nodeData)
{
    if (!node) {
        node = QQuickFramebufferObject::updatePaintNode(node, nodeData);
        QSGSimpleTextureNode *n = static_cast<QSGSimpleTextureNode *>(node);
        if (n)
            n->setTextureCoordinatesTransform(QSGSimpleTextureNode::MirrorVertically);
        return node;
    }
    return QQuickFramebufferObject::updatePaintNode(node, nodeData);
}

#2


1  

Typically this effect is caused by one of several things.

通常,这种影响是由以下几个因素之一引起的。

  • Mixing up radians and degrees
  • 混合弧度和角度
  • Forgetting to set the modelview matrix to the inverse of the camera transform
  • 忘记将modelview矩阵设置为相机变换的逆
  • Screwing up the inputs to lookat
  • 把输入弄得一团糟

I suspect the issue with this is the last.

我怀疑这是最后一个问题。

QVector3D cameraUpDirection = cameraTransformation * QVector3D(0, 1, 0);

Why are you multiplying the up vector by this transformation? I can understand multiplying the distance, so that the camera position is transformed, rotating the up axis sent to a lookat function will result in weirdness I suspect.

为什么要把上向量乘以这个变换?我可以理解乘上距离,这样摄像机的位置就会改变,旋转上轴发送到lookat函数会导致奇怪的结果。

Generally, doing transforms using a camera matrix AND using lookat is a little odd. If you already have a camera matrix with the proper rotation, you can just translate that matrix by the distance required, expressed as a Z vector of the appropriate length, probably QVector3D(0, 0, mDistance), and then setting the view matrix to the inverse of the camera matrix:

一般来说,使用相机矩阵进行变换和使用lookat有点奇怪。如果你已经有了一个具有适当旋转的相机矩阵,你可以把这个矩阵转换成所需的距离,用合适长度的Z向量表示,可能是QVector3D(0,mdistance),然后将视图矩阵设置为相机矩阵的逆:

vMatrix = cameraTransformation.inverted();

#1


2  

It is actually not the camera that upside down but the texture was rendered to QML surface upside down. That is really confusing because you do get the correct direction (Y up) if you are using widget based stacks (QOpenGLWidget) or simply QOpenGLWindow.

其实倒着的不是相机,而是画质被倒过来呈现给QML的表面。这确实令人困惑,因为如果您使用基于小部件的栈(QOpenGLWidget)或简单的QOpenGLWindow,那么您确实得到了正确的方向(Y向上)。

Basically the same as this question. some explanation can be found on the forum or in the bug tracker.

基本上和这个问题一样。可以在论坛或bug跟踪器中找到一些解释。

I think the best solution is the one in bug tracker which requires no additional transformation on either the QML item or in matrix: overriding updatePaintNode to setTextureCoordinatesTransform to vertically mirrored.

我认为最好的解决方案是bug tracker,它不需要对QML项或matrix:覆盖updatePaintNode到setTextureCoordinatesTransform以垂直镜像。

QSGNode *MyQQuickFramebufferObject::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNodeData *nodeData)
{
    if (!node) {
        node = QQuickFramebufferObject::updatePaintNode(node, nodeData);
        QSGSimpleTextureNode *n = static_cast<QSGSimpleTextureNode *>(node);
        if (n)
            n->setTextureCoordinatesTransform(QSGSimpleTextureNode::MirrorVertically);
        return node;
    }
    return QQuickFramebufferObject::updatePaintNode(node, nodeData);
}

#2


1  

Typically this effect is caused by one of several things.

通常,这种影响是由以下几个因素之一引起的。

  • Mixing up radians and degrees
  • 混合弧度和角度
  • Forgetting to set the modelview matrix to the inverse of the camera transform
  • 忘记将modelview矩阵设置为相机变换的逆
  • Screwing up the inputs to lookat
  • 把输入弄得一团糟

I suspect the issue with this is the last.

我怀疑这是最后一个问题。

QVector3D cameraUpDirection = cameraTransformation * QVector3D(0, 1, 0);

Why are you multiplying the up vector by this transformation? I can understand multiplying the distance, so that the camera position is transformed, rotating the up axis sent to a lookat function will result in weirdness I suspect.

为什么要把上向量乘以这个变换?我可以理解乘上距离,这样摄像机的位置就会改变,旋转上轴发送到lookat函数会导致奇怪的结果。

Generally, doing transforms using a camera matrix AND using lookat is a little odd. If you already have a camera matrix with the proper rotation, you can just translate that matrix by the distance required, expressed as a Z vector of the appropriate length, probably QVector3D(0, 0, mDistance), and then setting the view matrix to the inverse of the camera matrix:

一般来说,使用相机矩阵进行变换和使用lookat有点奇怪。如果你已经有了一个具有适当旋转的相机矩阵,你可以把这个矩阵转换成所需的距离,用合适长度的Z向量表示,可能是QVector3D(0,mdistance),然后将视图矩阵设置为相机矩阵的逆:

vMatrix = cameraTransformation.inverted();