所以我最近一直在學習四元數,并決定做出自己的實作。x/y/z軸的旋轉本身作業正常,y/z軸的旋轉也是如此,但當我把x軸加到其他任何一個軸上時,我就會得到一個奇怪的拉伸輸出。我將在下面附上旋轉的重要代碼:(請注意,我對cpp很陌生)
。下面是我對四元數的描述(據我所知,因為它們是單位四元數,所以不需要虛數):
struct Quaternion {
float w, x, y, z;
};
四元數的乘法規則:
四元數 operator* (Quaternion n, Quaternion p) {
四元數o。
//實作四元數乘法規則:
o.w = n.w * p.w - n.x * p.x - n.y * p.y - n.z * p.z。
o.x = n.w * p.x n.x * p.w n.y * p.z - n.z * p.y。
o.y = n.w * p.y - n.x * p.z n.y * p.w n.z * p.x。
o.z = n.w * p.z n.x * p.y - n.y * p.x n.z * p.w。
return o;
}
生成旋轉四元數以乘以總旋轉:
四元數 rotate(float w, float x, float y, float z) {
四元數n。
n.w = cosf(w/2)。
n.x = x * sinf(w/2)。
n.y = y * sinf(w/2)。
n.z = z * sinf(w/2)。
return n;
}
最后,將四元數變成x/y/z位置的矩陣計算:
inline vector<float>。quaternion_matrix(Quaternion total, vector<float> vec) {
float x = vec[0], y = vec[1] , z = vec[2] 。
//實作3x3四元數旋轉矩陣:
vec[0] = (1 - 2 * pow(總。 y, 2) - 2 * pow(total. z, 2))*x (2 * total.x * total.y - 2 * total. w * total.z)*y (2 * total.x * total.z 2 * total.w * total.y)*z。
vec[1] = (2 * total.x * total.y 2 * total. w * total.z)*x (1 - 2 * pow(total. x, 2) - 2 * pow(total. z, 2))*y (2 * total.y * total.z 2 * total.w * total.x) *z。
vec[2] = (2 * total.x * total.z - 2 * total. w * total.y)*x (2 * total.y * total.z - 2 * total.w * total. x)*y (1 - 2 * pow(total. x, 2) - 2 * pow(total.y, 2) )*z。
return vec;
}
差不多就是這樣(我還有一個歸一化函式來處理浮點誤差),我把所有物件的四元數初始化為:w = 1, x = 0, y = 0, z = 0。我使用這樣的運算式來旋轉四元數:
obj.rotation = rotate(angle, x-axis, y-axis, z-axis)* obj.rotation
其中obj.rotation是物件的總四元數旋轉值。
如果有人知道問題出在哪里,或者以前也遇到過這個問題,我希望能在這個問題上得到任何幫助。謝謝
編輯:用總數乘以這些四元數,就能輸出預期的旋轉值:。rotate(angle,1,0, 0)
旋轉(angle,0,1, 0)
旋轉(angle,0,0, 1)
旋轉(angle,0,1, 1)
然而,任何像這樣的旋轉都會使模型產生奇怪的拉伸:
rotate(angle,1,1, 0)
旋轉(angle,1,0, 1)
編輯2:這里是我用來歸一化四元數的歸一化函式:
。四元數 normalize(Quaternion n, double tolerance){
//加入四元數值的所有平方,如果歸一化,總的來說將是1:。
double total = pow(n.w, 2) pow(n. x, 2) pow(n.y, 2) pow(n.z, 2) 。
if (total > 1 tolerance || total < 1 - tolerance) {
///將四元數的值歸一化,如果它超過某個公差值:
n.w /= (float) sqrt(總)。
n.x /= (float) sqrt(total)。
n.y /= (float) sqrt(總數)。
n.z /= (float) sqrt(total)。
}
return n;
}
uj5u.com熱心網友回復:
正如評論中指出的,你沒有正確地初始化你的四元數。
以下四元數不是旋轉:
rotate(angle,0,1, 1)
旋轉(angle,1,1, 0)
rotate(angle,1,0, 1)
原因是軸沒有被規范化,例如,矢量(0,1,1)沒有被規范化。還要確保你的角度是用弧度表示的。
uj5u.com熱心網友回復:
為了實作兩個旋轉的順序,你需要兩個基本旋轉的四元數乘積。每個基本的旋轉都由一個軸和一個角度來指定。但是在你的代碼中,你沒有確保你有一個用于軸的單位向量(方向向量)。
請做如下修改
四元數rotate(float w。float x, float y, float z) {
四元數n。
float f = 1/sqrtf(x*x y*y z*z)
n.w = cosf(w/2)。
n.x = f * x * sinf(w/2)。
n.y = f * y * sinf(w/2)。
n.z = f * z * sinf(w/2)。
return n。
}
然后按如下方式使用它
四元數n = rotate(angle1,1,0, 0) * rotate(angle2,0,1, 0)
對于angle1圍繞x軸的組合旋轉,以及angle2圍繞y軸的組合旋轉。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/319992.html
標籤:
上一篇:為什么輸出是16而不是11?
