Невозможно указать ни одну строку для изменения, но есть предложения:
, когда происходит первый поворот, камера внезапно прыгает
Это признак того, что что-то не инициализируется к тому, что вы думаете. В этом случае тангаж и рыскание являются производными значениями, которые можно рассчитать по прямому вектору, верно? Когда вы получили производные значения, вы никогда не должны инициализировать их напрямую, потому что есть вероятность, что вы ошибетесь. Если два значения, которые должны быть «одинаковыми», различны, произойдут странные вещи. Вместо этого инициализируйте прямой вектор и сразу рассчитайте его высоту и рыскание.
И cos (sin (y)) не должно быть 0
Мы все делаем эту ошибку из время от времени. Но в этом случае я не думаю, что это имеет значение по причинам позже.
Тем не менее, вы можете проверить, что происходит, когда передний вектор равен (0, 0, 0). Удивительно, что в графическом программировании как-то получается получить нулевой вектор.
float yaw = glm :: градусов (glm :: acos ((float) x / glm :: cos (glm :: asin) (у))));
Решили ли вы, какое представление угла Эйлера вы используете? В простом случае вам никогда не нужно использовать более одного значения координаты одной оси для вычисления угла, но здесь вы используете два.
Простой случай, когда рыскание (курс), наклон и крен независимы углы, так что рыскание не меняется, если высота тона меняется, и наоборот. Ваш последний кодовый блок с векторами xUnit и yUnit, кажется, делает это.
Однако в авиасимуляторах и в аэрокосмических расчетах рывок-тангаж немного сложнее, потому что они не независимы. Угол поворота может быть измерен в плоскости тангажа, а не в абсолютном XZ. А аэрокосмический рывок часто измеряется с «севера» оси Z, а не X. Таким образом, вы должны четко понимать, какой тип рыскания и тангажа вы измеряете, и быть последовательными во всем. И вам нужно изучить любые учебные примеры или код, чтобы выяснить, как они используют тональность и тональность, и соответствует ли она вашим.
Я предлагаю сейчас придерживаться простых однокоординатных мер.
float pitch = glm :: градусов (glm :: acos (glm :: dot (forward, yUnit)));
Опять же, вы уверены, что форвард нормализован? LookAt обычно закодирован, чтобы быть более прощающим, чем математические библиотеки, поэтому легко ошибиться.
И вы проверили, что ваша математическая библиотека имеет значения за пределами от -180 до 180 градусов? Еще одна вещь, о которой стоит беспокоиться.
Надеюсь, это поможет. Если вы находите углы Эйлера беспокойными и раздражающими, вы не одиноки! Вот почему многие книги и учебники по 3D рекомендуют изучать кватернионы.