2012-07-20 55 views
1

我想實現骨骼動畫在我的遊戲引擎和我有插值問題。GLM ::混合返回無效四元

每個幀,我想幀之間進行內插,因此我具有類似於此代碼:

// This is the soon-to-be-interpolated joint 
Joint &finalJoint = finalSkeleton.joints[i]; 

// These are our existing joints 
const Joint &joint0 = skeleton0.joints[i]; 
const Joint &joint1 = skeleton1.joints[i]; 

// Interpolate 
finalJoint.position = glm::lerp(joint0.position, joint1.position, interpolate); 
finalJoint.orientation = glm::mix(joint0.orientation, joint1.orientation, interpolate); 

最後一行就是問題所在。 finalJoint的方向有時是(-1.#IND, -1.#IND, -1.#IND, -1.#IND)

這些都是一些例子價值觀和他們產生什麼(請注意,interpolation0.4在這三種情況下):

  • joint0.orientation = (0.707107, 0.000242, 0.707107, 0.0)
    joint1.orientation = (0.707107, 0.000242, 0.707107, 0.0)
    finalJoint = (-1.#IND, -1.#IND, -1.#IND, -1.#IND)(錯誤)

  • joint0.orientation = (-0.451596, -0.61858, -0.262811, -0.586814)
    joint1.orientation = (-0.451596, -0.61858, -0.262811, -0.586814)
    finalJoint = (-0.451596, -0.61858, -0.262811, -0.586814)(正確)

  • joint0.orientation = (0.449636, 0.6195, 0.26294, 0.58729)
    joint1.orientation = (0.449636, 0.6195, 0.26294, 0.58729)
    finalJoint = (-1.#IND, -1.#IND, -1.#IND, -1.#IND)(錯誤)

(是的,我知道它是相同的值之間插值)。

我還沒有準確掌握四元數是如何工作的,但這對我來說似乎很奇怪。

+0

這是真實的(不幸)許多三維幾何操作。例如,如果你做'cross(a,a)',你會得到什麼?不良。但是,我不明白這對於兩個四元組之間的隔離可能是一個問題。 – Puppy 2012-07-20 02:24:43

+0

您是否認爲這只是GLM的四元數slerp實現中的一個錯誤? – 2012-07-20 03:27:54

+0

@NicolBolas我想這是可能的。我剛開始考慮它,但經過一段時間的搜索後,我找不到任何有問題的人。我現在要睡覺了,但我會明天嘗試推出自己的斯勒普功能,看看它是否有效。 – Merigrim 2012-07-20 03:41:23

回答

2

如果你看一下typical Slerp equation,你會看到它有一個分數的分母其中Ω是兩個四元數之間的角度Sin(Ω):即Ω = acos(dot_product(q1,q1));現在,Sin(0)==0;而當你除以零,有是問題。正如維基百科文章中提到的那樣,這是一個可移動的不連續性,但需要一些額外的檢查。

我只是拉下來的代碼來看看。這是它的總和:

T angle = acos(dot(x, y)); 
return (glm::sin((T(1)-a)*angle)*x+glm::sin(a*angle)*y)/glm::sin(angle); 

沒有特殊檢查。當角度接近於零時,這很容易產生數字問題。對於一些內插來說,它也可能需要漫長的旋轉球體。還有兩個版本的glm ::: mix註釋說,要更好地處理這些問題。它看起來像當前版本及其伴隨的問題是2011年5月的committed to the repository.

如果角度小於某個閾值量,我會建議恢復爲使用線性插值的版本。只是評論當前並取消舊版評論。

+0

確實,這是問題所在。通過我自己的實現(對此進行檢查),事情似乎有些不錯,但如您所說,使用其他GLM版本似乎更好。 – Merigrim 2012-07-24 17:56:22

+1

FWIW,它昨天已被更正(在有問題的情況下使用線性插值,正如基本數學書中提出的那樣):https://github.com/g-truc/glm/commit/c19dda37972b762aa0dee8444e762bdce9f04759 – Calvin1602 2012-12-20 10:04:48