原先快乐魔方的旋转采取的是这么一个方法:

glRotate(xAngle,1,0,0);   //绕x轴旋转xAngle

glRotate(yAngle,0,1,0);   //绕y轴旋转yAngle

其中,xAngle和yAngle如下计算

xAngle = y2 – y1; 

yAngle = x2 – x1;

(x1,y1)是down时的屏幕坐标,(x2,y2)是move时的屏幕坐标

这个方法的缺陷是:实际操作中,当绕x轴旋转-180度(触摸垂直向上移动)后,然后再绕y轴做逆时针旋转(触摸平行向右),你会发现魔方实际是做顺时针旋转,而不是期望的CCW。

 

解决这个问题的方法是Quaternion。

Quaternnion的定义:

Q = w + xi + yj + zk,这就是一种符号表示方法,具体定义见http://en.wikipedia.org/wiki/Quaternion#Definition

 

Quaternion可以应用在空间的旋转之中,假设:

v是1个三维向量(v1,v2,v3),我们理解为3维空间的1个点,也可以表示为1个quaternion(0,v1,v2,v3),那么点v绕向量u转w度可以这么计算

image

其中 q也是1个quaternion,定义为 image

v’取后面的3个数,即是空间点v旋转之后的新坐标。

 

如果Q1是第1次旋转,Q2是第2次旋转,那么Q=Q2*Q1表示先做Q1,再做Q2

Quaternion相乘计算如下:

(Q2* Q1).w = (w1w2 – x1x2 – y1y2 – z1z2)
(Q2* Q1).x = (w1x2 + x1w2 + y1z2 – z1y2)
(Q2 * Q1).y = (w1y2 – x1z2 + y1w2 + z1x2)
(Q2 * Q1).z = (w1z2 + x1y2 – y1x2 + z1w2

有了Q,可以将之转化为M,如此就可用glMultMatrix来建立ModelView Matrix,转化公式是:

w2+x2-y2-z2    2xy+2wz                   2xz-2wy                         0

2xy-2wz           w2-x2+y2-z2      2yz-2wx                         0

2xz+2wy           2yz-2wx            w2-x2-y2+z2           0

0                        0                        0                           1

 

参考:

  1. http://www.cprogramming.com/tutorial/3d/quaternions.html
  2. http://stackoverflow.com/questions/2758501
  3. Quaternions and spatial rotation
  4. 关于旋转的进一步解释
  5. Quaternion的3种运算:conjugation,reciprocal,norm