Я по сути работаю над функцией для slerping и хотя это вроде как работает, у меня странная перспективная проблема, которую я застрял, пытаясь решить прямо сейчас.
Quaternion sLerp(Quaternion start, Quaternion end, float s)
{
float dot = qDot(start, end);
float theta = std::acos(dot);
float sTheta = std::sin(theta);
float w1 = sin((1.0f-s)*theta) / sTheta;
float w2 = sin(s*theta) / sTheta;
Quaternion Temp(0,0,0,0);
Temp = start*w1 + end*w2;
return Temp;
}
По сути, то, что он делает (или должен делать), это просто разбрасывает между двумя значениями, чтобы обеспечить вращение, и результат этого преобразовывается в матрицу вращения. Но то, что идет не так, это ужасно, ужасно растянутое представление … по какой-то причине во время вращения оно растягивало все, начиная со всего слишком длинного / тонкого и достигая середины гораздо меньшей длины, прежде чем снова становиться худым. Любая помощь будет отличной.
Ваш код Slerp кажется нормальным, хотя обычно нужно убедиться, что dot>=0
потому что иначе вы вращаете длинный круг. В общем, также важно убедиться, что dot!=1
потому что вы столкнетесь с деления на ноль проблемы.
Правильный кватернион никогда не должен растягивать взгляд. Либо вы передаете в кватернионы не единичной длины для start
или же end
или ваш код кватерниона к матрице является подозрительным (или вы получаете странное поведение, потому что угол между двумя кватернионами очень мал, а вы делите почти на ноль).
Мой код для преобразования из кватерниона в матрицу для использования в OpenGL:
// First row
glMat[ 0] = 1.0f - 2.0f * ( q[1] * q[1] + q[2] * q[2] );
glMat[ 1] = 2.0f * (q[0] * q[1] + q[2] * q[3]);
glMat[ 2] = 2.0f * (q[0] * q[2] - q[1] * q[3]);
glMat[ 3] = 0.0f;
// Second row
glMat[ 4] = 2.0f * ( q[0] * q[1] - q[2] * q[3] );
glMat[ 5] = 1.0f - 2.0f * ( q[0] * q[0] + q[2] * q[2] );
glMat[ 6] = 2.0f * (q[2] * q[1] + q[0] * q[3] );
glMat[ 7] = 0.0f;
// Third row
glMat[ 8] = 2.0f * ( q[0] * q[2] + q[1] * q[3] );
glMat[ 9] = 2.0f * ( q[1] * q[2] - q[0] * q[3] );
glMat[10] = 1.0f - 2.0f * ( q[0] * q[0] + q[1] * q[1] );
glMat[11] = 0.0f;
// Fourth row
glMat[12] = 0.0;
glMat[13] = 0.0;
glMat[14] = 0.0;
glMat[15] = 1.0f;
Нужно ли нормализовать кватернион?
Я думаю следующее:
float sTheta = std::sin(theta);
должно быть:
float sTheta = sqrt(1.0f - sqr(theta));