Учитывая нормализованный кватернион, A_q
и нормализованный вектор направления, B_v
мы рассчитываем новое вращение, C_q
, что будет вращаться A_q
«лицом» в направлении B_v
, Чтобы уточнить, давай D_q = C_q * A_q
такой, что (1,0,0)
повернуто на D_q
будет равен B_v
,
Нотабене Для удобства обозначения отныне мы будем ссылаться на (1,0,0)
повернутый любым кватернионом как символ этого кватерниона с суффиксом _v
т.е. (1,0,0)
повернуто на A_q
становится A_v
,
Я реализовал такой сценарий Вот (интерактивно), с источником Вот, и прикрепили gif ниже тоже.
Моя проблема в том, что когда A_v
а также B_v
близки к противоположным (или, казалось бы, приближаются к антипараллельным), D_q
проявляет внезапный поворот / крен, что нежелательно. Изображение выше демонстрирует это.
Он находится в C ++ API UE4, но он должен быть достаточно независимым от языка / фреймворка для анализа:
FTransform UMWEUtil::FindNewRotation(FTransform A_t, FVector B_v)
{
FQuat A_q = A_t.GetRotation();
FVector A_v = A_q.GetForwardVector();
A_v.Normalize();
B_v.Normalize();
FVector AxisOfRotation = FVector::CrossProduct(A_v, B_v).GetSafeNormal();
float Rads = FMath::Acos(FVector::DotProduct(A_v, B_v));
FQuat C_q(AxisOfRotation, Rads);
FQuat D_q = C_q * A_q;
return FTransform(D_q);
}
A_v X B_v
меняющиеся полушария. Но тогда, почему это происходит только один раз, а не дважды (перекрестное произведение, A_v X B_v
виден переход полушарий дважды в полный оборот)?D_q
в кватернионы качания / крутки и используйте только кватернионы качания (таким образом, удаляя внезапный поворот). Тем не менее, это похоже на пластырь из-за моего непонимания проблемы, есть ли другое решение, которое приведет к плавному переходу?FTransform UMWEUtil::FindNewRotation2(FTransform A_t, FVector B_v)
{
FQuat A_q = A_t.GetRotation();
FVector A_v = A_q.GetForwardVector();
A_v.Normalize();
B_v.Normalize();
FVector AxisOfRotation = FVector::CrossProduct(A_v, B_v).GetSafeNormal();
float Rads = FMath::Acos(FVector::DotProduct(A_v, B_v));
FQuat C_q(AxisOfRotation, Rads);
FQuat D_q = C_q * A_q;
FQuat OutSwing;
FQuat OutTwist;
D_q.ToSwingTwist(FVector::ForwardVector, OutSwing, OutTwist);
return FTransform(OutSwing);
}
Задача ещё не решена.
Других решений пока нет …