網(wǎng)上有很多四元數(shù)相關(guān)的文章。
百度百科 http://baike.baidu.com/view/319754.htm
某位的博客 http://caterpillar.onlyfun.net/Gossip/ComputerGraphics/QuaternionsRotate.htm
但當(dāng)你看完這些后。再看著下面這樣的代碼,你能快速回過神來么?
class CQuaternion


{
public:
CQuaternion(const float fScalar,const Vector3& rVec)

{
mVector=rVec ;
mScalar=fScalar;
}

void FromAxisAngle (const Vector3& rAxis, const F32 Angle)

{
F32 fSin, fCos;
//取得一個弧度角的SIN COS值
SinCos( Angle*0.5f, fSin, fCos);
mVector = rAxis*fSin;
mScalar = fCos;
}
private:
float mScalar;
float mVector;
}

class CMatrix44


{
public:

enum
{ _X_,_Y_,_Z_,_W_ };
void QuaternionToMatrix(const CQuaternion& q)

{
F32 s,xs,ys,zs,wx,wy,wz,xx,xy,xz,yy,yz,zz;
s = q.Length2();
s = (s>0 ? 2.f/s : 0);

xs = q.Vect[_X_]*s; ys = q.Vect[_Y_]*s; zs = q.Vect[_Z_]*s;
wx = q.Scalar*xs; wy = q.Scalar*ys; wz = q.Scalar*zs;
xx = q.Vect[_X_]*xs; xy = q.Vect[_X_]*ys; xz = q.Vect[_X_]*zs;
yy = q.Vect[_Y_]*ys; yz = q.Vect[_Y_]*zs; zz = q.Vect[_Z_]*zs;

(*this)[0].Set(1.f-(yy+zz),xy+wz, xz-wy, 0.f); // col 0
(*this)[1].Set(xy-wz, 1.f-(xx+zz),yz+wx, 0.f); // col 1
(*this)[2].Set(xz+wy, yz-wx, 1.f-(xx+yy),0.f); // col 2
}
//忽略其它無關(guān)緊要的
//、、、、、、、
};


//========================================================
不用多說,肯定有回過神來的,也有沒有回過神來的。
正如上面那某位的博客里面講到的。

對于旋轉(zhuǎn)軸A,繞其旋轉(zhuǎn)一定的角度,則可以表示為
x = s * Xa
y = s * Xb
z = s * Xc
w = cos(θ/2)
s = sin(θ/2)
這正是我們FromAxisAngle 所做的事情。
而QuaternionToMatrix則是對應(yīng)了
我想說明的是,數(shù)學(xué)庫本身并不在于代碼。而是在于數(shù)學(xué)公式,代碼僅是將其用另一種符號表示出來而已。只要仔細(xì)去看,定能明白其中的道理。
關(guān)于文中介紹的公式推導(dǎo)以及萬向鎖,可以GOOGLE和百度。
另外,編程中還經(jīng)常用到歐拉角和矩陣的轉(zhuǎn)換。
這三個的特點(diǎn)。
矩陣運(yùn)算的數(shù)據(jù)相對來說比較直觀,容易調(diào)試和診斷。但數(shù)據(jù)存儲量大,特別是旋轉(zhuǎn)的時候,會浪費(fèi)很多空間。
歐拉角儲存小,但有萬向鎖,并且插值不夠平滑。
四元數(shù)據(jù)量介于二者之間。但插值容易。
在骨骼動畫中,可以在文件中存儲歐拉角,加載后將旋轉(zhuǎn)數(shù)據(jù)轉(zhuǎn)換為四元數(shù)。最后動畫計(jì)算時統(tǒng)一采用矩陣運(yùn)算。
要說的東西很多,一言難盡。今天就到這里吧。