实施带有偏轴投影的相机

时间:2019-02-11 17:56:10

标签: c++ opengl camera glm-math frustum

我正在尝试为视差栅栏显示创建3D查看器,但是我对摄像机的运动感到困惑。您可以在以下位置看到视差栅栏显示:displayblocks.org

此效果需要多个视图,this tutorial提供了根据显示属性计算interViewpointDistance的代码,因此选择了头位置。

以下是矩阵创建中涉及的代码部分:

for (y = 0; y < viewsCountY; y++) {
    for (x = 0; x <= viewsCountX; x++) {
        viewMatrix = glm::mat4(1.0f);
        // selection of the head Position
        float cameraX = (float(x - int(viewsCountX / 2))) * interViewpointDistance;
        float cameraY = (float(y - int(mviewsCountY / 2))) * interViewpointDistance;

        camera.Position = glm::vec3(camera.Position.x + cameraX, camera.Position.y + cameraY, camera.Position.z);

        // Move the apex of the frustum to the origin.
        viewMatrix = glm::translate(viewMatrix -camera.Position);

        projectionMatrix = get_off_Axis_Projection_Matrix();

        // render's stuff
        // (...) 
        // glfwSwapBuffers();
    }
}

以下代码是投影矩阵函数。我使用罗伯特·库伊玛(Robert Kooima)的论文generalized perspective projection

glm::mat4 get_off_Axis_Projection_Matrix() {
    glm::vec3 Pe = camera.Position;

    // space corners coordinates (space points)
    glm::vec3 Pa = glm::vec3(screenSizeX, -screenSizeY, 0.0);
    glm::vec3 Pb = glm::vec3(screenSizeX, -screenSizeY, 0.0);
    glm::vec3 Pc = glm::vec3(screenSizeX, screenSizeY, 0.0);

    // Compute an orthonormal basis for the screen.
    glm::vec3 Vr = Pb - Pa;
    Vr = glm::normalize(Vr);

    glm::vec3 Vu = Pc - Pa;
    Vu = glm::normalize(Vu);

    glm::vec3 Vn = glm::cross(Vr, Vu);
    Vn = glm::normalize(Vn);

    // Compute the screen corner vectors.
    glm::vec3 Va = Pa - Pe;
    glm::vec3 Vb = Pb - Pe;
    glm::vec3 Vc = Pc - Pe;
    //-- Find the distance from the eye to screen plane.
    float d = -glm::dot(Va, Vn);

    // Find the extent of the perpendicular projection.
    float left = glm::dot(Va, Vr) * const_near / d;
    float right = glm::dot(Vr, Vb) * const_near / d;
    float bottom = glm::dot(Vu, Va) * const_near / d;
    float top = glm::dot(Vu, Vc) * const_near / d;

    // Load the perpendicular projection.
    return glm::frustum(left, right, bottom, top, const_near, const_far + d);
}

这两种方法都有效,而且我可以看到我的多个视图投影良好。 但是我无法使用Tilt和Pan来制作像FPS一样正常工作的相机。 例如,这段代码为我提供了“头部跟踪”效果(但使用鼠标),可以方便地测试投影,但这不是我想要的。

float cameraX = (mouseX - windowWidth / 2) / (windowWidth * headDisplacementFactor);
float cameraY = (mouseY - windowHeight / 2) / (windowHeight * headDisplacementFactor);
camera.Position = glm::vec3(cameraX, cameraY, 60.0f);
viewMatrix = glm::translate(viewMatrix, -camera.Position);

如果使用lookAt创建了viewmatrix,我的相机类将起作用。但是使用离轴投影时,使用lookAt将旋转场景,通过该场景将丢失近平面和屏幕平面之间的对应关系。 我可能需要平移/旋转用于创建视锥的空间角坐标PaPbPc,但我不知道如何。

0 个答案:

没有答案