Объединение кватернионов с разной точкой поворота
История:
В настоящее время я использую шейдер скелетной анимации в GLSL, и для экономии места и сложности я использую Quaternions для вращения костей с использованием взвешенного умножения кватернионов (каждой кости) для накопления "окончательного вращения" для каждой вершины.
Что-то вроде: (псевдокод, просто предположим, что математика кватернионов работает как ожидалось)
float weights[5];
int bones[5];
vec4 position;
uniform quaternion allBoneRotations[100];
uniform vec3 allBonePositions[100];
main(){
quaternion finalQuaternion;
for(i=0;i<5;i++){finalQuaternion *= allBoneRotations[bones[i]]*weights[i];}
gl_position = position.rotateByQuaternion(finalQuaternion);
}
Реальный код сложный, неаккуратный и работающий, как ожидалось, но это должно дать общую идею, так как это в основном математический вопрос, код не имеет большого значения, он просто предоставляется для ясности.
Проблема:
Я был в процессе добавления "опорных точек" / "совлокальных мест" к каждой кости (отрицательный перевод, поворот на "окончательный кватернион", перевод), когда я понял, что "окончательный кватернион" не будет принимать при совпадении самих кватернионов учитываются разные точки поворота. В этом случае каждое вращение кости будет обработано так, как если бы оно было вокруг точки (0,0,0).
Учитывая, что кватернионы представляют только поворот, кажется, мне нужно либо "добавить" позицию к кватернионам (если это возможно), либо просто преобразовать все кватернионы в матрицы, а затем умножить матрицу на объединение ряда переводов и поворотов. Я действительно надеюсь, что последнее не понадобится, поскольку кажется, что это будет действительно неэффективно, сравнительно.
Я искал mathoverflow, math.stackexchange и все, что еще предоставлял Google, и читал следующие ресурсы до сих пор в надежде выяснить сам ответ:
Консенсус в том, что Quaternions не кодируют "перевод" или "позицию" в каком-либо смысле и, похоже, не обеспечивают интуитивно понятный способ имитации, поэтому чистая математика кватернионов вряд ли будет жизнеспособным решением.
Однако было бы неплохо получить окончательный ответ на этот вопрос. Кто-нибудь знает какой-либо способ "подделать" компонент позиции кватерниона, который каким-то образом сохранит математическую эффективность кватерниона или какой-либо другой метод "накапливать" вращения вокруг разных точек происхождения, что более эффективно, чем просто вычисление матрицы кватернионов и выполнения матричного перевода и умножения вращения для каждого кватерниона? Или, может быть, какая-то математическая уверенность в том, что разные точки поворота на самом деле не имеют никакого значения и могут быть применены позже (но я сомневаюсь).
Или использует кватернионы в этой ситуации только плохую идею на первый взгляд?
Ответы
Ответ 1
В самом деле, нет такой вещи, как компонент позиции кватерниона, поэтому вам нужно будет отслеживать его отдельно. Предположим, что индивидуальные преобразования оказываются похожими на
x' = R(q)*(x-pivot)+pivot = R(q)*x + (pivot-R(q)*pivot) = R(q)*x+p,
где q
- ваш кватернион, R(q)
- это матрица вращения, построенная из него, а p=pivot-R(q)*pivot
- компонент положения/перевода. Если вы хотите объединить два таких преобразования, вы можете сделать это, не перебирая полноразмерное умножение:
x'' = R(q2)*x'+p2 = R(q2)*R(q)*x + (R(q2)*p+p2) = R(q2*q)*x + (R(q2)*p+p2).
Таким образом, объединенный кватернион будет q2*q
, а комбинированное положение - R(q2)*p+p2
. Обратите внимание, что вы даже можете применять кватернионы к векторам (R(q2)*p
и т.д.) Без явного построения матриц вращения, если вы хотите их полностью избежать.
Тем не менее, существует понятие "двойных кватернионов", которые на самом деле содержат компонент трансляции и, по-видимому, лучше для представления движений винта. Проверьте их в Wiki и здесь (последняя ссылка также указывает на бумагу).
Ответ 2
После обширного дополнительного поиска и чтения больше о кватернионах, чем любой здравомыслящий человек, я, наконец, нашел свой ответ здесь:
http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/other/dualQuaternion/index.htm
Оказывается, Двойные кватернионы действуют аналогично действительным кватернионам, причем многие из математических операций основаны на правильной математике кватернионов, но они обеспечивают как ориентацию, так и смещение, и могут быть объединены для любой требуемой последовательности перевода вращения например, преобразование матрицы преобразования, но без способности сдвига/масштабирования.
На странице также есть раздел, который точно выполняет функцию "поворот вокруг произвольной точки", которую я требую, используя двойное умножение кватернионов. Возможно, мне следовало бы изучить немного больше, прежде чем спрашивать, но, по крайней мере, ответ здесь сейчас, если кто-то еще смотрит.