Математика за вводом мыши в opengl и значениями рыскания / тангажа

Привет я пробовал некоторые c ++ opengl коды и сделал камеру. Я хотел дать сцене ввод мышью, чтобы осмотреться, поэтому я добавил этот код так же, как учебник здесь. https://learnopengl.com/Getting-started/Camera

Тем не менее, есть некоторые математические понятия, которые я не понимаю в отношении значений рыскания и тангажа. Вот функция обратного вызова движения мыши.

void mouse_callback(GLFWwindow* window, double xpos, double ypos) {
if (firstMouse) //preventing large jumps
{
lastX = xpos;
lastY = ypos;
firstMouse = false;
}

float xoffset = xpos - lastX;
float yoffset = lastY - ypos;
lastX = xpos;
lastY = ypos;

float sensitivity = 0.1f;
xoffset *= sensitivity;
yoffset *= sensitivity;

yaw += xoffset;
pitch += yoffset;

if (pitch > 89.0f)
pitch = 89.0f;
if (pitch < -89.0f)
pitch = -89.0f;

glm::vec3 front;
front.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
front.y = sin(glm::radians(pitch));
front.z = cos(glm::radians(pitch)) * sin(glm::radians(yaw));

//cameraFront is the direction vector of the camera. Where the camera is looking at
cameraFront = glm::normalize(front);
}

Вот глобальные переменные с их начальными значениями, которые используются в функции mouse_callback на всякий случай.

glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f);
glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
glm::mat4 view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);
//lookAt function requires position, target's position, up vector respectively.

Есть 2 вещи, которые я не понимаю. Как я понимаю, рыскание и тангаж рассчитываются по оси Y и оси X соответственно. И используя нашу правую руку и помещая большой палец в направлении оси +, направление, в котором изогнуты другие пальцы, является положительным направлением угла.

Теперь допустим, что я переместил мышь вправо, не изменяя yoffset. Затем в соответствии с функцией mouse_callback значение рыскания увеличивается, поскольку xoffset является положительным. Поскольку положительное направление оси y указывает на верхнюю часть окна, которое мы наблюдаем, увеличение рыскания означает, что вектор направления камеры должен поворачиваться влево, вправо? Но в программе камера поворачивается и показывает правую часть сцены. Я не понимаю, что происходит.

Если я знаю, что здесь происходит, я думаю, что могу понять, почему порядок вычисления для получения значения yoffset также отличается от получения значения xoffset.

Любая помощь будет принята с благодарностью. Скажите, если я ошибаюсь какие-либо математические концепции или что-то Заранее спасибо!

1

Решение

Поскольку положительное направление оси y указывает на верхнюю часть окна, которое мы наблюдаем, увеличение рыскания означает, что вектор направления камеры должен поворачиваться влево, вправо?

№ Направление y Ось здесь не имеет ничего общего. С уходом pitch в 0 формула задана равной:

front.x = cos(glm::radians(yaw))
front.y = 0
front.z = sin(glm::radians(yaw));

так что, если рыскание равно 0, вы в конечном итоге (1,0,0) (право). Если вы увеличите его до 90 градусов, вы получите (0,0,1), который указывает прямо на спину в правой системе координат, поэтому вы просто повернули направо.

Вы как-то связываете это с положительной ориентацией вращения, которая всегда поворачивается от z к x при вращении вокруг y. Но эти формулы не реализуют положительное вращение вокруг оси y на угол yaw, но они на самом деле вращаются на -yaw:
Поскольку система настроена так, чтобы давать + x под углом 0, мы можем рассматривать это как вращение вектора прямого направления v= (1,0,0) вокруг оси y, поэтому классическая матрица вращения даст:

      (  cos(yaw)      0     sin(yaw) )           ( cos(yaw) )
v' =  (     0          1        0     ) * v   =   (     0    )
(  -sin(yaw)     0     cos(yaw) )           (-sin(yaw) )

Однако, когда вы поворачиваете в отрицательном направлении вращения, вы получаете транспонированную матрицу, просто переворачивая знак минус для sin:

      (  cos(yaw)      0    -sin(yaw) )           ( cos(yaw) )
v' =  (     0          1        0     ) * v   =   (     0    )
(  sin(yaw)      0     cos(yaw) )           ( sin(yaw) )

Так что это просто

front = R_y ( -yaw) * (1,0,0)^T

Если вы посмотрите на полную формулу с pitch и вы заметите, что оно будет равно:

front = R_y(-yaw) * R_z(pitch) * (1,0,0)^T

который является просто вращением компаса, сначала вращающимся (1,0,0) вокруг оси z на угол pitch в положительном порядке, а затем вращая результат вокруг оси y на угол yaw в отрицательном порядке.

Я также думаю, что автор исходного кода, который вы цитируете, был либо а) спешащим, либо б) просто немного смущен тем, как здесь работает математика. Я говорю это по двум причинам:

  1. Направление по умолчанию задается как (0,0, -1), но углы Эйлера устанавливаются так, чтобы pitch=0, yaw=0 в результате (1,0,0) направление просмотра, по умолчанию yaw=-90, Можно было бы сформулировать это более понятным и интуитивно понятным способом, чтобы нулевые углы давали направление вперед по умолчанию.

  2. Использование lookAt здесь совершенно ненужно. Орто-нормализация, которую она будет выполнять внутри компании, — это просто трата вычислительной мощности (не большая по сегодняшним стандартам, но тем не менее). Использование (0,1,0) как восходящий вектор станет очень нестабильным вблизи полюсов, а ограничение pitch в [-89,89] это просто взлом, чтобы предотвратить это. На самом деле нет ничего плохого в том, что эта камера смотрит прямо вверх или вниз в этой навигационной модели (поскольку вы перемещаетесь только вдоль 2D-плоскости, прямое направление по-прежнему четко определяется yaw один, даже если смотреть прямо вверх или вниз). Блокировка карданного подвеса, вызванная этой ситуацией, также не имеет значения, поскольку третьего поворота просто не последовало.

    Действительно, гораздо проще просто создать матрицу вида непосредственно из двух углов поворота и положения камеры, и полностью избежать любых проблем вблизи или при полных 90 градусах.

1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector