四元数入门

四元数常常可以在3D的书上看到。
但我的那本3D图形学书上,在没讲四元数是干什么的之前,就列了几张纸的公式,
大概因为自己还在上高中,不知道的太多,看了半天没看懂。。。
终于,在gameres上看到了某强人翻译的一个“4元数宝典 ”(原文是日本人写的。。。),感觉很好,分享下。

★旋转篇:
 我将说明使用了四元数(si yuan shu, quaternion)的旋转的操作步骤
)四元数的虚部,实部和写法
所谓四元数,就是把4个实数组合起来的东西。
4个元素中,一个是实部,其余3个是虚部。
比如,叫做Q的四元数,实部t而虚部是x,y,z构成,则像下面这样写。
=  (t; x, y, z) 
又,使用向量 V
= (x,y,z),
=  (t; V)  
也可以这么写。

正规地用虚数单位i,j,k的写法的话,
=  t  +  xi  +  yj  +  zk 
也这样写,不过,我不大使用

)四元数之间的乘法
虚数单位之间的乘法 
ii 
=   - 1 , ij  =   - ji  =  k (其他的组合也是循环地以下同文) 
有这么一种规则。(我总觉得,这就像是向量积(外积),对吧) 
用这个规则一点点地计算很麻烦,所以请用像下面这样的公式计算。

=  (a; U) 
=  (b; V) 
AB 
=  (ab  -  U·V; aV  +  bU  +  U×V)
不过,“U·V”是内积,「U×V」是外积的意思。
注意:一般AB
<> BA所以乘法的左右要注意!

3 )3次元的坐标的四元数表示
如要将某坐标(x,y,z)用四元数表示,
=  ( 0 ; x, y, z) 
则要这么写。
 
另外,即使实部是零以外的值,下文的结果也一样。用零的话省事所以我推荐。

)旋转的四元数表示
以原点为旋转中心,旋转的轴是(α, β, γ)
(但 α
^ 2   +  β ^ 2   +  γ ^ 2   =   1 ), 
(右手系的坐标定义的话,望向向量(α, β, γ)的前进方向反时针地) 
转θ角的旋转,用四元数表示就是,
=  (cos(θ / 2 ); α sin(θ / 2 ), β sin(θ / 2 ), γ sin(θ / 2 )) 
=  (cos(θ / 2 );  - α sin(θ / 2 ),  - β sin(θ / 2 ),  - γ sin(θ / 2 )) 
(另外R 叫 Q 的共轭四元数。) 

那么,如要实行旋转,
则 R P Q 
= (0 ; 答案) 

请像这样三明治式地计算。这个值的虚部就是旋转之后的点的坐标值。
 (另外,实部应该为零。请验算看看) 

例子代码

///  Quaternion.cpp 
///  (C) Toru Nakata, toru-nakata@aist.go.jp 
///  2004 Dec 29 
  
#include 
< math.h >  
#include 
< iostream.h >  
  
///  Define Data type 
typedef  struct  

              
double  t;  //  real-component 
               double  x;  //  x-component 
               double  y;  //  y-component 
               double  z;  //  z-component 
} quaternion; 
  

//// Bill 注:Kakezan 在日语里是 “乘法”的意思
quaternion Kakezan(quaternion left, quaternion right) 

              quaternion ans; 
              
double  d1, d2, d3, d4; 
  
              d1 
=   left.t  *  right.t; 
              d2 
=   - left.x  *  right.x; 
              d3 
=   - left.y  *  right.y; 
              d4 
=   - left.z  *  right.z; 
              ans.t 
=  d1 +  d2 +  d3 +  d4; 
  
              d1 
=   left.t  *  right.x; 
              d2 
=   right.t  *  left.x; 
              d3 
=   left.y  *  right.z; 
              d4 
=   - left.z  *  right.y; 
              ans.x 
=   d1 +  d2 +  d3 +  d4; 
  
              d1 
=   left.t  *  right.y; 
              d2 
=   right.t  *  left.y; 
              d3 
=   left.z  *  right.x; 
              d4 
=   - left.x  *  right.z; 
              ans.y 
=   d1 +  d2 +  d3 +  d4; 
  
              d1 
=   left.t  *  right.z; 
              d2 
=   right.t  *  left.z; 
              d3 
=   left.x  *  right.y; 
              d4 
=   - left.y  *  right.x; 
              ans.z 
=   d1 +  d2 +  d3 +  d4; 
              
              
return  ans; 

  
/// / Make Rotational quaternion 
quaternion MakeRotationalQuaternion( double  radian,  double  AxisX,  double  AxisY,  double  AxisZ) 

              quaternion ans; 
              
double  norm; 
              
double  ccc, sss; 
              
              ans.t 
=  ans.x  =  ans.y  =  ans.z  =   0.0
  
              norm 
=  AxisX  *   AxisX  +   AxisY  *   AxisY  +   AxisZ  *   AxisZ; 
              
if (norm  <=   0.0 return  ans; 
  
              norm 
=   1.0   /  sqrt(norm); 
              AxisX 
*=  norm; 
              AxisY 
*=  norm; 
              AxisZ 
*=  norm; 
  
              ccc 
=  cos( 0.5   *  radian); 
              sss 
=  sin( 0.5   *  radian); 
  
              ans.t 
=  ccc; 
              ans.x 
=  sss  *  AxisX; 
              ans.y 
=  sss  *  AxisY; 
              ans.z 
=  sss  *  AxisZ; 
  
              
return  ans; 

  
/// / Put XYZ into  quaternion 
quaternion PutXYZToQuaternion( double  PosX,  double  PosY,  double  PosZ) 

              quaternion ans; 
  
              ans.t 
=   0.0
              ans.x 
=  PosX; 
              ans.y 
=  PosY; 
              ans.z 
=  PosZ; 
  
              
return  ans; 

  
/// // main 
int  main() 

              
double  px, py, pz; 
              
double  ax, ay, az, th; 
              quaternion ppp, qqq, rrr; 
  
              cout 
<<   " Point Position (x, y, z)  "   <<  endl; 
              cout 
<<   "   x =  "
              cin 
>>  px; 
              cout 
<<   "   y =  "
              cin 
>>  py; 
              cout 
<<   "   z =  "
              cin 
>>  pz; 
              ppp 
=  PutXYZToQuaternion(px, py, pz); 
  
              
while ( 1 ) { 
                            cout 
<<   " /nRotation Degree ? (Enter 0 to Quit)  "   <<  endl; 
                            cout 
<<   "   angle =  "
                            cin 
>>  th; 
                            
if (th  ==   0.0 break
  
                            cout 
<<   " Rotation Axis Direction ? (x, y, z)  "   <<  endl; 
                            cout 
<<   "   x =  "
                            cin 
>>  ax; 
                            cout 
<<   "   y =  "
                            cin 
>>  ay; 
                            cout 
<<   "   z =  "
                            cin 
>>  az; 
  
  
                            th 
*=   3.1415926535897932384626433832795   /   180.0 ///  Degree -> radian; 
  
                            qqq 
=  MakeRotationalQuaternion(th, ax, ay, az); 
                            rrr 
=  MakeRotationalQuaternion( - th, ax, ay, az); 
  
                            ppp 
=  Kakezan(rrr, ppp); 
                            ppp 
=  Kakezan(ppp, qqq); 
  
                            cout 
<<   " /nAnser X =  "   <<  ppp.x 
                                          
<<    " /n      Y =  "   <<  ppp.y 
                                          
<<    " /n      Z =  "   <<  ppp.z  <<  endl; 
  
              } 
  
              
return   0
}  
http://staff.aist.go.jp/toru-nakata/quaternion.html
http://bbs.gameres.com/showthread.asp?threadid=73511
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值