Форум

Поворот объекта относительно локальной оси

30 января 2018 14:01
Запутался с векторами поворота и кватерионами.
Значит так.
Вот такая конструкция вращает объект вокруг Vec3, который я задаю:

var AXIS_X = new Float32Array([1, 0, 0]); // Ось Х

m_quat.setAxisAngle(AXIS_X, (-Math.PI/360 ) * increment, quat_tmp); // Определяем кватерион из текущего положения и приращения
m_transform.get_rotation(obj, quat_tmp2); // Получаем текущее вращение в кватерион
m_quat.multiply(quat_tmp, quat_tmp2, quat_tmp); // Перемножаем текущее положение и требуемый поворот
m_transform.set_rotation_v(obj, quat_tmp); // Поворачиваем объект в новую позицию


Код отлично работает, когда я хочу повернуть объект вокруг ГЛОБАЛЬНЫХ осей X,Y,Z.
А мне нужно чтобы объект поворачивался вокруг ЛОКАЛЬНОЙ оси.

Мне нужно получить текущее вращение объекта, но функция

m_transform.get_rotation(obj, opt_destopt) → {Quat}

Даёт кватерион.
А мне нужен Vec3 для функции m_quat.setAxisAngle.

Как быть в данной ситуации?
30 января 2018 14:15
Код отлично работает, когда я хочу повернуть объект вокруг ГЛОБАЛЬНЫХ осей X,Y,Z.
А мне нужно чтобы объект поворачивался вокруг ЛОКАЛЬНОЙ оси.
Нужно заменить порядок перемножения кватернионов:
m_quat.multiply(quat_tmp, quat_tmp, quat_tmp2);
m_quat.multiply(quat_tmp2, quat_tmp, quat_tmp2);
Команда Blend4Web - разработчик
Twitter
LinkedIn
30 января 2018 14:46
Мне нужно получить текущее вращение объекта, но функция

m_transform.get_rotation(obj, opt_destopt) → {Quat}

Даёт кватерион.
А мне нужен Vec3 для функции m_quat.setAxisAngle.
достаточно взять первые 3 компоненты кватерниона + нормализовать полученный вектор
Команда Blend4Web - разработчик
Twitter
LinkedIn
30 января 2018 15:34
В произведении кватернионов поменяйтя порядок аргументов:
m_quat.multiply(quat_tmp, quat_tmp, quat_tmp2);

У вас небольшая ошибка. Вы вычисляете просто квадрат кватерниона.
Вот так заработало
m_quat.multiply(quat_tmp2, quat_tmp, quat_tmp2);



достаточно взять первые 3 компоненты кватерниона (+ возможно, стоит нормализовать полученный вектор, в случае если угол поворота, который вы хотите задать, является малым)

Это решение скорее всего более громоздкое (лишняя операция\строчка кода).
"малый угол" - да, я приращаю по 1-5 градусов.
30 января 2018 15:36
У вас небольшая ошибка. Вы вычисляете просто квадрат кватерниона.
Вот так заработало
Да, это, конечно, очепятка. Сейчас поправим, чтобы случайно забредших в тему не вводить в заблуждение
[UPD] нормализовывать вектор, задающий ось, нужно всегда, для корректной работы m_quat.setAxisAngle
Команда Blend4Web - разработчик
Twitter
LinkedIn
30 января 2018 16:56
Так. Новые вводные.
Вращаю я так, как мне надо. Сделал даже инкремент вращения на 5 градусов.
Вращаю объект на 180 градусов
Теперь мне нужно ПОЛУЧИТЬ вращение объекта в ГРАДУСАХ.
Делаю так
console.log ((m_transform.get_rotation_euler(obj)[1]*(57.2958)));

Получаю вывод консоли
0..5..10..15.. …..85..90 - казалось бы - получены градусы, но не тут то было поворот от 0 до 180 дает следующий вывод
0..5..10..15.. …..85..90..85..80.. … … 15..10..5.
т.е. до 90 идет нормально, а потом вместо 95 идет 85 и так далее.
т.е. двум положениям соответствует один угол.
Как избежать такой дихотомии?

Например в кватернионах есть
setAxisAngle(axis, rad, out) → {Quat}

но мне нужно не set, a get.

Или можно как-нибудь получить "человеческие" градусы не через углы Эйлера?
30 января 2018 17:04
Так. Новые вводные.
Вращаю я так, как мне надо. Сделал даже инкремент вращения на 5 градусов.
Вращаю объект на 180 градусов
Теперь мне нужно ПОЛУЧИТЬ вращение объекта в ГРАДУСАХ.
Делаю так
console.log ((m_transform.get_rotation_euler(obj)[1]*(57.2958)));

Получаю вывод консоли
0..5..10..15.. …..85..90 - казалось бы - получены градусы, но не тут то было поворот от 0 до 180 дает следующий вывод
0..5..10..15.. …..85..90..85..80.. … … 15..10..5.
т.е. до 90 идет нормально, а потом вместо 95 идет 85 и так далее.
т.е. двум положениям соответствует один угол.
Как избежать такой дихотомии?

Или можно как-нибудь получить "человеческие" градусы не через углы Эйлера?
Угол поворота вокруг оси вращения заданной в кватернионе (те по сути угол поворота при вращении через AxisAngle) можно получить как:
Math.acos(tmp_quat[3]) * 2
Команда Blend4Web - разработчик
Twitter
LinkedIn
30 января 2018 17:40
Угол поворота вокруг оси вращения заданной в кватернионе (те по сути угол поворота при вращении через AxisAngle) можно получить как:
Math.acos(tmp_quat[4]) * 2

Что-то всё-равно не так.
Во-первых, наверное всё-таки вы имели ввиду
Math.acos(tmp_quat[3]) * 2

т.к. у кватерниона нет пятой координаты[4], а есть четвертая [3]
Во вторых всё-равно не получается.
Вот такой код,

        m_transform.get_rotation(obj, quat_tmp2);
console.log(Math.acos(quat_tmp2[3]) * 2*(57.2958));


во время вращения объекта на ПРАВИЛЬНЫЕ 180 С ИНКРЕМЕНТОМ в 5 ГРАДУСОВ даёт следующий вывод
   120.00004290770006
122.92757747667115
125.93200298956047
129.00661573063044
132.14511558966493
135.34157397849685
138.5904208851458
141.88641437894051
145.22460900053633
148.60033076997655
152.00915533898376
155.4468737996139
158.90946612590167
162.3930820009238
165.89400565841694
169.40864041064557
172.93347852532855
176.46508169280335
180.00005597831736
183.5350301602349
187.06663351747298
190.59147202121227
194.10610671929166
197.60703117103847
201.09064696525232
204.55324094341432
207.99096106560543
211.39978731079665
214.7755125653175
218.1137071179368
221.4097041870633
224.6585547446033
227.85501686962013
230.99352055962714
234.06813723557678
237.07256679582864
240.00010158905263

т.е. при реальном повороте объекта на 180 вывод идет от 120 до 240 т.е. на 120 градусов.

Я подумал, что "ага, нужно умножить на 3/2"

В итоге вот такая строка

console.log(Math.acos(quat_tmp2[3]) * 3*(57.2958));

даёт следующий вывод

180.0000643615501
184.3913662150067
188.8980044843407
193.50992359594565
198.2176733844974
203.0123609677453
207.8856313277187
212.82962156841077
217.8369135008045
222.90049615496483
228.01373300847564
233.17031069942084
238.36419918885252
243.58962300138572
248.84100848762543
254.11296061596835
259.4002177879928
264.69762253920504
270.0000839674761
275.30254524035234
280.5999502762095
285.8872080318184
291.1591600789375
296.4105467565577
301.6359704478785
306.82986141512146
311.98644159840813
317.09968096619497
322.16326884797627
327.17056067690515
332.11455628059497
336.98783211690494
341.7825253044302
346.4902808394407
351.10220585336515
355.60885019374297
360.00015238357895

т.е.
1. изменение на реальные 180 градусов.
2. Очень точные значения в точках 180, 270, 360 градусов.
Но в промежуточных углах разброд и шатание, который не уйдет через округление Math.round.

Что я делаю не так?
30 января 2018 17:52
Что-то всё-равно не так.
Во-первых, наверное всё-таки вы имели ввиду
Math.acos(tmp_quat[3]) * 2
Ага, сегодня явно не мой день
1. изменение на реальные 180 градусов.
2. Очень точные значения в точках 180, 270, 360 градусов.
Но в промежуточных углах разброд и шатание, который не уйдет через округление Math.round
Опишите, пожалуйста, задачу в целом:
начальная ориентация объекта, какой поворот нужен и какие значения хотите получать итд так понятнее будет
Команда Blend4Web - разработчик
Twitter
LinkedIn
30 января 2018 17:57
начальная ориентация объекта, какой поворот нужен итд так понятнее будет
С поворотом я разобрался. Забыли про него.
Текущая задача элементарна.
Получить значение поворота ЛЮБОГО объекта сцены в градусах (т.е. локальное положение относительно мира).
Например (angle_X, angle_Y, angle_Z). Например (45, 267, 310).

Получать значения хочу типа 45,0001435356456 (которые округлю до целого).
 
Пожалуйста, зарегистрируйтесь или войдите под своей учетной записью , чтобы оставлять сообщения.