c++ - 如何从 View 投影矩阵检索相机原点/位置? (OpenGL)

标签 c++ opengl glm-math projection-matrix frustum

有什么方法可以从 View 投影矩阵中检索相机原点/位置吗? (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) // EDIT
        glm::vec4(0.f, 0.f,-1.f, 0.f) // SOLVED
    };

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

[已解决]

问题是我需要使用 glm::vec4(0.f, 0.f,-1.f, 0.f) 而不是 glm::vec4( 0.f、0.f、0.f、1.f)

以下是所需的结果:enter image description here

最佳答案

一般情况下,如果您只有一个组合的 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 坐标。

关于c++ - 如何从 View 投影矩阵检索相机原点/位置? (OpenGL),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59534879/

相关文章:

c++ - VTK:可视化深度缓冲区

c++ - 将vec3与模型矩阵相乘的问题(缩放问题)

c++ - 旋转实现错误

c++ - 为什么我不能将数组值返回给主函数?

python - 使用 Cython 包装返回 MPI 通信器的 C++ 函数

image - OpenGL 与 GLUT——malloc 错误

c++ - OpenGL - glm 转换和比例合成

c++ - 在不截断的情况下撤消类次

c++ - 使用调试文件构建 C++ 项目

android - 将 OpenGL glBegin() 移植到 OpenGL ES