Реализуйте камеру с внеосевой проекцией - PullRequest
0 голосов
/ 11 февраля 2019

Я пытаюсь создать 3D-просмотрщик для дисплея с параллаксным барьером, но я застрял в движениях камеры.Вы можете увидеть отображение барьера параллакса по адресу: displayblocks.org

Для этого эффекта требуется несколько представлений, в этом руководстве предоставьте код для вычисления 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();
    }
}

Следующий код является функцией матрицы проекции.Я использую обобщенную перспективную проекцию Роберта Кооймы .

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

Эти два метода работают, и я вижу, что мои множественные виды хорошо проецируются.Но я не могу сделать камеру, которая работает нормально, как в FPS, с Tilt и Pan.Этот код, например, дает мне эффект «отслеживания головы» (но с помощью мыши), он был удобен для проверки проекций, но это не то, что я ищу.

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

Мой класс камеры работает, если viewmatrix создается с lookAt.Но в случае внеосевого проецирования использование lookAt будет вращать сцену, из-за которой соответствие между ближней плоскостью и плоскостью экрана будет потеряно.Возможно, мне потребуется перевести / повернуть координаты пространственных углов Pa, Pb, Pc, используемые для создания усеченного конуса, но я не знаю, как.

...