OGRE中的四元数与旋转

想象一个物体在3D空间中移动的过程,该物体必然会涉及到旋转。例如一个怪物,他的运动方向会改变,要改变其方向只需要对其进行旋转即可。

旋转的方式大致分为三种:Euler旋转,矩阵旋转,以及四元数旋转。

这里稍微记录下我目前对于四元数旋转的理解。对于四元数方面的数学,以及其原理,这里不关心,只需要学会如何使用即可。

无论是哪一种旋转,物体与该物体的局部坐标系之间的相对位置,相对方位都是不会改变的。因此,在进行两个局部旋转(即相对于局部坐标系)时,要注意结果可能不是你预期的。

对于Euler旋转,OGRE中为SceneNode提供了yaw, pitch, roll之类的接口。这些接口默认都是参照局部坐标系旋转,可以通过第二个参数来指定,例如 yaw( Degree( 90 ), SceneNode::TS_WORLD );

OGRE中的Quaternion类用于四元数处理。该类(也可以说是四元数本身)有四个成员:x,y,z,w。这四个数分别代表什么?

在OGRE论坛上我找到了一些可以让人很容易理解的信息:

Quaternions can seem pretty daunting because of the use of 'imaginary' numbers. It's much easier to understand if you just ignore this concept completely. The basic formula for creating a quaternion from angle/axis is:


Q = cos (angle/2) + i (x * sin(a/2)) + j (y * sin(a/2)) + k(z * sin(a/2))


or

Code:


Q.w = cos (angle / 2)

Q.x = axis.x * sin (angle / 2)

Q.y = axis.y * sin (angle / 2)

Q.z = axis.z * sin (angle / 2)

稍微忽略下那些复数之类的概念,使用角度/轴的方式创建四元数的公式为:

Q = cos (angle/2) + i (x * sin(a/2)) + j (y * sin(a/2)) + k(z * sin(a/2))


对应的代码为:

Q.w = cos (angle / 2)

Q.x = axis.x * sin (angle / 2)

Q.y = axis.y * sin (angle / 2)

Q.z = axis.z * sin (angle / 2)


再看一下OGRE中关于Quaternion的一个构造四元数的函数源代码:

void Quaternion::FromAngleAxis (const Radian& rfAngle,

const Vector3& rkAxis)

{

// assert: axis[] is unit length

//

// The quaternion representing the rotation is

// q = cos(A/2)+sin(A/2)*(x*i+y*j+z*k)


Radian fHalfAngle ( 0.5*rfAngle );

Real fSin = Math::Sin(fHalfAngle);

w = Math::Cos(fHalfAngle);

x = fSin*rkAxis.x;

y = fSin*rkAxis.y;

z = fSin*rkAxis.z;

}


虽然可以说四元数中的w代表旋转量,x, y, z代表对应轴,但是这也不全正确。因为我们看到,对于真正的旋转量啊之类的数据,是需要进行有些公式变换后,才得到w, x, y, z 的。

但是,即使如此,我们还是可以这样简单地构造一个四元数用于旋转:

Quaternion q( Degree( -90 ), Vector3::UNIT_X );

该构造函数第一个参数指定旋转角度,第二个参数指定旋转轴(可能不是),上面的代码就表示,饶着X轴(正X方向),旋转-90度。将该四元数用于一个Scene Node旋转:

sceneNode->rotate( q );

即可实现该node饶X轴旋转-90度的效果。


再看一下OGRE tutorial中的一段代码:

Vector3 src = mNode->getOrientation() * Vector3::UNIT_X;

Ogre::Quaternion quat = src.getRotationTo(mDirection);

mNode->rotate(quat);

SceneNode的getOrientation获得该node的方位,用一个四元数来表示。什么是方位?这里我也不清楚,但是对于一个四元数,它这里表示的是一种旋转偏移,偏移于初始朝向。

OGRE论坛上有这么一段话:

The reason there's no other way to convert a quaternion to a vector is because a quaternion is relative. It has no direction.

With a direction (like a vector) you could say "face north east".

But with a quaternion, you say "face 45 degrees clockwise from whatever direction you are already facing" (very simplified example). Without knowing which way the object is already facing, a quaternion is virtually meaningless with respect to orientation. So we just default it to some initial direction, like Unit Z, and make all orientations relative to that.

然后,getOrientation() * Vector3::UINT_X又会得到什么?我可以告诉你,第一句代码整体的作用就是获取该物体当前面向的方向。

posted on 2009-09-15 10:17  leonwei  阅读(219)  评论(0编辑  收藏  举报