OpenGL, перевод камеры от первого лица

Мне было интересно, как я могу заставить свою камеру FPS двигаться вперед и назад в зависимости от направления камеры, но я с треском провалился, я хотел бы знать, как сделать это оптимально, так как сейчас мой код переключается направления позади моего треугольника (w становится s, а s становится w) и обычно не работают (двигайтесь по диагонали вместо иногда вперед), вращение работает отлично, но перевод портит мою матрицу...

void glfwCursorCallback(GLFWwindow* window, double x, double y) {
    camera.rx += (x - camera.lcx) * 0.01f;
    camera.ry += (y - camera.lcy) * 0.01f;
    kmMat4RotationYawPitchRoll(&camera.mat, camera.ry , camera.rx, 0.0f);
    camera.lcx = x;
    camera.lcy = y;
}
...
kmMat4PerspectiveProjection(&projection, 90.0f, aspect, 0.1f, 1000.f);
float x = 0.0f, y = 0.0f, z = -1.0f;
while(!glfwWindowShouldClose(window)) {
    if(glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
        /* pitch - ry */
        x += 0.1*sin(camera.ry)*cos(camera.rx);
        y += 0.1*sin(camera.ry)*sin(camera.rx);
        z += 0.1*cos(camera.ry);
    }
    if(glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
        x -= 0.1*sin(camera.ry)*cos(camera.rx);
        y -= 0.1*sin(camera.ry)*sin(camera.rx);
        z -= 0.1*cos(camera.ry);
    }

    glClear(GL_COLOR_BUFFER_BIT);
    kmMat4Translation(&transform, x, y, z);
    kmMat4Multiply(&object, &camera.mat, &transform);
    kmMat4Multiply(&final, &projection, &object);
    glUniformMatrix4fv(shader.mpm, 1, GL_FALSE, final.mat);
    ...

Я понятия не имею, как это сделать, так как никогда не делал этого раньше, поэтому мне бы хотелось получить несколько советов от более опытных людей!

Редактировать: цель состоит в том, чтобы камера двигалась вперед в соответствии с ориентацией. Кроме того, он отлично работает, если я опускаю x, y и просто устанавливаю z на +- 0,1 ... так что это не проблема умножения матриц.


person Whiteclaws    schedule 01.10.2017    source источник


Ответы (1)


В то время как в мире ось X указывает вправо, ось Y — вперед, а ось Z — вверх, в окне просмотра ось X указывает влево, ось Y — вверх, а ось Z — вверх. Ось Z вне поля зрения (Обратите внимание, что в правосторонней системе ось Z является перекрестным произведением оси X и оси Y).

мир для просмотра

Поэтому каждая точка и каждый вектор из системы отсчета сцены должны быть сначала преобразованы в координаты области просмотра. Это можно легко обработать с помощью следующей таблицы:

 x  y  z
--------
 1  0  0  | x' =  x
 0  0  1  | y' =  z
 0 -1  0  | z' = -y


Дальше надо пошагово менять матрицу камеры и не суммировать движения и повороты. Это означает, что вы должны рассчитать текущее движение и текущую матрицу вращения. Примените движение и вращение к камере и оставьте камеру для следующего цикла цикла. В следующем цикле цикла вы должны использовать управляемую камеру из предыдущего цикла и применить новое движение и вращение. Это приводит к постепенному изменению камеры, всегда основанному на ее текущем положении и ориентации.

движение и вращение


Ваш код должен выглядеть примерно так:

double currenYaw    = 0.0;
double currentPitch = 0.0;
double currentX     = 0.0;
double currentY     = 0.0;

void glfwCursorCallback( GLFWwindow* window, double x, double y )
{
    currenYaw    += (x - currentX) * 0.01;
    currentPitch += (currentY - y) * 0.01;
    currentX      = x;
    currentY      = y;
}

glfwGetCursorPos( _wnd, &currentX, &currentY );
while(!glfwWindowShouldClose(window)) {

    float x = 0.0f, y = 0.0f, z = 0.0f;
    if ( glfwGetKey(_wnd, GLFW_KEY_W) == GLFW_PRESS )
        y = 0.1f;
    if ( glfwGetKey(_wnd, GLFW_KEY_S) == GLFW_PRESS ) {
        y = -0.1f;
    if ( glfwGetKey(_wnd, GLFW_KEY_D) == GLFW_PRESS )
        x = 0.1f;
    if ( glfwGetKey(_wnd, GLFW_KEY_A) == GLFW_PRESS ) {
        x = -0.1f;
    if ( glfwGetKey(_wnd, GLFW_KEY_Q) == GLFW_PRESS )
        z = -0.1f;
    if ( glfwGetKey(_wnd, GLFW_KEY_E) == GLFW_PRESS ) {
        z = 0.1f;

    // movment
    kmMat4 yaw_matrix; 
    kmMat4Translation( &transform, x, z, -y );

    // yaw
    kmMat4 yaw_matrix;
    kmMat4RotationY( &yaw_matrix, currenYaw );
    currenYaw = 0.0;

    // pitch
    kmMat4 pitch_matrix;
    kmMat4RotationX( &pitch_matrix, currentPitch );
    currentPitch = 0.0;

    // roatation = pitch_matrix * yaw_matrix
    kmMat4 roatation;
    kmMat4Multiply( &roatation, &yaw_matrix, &yaw_matrix );

    // change the camera matrix incrementally
    kmMat4Multiply( &camera.mat, &transform, &camera.mat );
    kmMat4Multiply( &camera.mat, &roatation, &camera.mat );

    ....
}


Seet further:

person Rabbid76    schedule 01.10.2017
comment
Я хотел бы переместиться к камере и сохранить это значение для дальнейшего времени (x, y, z). Я не просто хочу двигаться на фиксированную величину по оси, я уже делаю это хорошо - person Whiteclaws; 01.10.2017
comment
Ваше решение делает треугольник центром мира и камерой, вращающейся вокруг него, так что это не совсем то, что я ищу, я ищу камеру FP - person Whiteclaws; 01.10.2017