如何从视图投影矩阵中检索相机的原点/位置? (OpenGL)

时间:2019-12-30 17:53:16

标签: opengl matrix projection projection-matrix frustum

有什么方法可以从视图投影矩阵中检索相机的原点/位置吗? (OpenGL)

我正在尝试绘制相机的视锥,并且在计算平面的角时没有问题。

但是我不知道如何检索代表相机原点的点。

我希望通过乘以同质的剪辑空间坐标来检索此信息:

glm::vec4(0.f, 0.f, 0.f, 1.f)

但是我有点看起来像是倒置的相机位置。 (在屏幕快照中标记为 X )。包括以下所有源代码。

enter image description here

    // Homogeneous points for source cube in clip-space.
    std::array<glm::vec4, 9> corners =
    {
        // Far plane
        glm::vec4(-1.f,-1.f, 1.f, 1.f), // bottom-left
        glm::vec4( 1.f,-1.f, 1.f, 1.f), // bottom-right
        glm::vec4( 1.f, 1.f, 1.f, 1.f), // top-right
        glm::vec4(-1.f, 1.f, 1.f, 1.f), // top-left

        // Near plane
        glm::vec4(-1.f,-1.f,-1.f, 1.f), // bottom-left
        glm::vec4( 1.f,-1.f,-1.f, 1.f), // bottom-right
        glm::vec4( 1.f, 1.f,-1.f, 1.f), // top-right
        glm::vec4(-1.f, 1.f,-1.f, 1.f), // top-left

        // Camera/screen center position.
        glm::vec4(0.f, 0.f, 0.f, 1.f)
    };

    const auto invMatrix(glm::inverse(viewProjectionMatrix));

    for (U32 i = 0; i < corners.size(); i++)
    {
        corners[i] = invMatrix * corners[i]; // 4x4 * 4x1 matrix/vector multiplication.
        corners[i] /= corners[i].w; // Homogeneous to euclidean/cartesian conversion
    }

    // Far plane.
    this->AddLine(corners[0], corners[1], rColor);
    this->AddLine(corners[1], corners[2], rColor);
    this->AddLine(corners[2], corners[3], rColor);
    this->AddLine(corners[3], corners[0], rColor);

    // Near plane.
    this->AddLine(corners[4], corners[5], rColor);
    this->AddLine(corners[5], corners[6], rColor);
    this->AddLine(corners[6], corners[7], rColor);
    this->AddLine(corners[7], corners[4], rColor);

    // Connection from Near rectangle to the Far rectangle.
    this->AddLine(corners[0], corners[4], rColor);
    this->AddLine(corners[1], corners[5], rColor);
    this->AddLine(corners[2], corners[6], rColor);
    this->AddLine(corners[3], corners[7], rColor);

    // X
    this->AddLine(corners[4], corners[8], rColor);
    this->AddLine(corners[5], corners[8], rColor);
    this->AddLine(corners[6], corners[8], rColor);
    this->AddLine(corners[7], corners[8], rColor);

1 个答案:

答案 0 :(得分:3)

在一般情况下,如果只有一个合成的viewProjection矩阵,则无法从中推论出相机的原点。您将需要其他信息。

如果您知道自己的投影是正交的(或者实际上是任何类型的平行投影),那么就没有相机位置的有意义的概念,并且原点是您选择的一些(或多或少)任意点。要重建它,您将需要投影的参数将viewProjection分解为viewprojection。与完整构建proj相比,可能会有一些捷径,但这取决于您可能事先知道/可以假设的实际投影参数的属性。

对于透视投影,情况实际上是简单:投影中心将投影到无穷远的某个点,但是我们确切知道它的位置在均匀的剪辑空间中。对于典型的投影矩阵来说,它仅为proj * vec4(0,0,0,1),而这只是proj的最后一列。假设使用默认的GL约定,则类似于(0, 0, alpha, 0)。 alpha的绝对值无关紧要,因为无论如何这只是一个方向,仅符号就很重要。同样,假设使用默认的GL约定,则alpha实际为负,因此投影中心在剪辑空间中将转换为(0,0,-1,0)。因此,您可以简单地将计算取反,然后从剪辑空间回到世界空间:p_center = inverse(viewProj) * vec4(0,0,-1,0)。别忘了结果仍然是同质坐标,因此您将需要除以结果w以得到有意义的3D坐标。