Я работаю над симулятором движения с 2 степенями свободы (pitch & roll). Я читаю матрицу преобразования из игры, и мне нужно получить углы и отправить на оборудование для управления двигателями. Поскольку у углов Эйлера есть особенности, я не могу их использовать. Он ведет себя так:
когда это должно понравиться:
Я подготовил онлайн-пример, чтобы лучше показать проблему:
// Get euler angles from model matrix
var mat = model.matrix;
mat.transpose();
var e = new THREE.Euler();
e.setFromRotationMatrix(mat, 'XZY');
var v = e.toVector3();
var pitch = -v.z;
var roll = -v.x;
http://jsfiddle.net/qajro0ny/3/
Насколько я понимаю, здесь есть две проблемы.
- На тренажере отсутствует ось рыскания.
- Даже если бы была ось рыскания, двигатели просто не ведут себя как компьютерная графика, т.е. им нужно время, чтобы добраться до целевой позиции.
Я читал о блокировке кардана и даже реализовал фильтр Эйлера, но это не сработало, как ожидалось. Большинство советов о блокировке кардана заключалось в использовании кватернионов, но я не могу управлять физическим двигателем с помощью кватерниона (или могу?).
Порядок осей здесь на самом деле не имеет значения, потому что его изменение только переместит сингулярность с одной оси на другую.
Мне нужно справиться с этим по-другому.
Я попытался умножить векторы осей на матрицу, а затем использовать крест и скалярное произведение, чтобы получить углы, но это тоже не удалось. Я думаю, что для правильного решения необходимо также задействовать перепроецирование оси, но я не мог этого понять. Но что-то мне подсказывает, что это правильный способ сделать это. Это было примерно так: http://jsfiddle.net/qajro0ny/53/
Потом мне пришла в голову другая идея. Я знаю предыдущую позицию, поэтому, возможно, сделаю следующее:
- Преобразовать матрицу в кватернион
- Вычислить разницу между текущим и предыдущим кватернионом
- Преобразуйте полученный кватернион в углы Эйлера
- Добавьте эти углы к статическим переменным тангажа, крена и рыскания.
Я попробовал и ... это сработало! Никаких особенностей в любом из направлений, идеальное вращение на 360 градусов по тангажу, крену и рысканью. Идеальное решение! Только вот ... это не так. Кадры не синхронизировались, поэтому через некоторое время углы стали отличаться от должных. Я думал о каком-то механизме синхронизации, но решил, что это неправильный путь.
Выглядело это так: http://jsfiddle.net/qajro0ny/52/
И та же логика, но напрямую с матрицами: http://jsfiddle.net/qajro0ny/54/
Я искал в Интернете повсюду, я прочитал десятки статей и других вопросов / сообщений, и я просто не могу поверить, что в моем случае ничего действительно не работает.
Я могу чего-то не понять или пропустить, поэтому вот все, что я нашел и попробовал:
Ссылки: http://pastebin.com/3G0dYLvu
Код: http://pastebin.com/PiZKwE2t (я собрал все вместе, так что все беспорядочно)
Должно быть, я чего-то упускаю, или я смотрю на это не под тем углом.