1

我本质上是在研究一个用于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;
}

本质上它正在做的(或应该做的)只是在两个值之间滑动以提供旋转,并且由此产生的结果被转换为旋转矩阵。但是出了问题的是一个可怕的,可怕的拉伸视图......由于某种原因,在旋转过程中它拉伸了所有东西,从所有东西开始太长/太薄,然后在开始变瘦之前达到一个更短的中点。任何帮助都会很棒。

4

2 回答 2

1

您的 slerp 代码看起来不错,尽管通常会确保这样做,dot>=0否则,您将绕圈旋转很长一段路。一般来说,确保这一点也很重要,dot!=1因为您会遇到被零除的问题。

一个适当的四元数不应该拉伸视图。要么你为 or 传递非单位长度的四元数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;
于 2012-12-26T21:37:42.283 回答
0

你需要标准化四元数吗?

我认为以下几点:

float sTheta = std::sin(theta);

应该:

float sTheta = sqrt(1.0f - sqr(theta));
于 2012-12-26T21:02:11.487 回答