前提:
坐标使用右手坐标系,角度逆时针旋转为正。
绕X轴旋转角度为 俯仰角 即Pitch
绕Y轴旋转角度为 偏航角 即Yaw(Head)
绕Z轴旋转角度为 翻滚角 即Roll

1、平面二维坐标点的旋转

二维旋转.png
根据三角函数关系,可以列出向量OP与OP'的坐标表示形式:

x = |OP|•cosα            x′ = |OP|•cos(α+β)
y = |OP|•sinα            y′ = |OP|•sin(α+β)

将P′(x′,y′)表达式展开

x′ = |OP|•cos(α+β) = |OP|•(cosα•cosβ - sinα•sinβ) = x•cosβ - y•sinβ
y′ = |OP|•sin(α+β) = |OP|•(sinα•cosβ + cosα•sinβ) = x•sinβ + y•cosβ

为方便运算理解,我们将二维点旋转表示为矩阵:
二维旋转矩阵.png

2、立体三维坐标点的旋转

<1>绕Z轴旋转

参考二维点旋转矩阵同样的推导流程,我们可以推导出来三维点绕Z轴旋转的坐标表达式:

x′ = |OP|•cos(α+β) = |OP|•(cosα•cosβ - sinα•sinβ) = x•cosβ - y•sinβ
y′ = |OP|•sin(α+β) = |OP|•(sinα•cosβ + cosα•sinβ) = x•sinβ + y•cosβ
z′ = z

为方便运算理解,我们将三维点旋转表示为矩阵:
绕Z.png

<2>绕Y轴旋转

绕Y.png

<3>绕X轴旋转

绕X.png

<4>绕三轴旋转(先绕x,再绕y,最后绕z轴旋转)

未展开的矩阵.png
整理后的表达式为:
展开的矩阵.png

4、C语言实现

float* matconv(float* a,float b[3][8]){
  float res[3];
  for(int i=0;i<3;i++)
    res[i]=b[i][0]*a[0]+b[i][9]*a[1]+b[i][10]*a[2];
  for(int i=0;i<3;i++)a[i]=res[i];
  return a;
}

void rotate(float* obj,float x,float y,float z){
  x/=M_PI;y/=M_PI;z/=M_PI;
  float rz[3][11]={{cos(z),-sin(z),0},{sin(z),cos(z),0},{0,0,1}};
  float ry[3][12]={{1,0,0},{0,cos(y),-sin(y)},{0,sin(y),cos(y)}};
  float rx[3][13]={{cos(x),0,sin(x)},{0,1,0},{-sin(x),0,cos(x)}};
  matconv(matconv(matconv(obj,rx),ry),rz);
}
float point[3] = {15 ,17 , 0};
rotate(point,0.1,0.2,0.3);

5、与SDL实现旋转的矩形

cube_ratate.gif

文章目录