Я пытаюсь создать 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
, используемые для создания усеченного конуса, но я не знаю, как.