程序中的四元数表示法
网上有很多四元数相关的文章。
百度百科 http://baike.baidu.com/view/319754.htm
某位的博客 http://caterpillar.onlyfun.net/Gossip/ComputerGraphics/QuaternionsRotate.htm
但当你看完这些后。再看着下面这样的代码,你能快速回过神来么?
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
}
//忽略其它无关紧要的
//、、、、、、、
};
//========================================================
不用多说,肯定有回过神来的,也有没有回过神来的。
正如上面那某位的博客里面讲到的。
对于旋转轴A,绕其旋转一定的角度,则可以表示为
x = s * Xa
y = s * Xb
z = s * Xc
w = cos(θ/2)
s = sin(θ/2)
这正是我们FromAxisAngle 所做的事情。
而QuaternionToMatrix则是对应了
我想说明的是,数学库本身并不在于代码。而是在于数学公式,代码仅是将其用另一种符号表示出来而已。只要仔细去看,定能明白其中的道理。
关于文中介绍的公式推导以及万向锁,可以GOOGLE和百度。
另外,编程中还经常用到欧拉角和矩阵的转换。
这三个的特点。
矩阵运算的数据相对来说比较直观,容易调试和诊断。但数据存储量大,特别是旋转的时候,会浪费很多空间。
欧拉角储存小,但有万向锁,并且插值不够平滑。
四元数据量介于二者之间。但插值容易。
在骨骼动画中,可以在文件中存储欧拉角,加载后将旋转数据转换为四元数。最后动画计算时统一采用矩阵运算。
要说的东西很多,一言难尽。今天就到这里吧。
作者:麒麟子
出处:http://www.cnblogs.com/qilinzi/
蛮牛专栏:麒麟子
简介:麒麟子,编程15年,科技创始人,技术作家。
09年进入游戏行业,16年创立成都幼麟科技有限公司。十年从业经验练就了游戏全栈技能,目前专注于手机游戏领域。
版权声明:本文版权归作者和博客园共有,欢迎转载。转载必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。