相关主题: OpenGL 矩阵、四元数到矩阵、角度到轴、观察到轴
目录
- 一、说明
- 二、罗德里格斯公式的推导
- 2.1 空间点旋转问题
- 2.2 对旋转问题的分析
- 三、罗德里格斯旋转公式矩阵表示:
- 四、最小C++代码
- 五、结论
一、说明
解决三维坐标下的刚体旋转问题,欧拉角存在缺陷,当旋转点落在坐标轴上,旋转公式失灵。围绕任意轴旋转的点3d变换,正规公式是罗德里格斯矩阵。本篇专门介绍它的推导过程,而且提供C++的示例代码。
二、罗德里格斯公式的推导
2.1 空间点旋转问题
三维笛卡尔坐标下,我们设定任意向量OR为轴,空间任意点P,让P围绕OR做圆周运动,那么P在任意时刻的坐标是什么?我们用罗德里格斯公式可以方便实现,问题是罗德里格斯公式如何导出?这是我们本文的主题。
OpenGL中绕任意轴旋转的4x4变换矩阵定义为:
2.2 对旋转问题的分析
用于绕任意轴旋转的 4x4 矩阵
本页说明如何使用罗德里格斯公式导出此旋转矩阵。假设 3D空间点P围绕单位向量 r → = ( x , y , z ) \overrightarrow{r} =(x,y,z) r=(x,y,z)旋转 θ \theta θ角到达Q点。
P 的向量形式分解为 O R → \overrightarrow{OR} OR和 R P → \overrightarrow{RP} RP和 的向量和,Q 分别为向量 O R → \overrightarrow{OR} OR和$\overrightarrow{RQ} 的和。
设向量 p → = O R → + R P → \overrightarrow{p}=\overrightarrow{OR}+ \overrightarrow{RP} p=OR+RP ,向量 q → = O R → + R Q → \overrightarrow{q}=\overrightarrow{OR}+ \overrightarrow{RQ} q=OR+RQ
因此,我们需要先求向量 O R → \overrightarrow{OR} OR和向量 R Q → \overrightarrow{RQ} RQ才能得到 Q。矢量向量 O R → \overrightarrow{OR} OR可以从 r → \overrightarrow{r} r和 p → \overrightarrow{p} p向量中求出.并且向量RQ来自 Q 点所在的圆平面。向量 O R → \overrightarrow{OR} OR与单位向量 r → \overrightarrow{r} r平行,其长度可以通过投影使用内积来向量OR计算。所以,可以写成; O R → = ( p → ⋅ r → ) r → \overrightarrow{OR}= (\overrightarrow{p} \cdot \overrightarrow{r})\overrightarrow{r} OR=(p⋅r)r
向量 R Q → \overrightarrow{RQ} RQ可以由旋转平面上的2个基本向量确定。我们使用矢量 R P → \overrightarrow{RP} RP作为第一个基向量,另一个基向量矢量 R S → \overrightarrow{RS} RS 垂直于圆平面内矢量 R P → \overrightarrow{RP} RP且长度相等,因为它们都是圆平面的半径。因此,矢量 R S → \overrightarrow{RS} RS可以通过 2 个垂直向量的叉积来计算;矢量 r → \overrightarrow{r} r和矢量 R P → \overrightarrow{RP} RP;
现在,向量RQ用这些基向量和三角函数的组合来表示;
最后,旋转后向量向量 q → \overrightarrow{q} q 由向量 O R → \overrightarrow{OR} OR和写成向量 R Q → \overrightarrow{RQ} RQ;
这个方程称为罗德里格斯旋转公式;
罗德里格斯旋转公式
三、罗德里格斯旋转公式矩阵表示:
It can be represented by an equivalent matrix form. First, convert vector OR and vector RS components to 3x3 matrix forms for P = (px, py, pz) and r = (x, y, z);
罗德里格斯旋转公式可以用矩阵表示,首先,将 O R → \overrightarrow{OR} OR
和 R S → \overrightarrow{RS} RS构成3x3矩阵形式, P → = ( p x , p y , p z ) \overrightarrow{P}=(p_x,p_y,p_z) P=(px,py,pz) P = (px, py, pz) 和 r = ( x , y , z ) r = (x, y, z) r=(x,y,z);
可以用等价矩阵形式表示。首先,将向量或和矢量RS分量转换为 3x3 矩阵形式,其中 P = (p x , p y , p z ) 和 r = (x, y, z);
也将罗德里格斯旋转公式写成矩阵方程:
旋转矩阵:
或者4x4矩阵:
四、最小C++代码
// minimal implementation of Vector3
struct Vector3
{float x, y, z;// ctorVector3() : x(0), y(0), z(0) {}// inner and cross productsfloat dot(Vector3& v) { return x*v.x + y*v.y + z*v.z; }Vector3 cross(Vector3& v) { return Vector3(y*v.z-z*v.y, z*v.x-x*v.z, x*v.y-y*v.x); }// scalar productfriend Vector3 operator*(float s, Vector3 v) { return Vector3(s*v.x, s*v.y, s*v.z); }Vector3& normalize() {float invLength = 1.0f / sqrtf(x*x + y*y + z*z);x *= invLength;y *= invLength;z *= invLength;return *this;}
}
...// define the rotation vector r and angle
Vector3 r = Vector3(1, 1, 1).normalize(); // make unit length
float a = 30 / 180 * PI; // rotation angle as radian// define a vector p to rotate
Vector3 p = Vector3(1, 2, 3);// compute the rotated vector q using Rodrigues' formula
Vector3 q = (1 - cos(a)) * p.dot(r) * r + cos(a) * p + sin(a) * r.cross(p);
五、结论
我们在这里介绍一个绕任意向量旋转的公式;还有一个有效方法是四元组旋转向量,它是任意球面上的两点,通过大圆旋转的问题。将在另一个文中介绍,请大家关注。