2013-06-12 2 views
2

두 쿼터니언 사이의 Slerp 보간 방법에 대한 두 가지 다른 소스를보고 있습니다. 그들은 하나 개의 주목할만한 차이를 제외하고 꽤 비슷 하나는 0과 1, 그리고 Here -1과 1 사이 다른 사이의 내적을 클램프 그들 중 하나입니다 : 여기 Quaternion 용 Slerp에서 내 제품 클램프

glm::fquat Slerp(const glm::fquat &v0, const glm::fquat &v1, float alpha) 
{ 
    float dot = glm::dot(v0, v1); 

    const float DOT_THRESHOLD = 0.9995f; 
    if (dot > DOT_THRESHOLD) 
     return Lerp(v0, v1, alpha); 

    glm::clamp(dot, -1.0f, 1.0f); //<-- The line in question 
    float theta_0 = acosf(dot); 
    float theta = theta_0*alpha; 

    glm::fquat v2 = v1 - v0*dot; 
    v2 = glm::normalize(v2); 

    return v0*cos(theta) + v2*sin(theta); 
} 

다른입니다 :

template <typename T> 
inline QuaternionT<T> QuaternionT<T>::Slerp(T t, const QuaternionT<T>& v1) const 
{ 
    const T epsilon = 0.0005f; 
    T dot = Dot(v1); 

    if (dot > 1 - epsilon) { 
     QuaternionT<T> result = v1 + (*this - v1).Scaled(t); 
     result.Normalize(); 
     return result; 
    } 

    if (dot < 0) //<-The lower clamp 
     dot = 0; 

    if (dot > 1) 
     dot = 1; 

    T theta0 = std::acos(dot); 
    T theta = theta0 * t; 

    QuaternionT<T> v2 = (v1 - Scaled(dot)); 
    v2.Normalize(); 

    QuaternionT<T> q = Scaled(std::cos(theta)) + v2.Scaled(std::sin(theta)); 
    q.Normalize(); 
    return q; 
} 

두 번째 질문에서 Lerp 알고리즘이 모든 경우에 적합하지 않다고 생각합니다.

나는이 차이점에 대해 의견을 나누기를 바랍니다.

답변

3

당신은 그들의 내부-제품이 1보다 약간 큰 것을 끝 있도록 포인트 차이 부동 그것을 만들 수 있습니다,이 함수에 전달하기 전에 당신이 그 (것)들에게 모두 권리를 정상화하더라도, slerp 둘 사이의 사원 수 q1q2을 수행하는 경우 또는 음수 미만일 수 있습니다. 그러면 acos이 다운됩니다. 물론 두 코드 조각에서 dot(q1,q2)>1 인 경우 코드는 선형 보간을 수행하고 즉시 반환됩니다. 따라서 +1에 클램핑하는 것은 불필요합니다. 두 번째 예제에서는 Lerp과 관련하여 특별한 문제가 없습니다.

두 경우 모두 0 또는 -1로 클램프하는 것은 일반적으로 불필요하며 잘못된 생각 일 수 있습니다.

두 가지 쿼터니언의 내부 제품이 음수이면 가장 큰 차이는 두 쿼터니언의 내부 제품이 음수이면 두 제품 사이를 보간하는 것이 먼 길을 의미한다는 것입니다. 두 선 사이의 각도가 30 도인 경우 330 도로 회전하여 한 선을 다른 선으로 보간 할 수도 있습니다. 오리엔테이션 공간도 동일하게 유지됩니다.

유닛 쿼터니언은 배향의 2 배 중복 표현입니다. 그래서 두 쿼터니언 사이의 내재가 0보다 작 으면 보간하기 전에 일반적으로 그 중 하나의 요소를 모두 무효화합니다.

할 경우은 먼 거리를 보간하려고합니다. -1로 클램프하는 것이 옳습니다. 내적을 제로로 클램핑하면 상황이 상당히 나빠질 것입니다. 주위를 멀리 보간하고 싶지 않다면 쿼터니언을 이들 함수 중 하나에 전달하기 전에 항상 음수가 아닌 내부 제품을 보장해야합니다. 그래서 제로 클램핑은 불필요합니다.

+0

으로 잘 알려져있다. 두 번째 코드는 간단한 냄새 테스트를 통과하지 못합니다. 처음에는 1-eps를 확인한 다음 다시 1로 클램프합니다. 코드에서 수비가 좋을지라도 acos는 -1 또는 -1 + eps를 클램프해야하지만 0은 클램프하지 않아야합니다. – starmole