2

I'm trying to create a 3D viewer for a parallax barrier display, but I'm stuck with camera movements. You can see a parallax barrier display at: displayblocks.org

Multiple views are needed for this effect, this tutorial provide code for calculating the interViewpointDistance depending of the display properties and so selecting the head Position.

Here are the parts of the code involved in the matrix creation:

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

The following code is the projection matrix function. I use the Robert Kooima's paper 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);
}

These two methods works, and I can see that my multiple views are well projected. But I cant manage to make a camera that works normally, like in a FPS, with Tilt and Pan. This code for example give me the "head tracking" effect (but with the mouse), it was handy to test projections, but this is not what I'm looking for.

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

My camera class works if viewmatrix is created with lookAt. But with the off-axis projection, using lookAt will rotate the scene, by which the correspondence between near plane and screen plane will be lost. I may need to translate/rotate the space corners coordinates Pa, Pb, Pc, used to create the frustum, but I don't know how.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Leon
  • 554
  • 4
  • 18
  • Could you clarify what behavior you want? Right now, you have a fixed window in 3D space, through which you look, no matter where your camera is. How do you want to incorporate rotations here? – Nico Schertler Feb 13 '19 at 05:01
  • If viewsCountX = 2 and viewsCountY = 0, I've got 2 points of view of the scene, like a VR headset, and I believe that code works for VR. Like with a VR headset, I want to be able to move and strafe. I also need the mouse to follow my look. Or, to use your analogy, as if I moved while holding the window in front of me. – Leon Feb 13 '19 at 15:05
  • For the mouse movement, I think I need to rotate the 4 points of the frustum about the view position point. For the front/back/left/right movements, I may need to translate all the frustum points, including the view position point, or maybe recreate the 4 frustum points from the view position and the apex distance from the frustum plan. – Leon Feb 13 '19 at 15:05
  • 1
    It might be easier to specify the off-axis projection directly then instead of sticking to the window metaphor. Essentially, you only need to know how much to shift left/right at the znear plane (and feed that to `glm::frustum`). The rest of it will be standard stuff. It is a bit hard to help without knowing the exact setup. You just need two projections for the left and right eye, where their center is located at the center of the screen, right? – Nico Schertler Feb 13 '19 at 19:25

0 Answers0