Slerp问题,透视翘曲

时间:2012-12-26 20:20:56

标签: c++ interpolation linear quaternions linear-interpolation

我基本上正致力于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;
}

基本上它正在做什么(或者应该做什么)只是在两个值之间进行旋转以提供旋转,并且将其结果转换为旋转矩阵。但出现问题的是一个可怕的,可怕的拉伸视图......由于某种原因,它在旋转期间拉伸了所有东西,从一切都太长/太薄开始到达一个更短的中点,然后再开始变瘦。任何帮助都会很棒。

2 个答案:

答案 0 :(得分:1)

你的slerp代码看起来很好,虽然通常会确保dot>=0,否则你会绕着圆圈旋转很长时间。一般而言,确保dot!=1也很重要,因为您将遇到除零问题。

正确的四元数应该永远不会拉伸视图。您要传递startend的非单位长度四元数,或者您的四元数到矩阵代码是可疑的(或者您正在获得时髦的行为,因为两个四元数之间的角度非常小,你几乎为零。)


我的代码用于从四元数转换为矩阵以便在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));