我基本上正致力于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;
}
基本上它正在做什么(或者应该做什么)只是在两个值之间进行旋转以提供旋转,并且将其结果转换为旋转矩阵。但出现问题的是一个可怕的,可怕的拉伸视图......由于某种原因,它在旋转期间拉伸了所有东西,从一切都太长/太薄开始到达一个更短的中点,然后再开始变瘦。任何帮助都会很棒。
答案 0 :(得分:1)
你的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;
答案 1 :(得分:0)
你需要规范化四元数吗?
我认为如下:
float sTheta = std::sin(theta);
应该是:
float sTheta = sqrt(1.0f - sqr(theta));