расстояние/величина между кватернионами, но игнорировать бросок

Я ищу способ определить, смотрит ли камера (a) в том же направлении, что и конкретный объект (b).

Я работаю только с поворотами, потому что здесь нас не волнуют положения (поэтому мы можем считать, что оба они расположены в начале координат).

Я работаю с кватернионами, используя gl-матрицу.

После многих поисков и тестов я понял, что могу определить «расстояние» (величину?) между двумя кватернионами, используя скалярное произведение.

var a = quat.create();
quat.rotateY(a, a, Math.PI);

var b = quat.create();
quat.rotateY(b, b, Math.PI);

quat.dot(a, b)

Это хорошо работает во многих случаях (возвращает число в диапазоне [0..1]: от 1, если оба смотрят в одном направлении, до 0, если оба смотрят в противоположные стороны).

Однако в моем случае я не хочу заботиться о «прокрутке» между объектами. Я имею в виду, что камера (a) может быть перевернута относительно (b), но все равно смотреть в ту же точку.

Например, если я поверну b на 180 градусов вокруг Z, я получу скалярное произведение, которое будет около 0, хотя оно все еще смотрит в том же направлении.

var a = quat.create();
quat.rotateY(a, a, Math.PI);

var b = quat.create();
quat.rotateY(b, b, Math.PI);
quat.rotateZ(b, b, Math.PI);

quat.dot(a, b);

Я пробовал много вещей, таких как умножение обратного числа a на b или [s]lerp, но я все еще не могу получить ничего, что соответствовало бы моим требованиям.

Конечно, я не могу просто отделиться и работать с абсолютной осью Z, потому что здесь все относительно, поэтому крен может быть вокруг любой оси.

Как я могу получить этот результат?

РЕДАКТИРОВАТЬ: благодаря ответу LutzL, вот как я реализовал решение:

var r = quat.create();
quat.invert(r, a);
quat.multiply(r, r, b);

var distance = r[3]*r[3] - r[0]*r[0] - r[1]*r[1] + r[2]*r[2];

person Sebastien C.    schedule 25.04.2014    source источник


Ответы (2)


Я интерпретирую это так, что единичный вектор оси Z (в местных координатах) является вашим вектором, указывающим вперед?

Кватернион a описывает перевод локальной системы координат в глобальную систему координат. Таким образом, вектор v в локальных координатах имеет направление a*v*a' (a'=сопряженное с a=обратное для единичного кватерниона) в глобальной системе отсчета. Таким образом, направление оси Z изменяется согласно ka=a*k*a'.

Таким образом, направление Z второго объекта равно kb=b*k*b'. Косинус угла между ними — это скалярное произведение ka и kb, которое также является действительной частью ka'*kb=a*k'*a'*b*k*b'. Действительная часть любого кватерниона v остается неизменной в a'*v*a, поэтому

масштаб (ka, kb) = реальный (ka * kb')

= -real(k * a' * b * k * b' * a) = -real( k * (a' * b) * k * (a'* b)')

Я не знаю специфики реализации GL, но операции заключаются в вычислении произведения p1=a'*b, повороте p1 вокруг оси Z на 180 градусов до p2, что на практике просто переворачивает знаки i и коэффициенты j и формирование скалярного произведения p1 и p2. Короткая версия

scal(ka,kb) = p1.w*p1.w - p1.x*p1.x - p1.y*p1.y + p1.z*p1.z

person Lutz Lehmann    schedule 25.04.2014
comment
Вау, это отлично работает. Проблема в том, что я не все понимаю :). Кажется, мне еще многому предстоит научиться. В любом случае, спасибо ! - person Sebastien C.; 26.04.2014

  1. Найдите 2 вектора dirA и dirB , направление камеры и объекта. Вы можете просто преобразовать вектор Z(0,0,1) соответствующими кватернионами.

  2. Найдите угол между векторами dirA dirB по

    угол = atan2(крест(dirA, dirB).len(), точка(dirS, dirB))

person minorlogic    schedule 26.04.2014