杭州网站设计渠道,怎么设置网站标题,《网站开发实训》实验报告,抚州购物网站开发设计四元数如何用于 3D 旋转#xff08;代替欧拉角和旋转矩阵#xff09;
在三维空间中#xff0c;物体的旋转可以用 欧拉角、旋转矩阵 或 四元数 来表示。 四元数相比于欧拉角和旋转矩阵有 计算更高效、避免万向锁、存储占用少 等优点#xff0c;因此广泛用于 游戏开发、机器…四元数如何用于 3D 旋转代替欧拉角和旋转矩阵
在三维空间中物体的旋转可以用 欧拉角、旋转矩阵 或 四元数 来表示。 四元数相比于欧拉角和旋转矩阵有 计算更高效、避免万向锁、存储占用少 等优点因此广泛用于 游戏开发、机器人学、计算机图形学和航空航天 等领域。
四元数的定义
一个四元数 q 由四个实数组成 q w x i y j z k qwxiyjzk qwxiyjzk 其中w,x,y,z 是实数i,j,k 是虚单位满足特定的乘法规则
旋转的基本表示方式
方式表示方法优缺点欧拉角Euler Angles(α,β,γ) 对应绕 X, Y, Z 轴的旋转优点直观易理解和现实生活的旋转方式类似。缺点存在万向锁Gimbal Lock问题计算复杂。旋转矩阵Rotation Matrix3×3 矩阵优点适用于线性代数计算方便复合旋转。缺点需要存储 9 个值数值误差累积会导致非正交性。四元数Quaternionqwxiyjzk优点旋转计算简单存储更紧凑只需要 4 个数避免万向锁插值平滑。缺点不直观不容易手动调整。
旋转四元数的定义
一个 旋转四元数q 表示围绕单位向量 (x,y,z) 旋转角度 θ 的旋转 q cos θ 2 sin θ 2 ( x i y j z k ) q\cos\frac{\theta}{2}\sin\frac{\theta}{2}(x\mathbf{i}y\mathbf{j}z\mathbf{k}) qcos2θsin2θ(xiyjzk) 或写成向量形式 q ( cos θ 2 , x sin θ 2 , y sin θ 2 , z sin θ 2 ) q\left(\cos\frac{\theta}{2},x\sin\frac{\theta}{2},y\sin\frac{\theta}{2},z\sin\frac{\theta}{2}\right) q(cos2θ,xsin2θ,ysin2θ,zsin2θ) 其中θ 是旋转角度 (x,y,z) 是旋转轴必须是单位向量 (xi,yj,zk) 是四元数的虚部表示旋转方向 注意旋转四元数必须是单位四元数即满足 ∣ q ∣ w 2 x 2 y 2 z 2 1 |q|\sqrt{w^2x^2y^2z^2}1 ∣q∣w2x2y2z2 1
使用四元数进行 3D 旋转
假设有一个点 v ( v x , v y , v z ) \mathbf{v}(v_x,v_y,v_z) v(vx,vy,vz)我们想用四元数 q 旋转它。方法如下
将点转换为纯四元数虚部存储向量坐标 p ( 0 , v x , v y , v z ) p(0,v_x,v_y,v_z) p(0,vx,vy,vz)计算旋转后的点 p ′ q p q − 1 p^{\prime}qpq^{-1} p′qpq−1 其中 q − 1 q^{-1} q−1是四元数的逆单位四元数的逆就是它的共轭 旋转后的点 p ′ p^{\prime} p′也是一个纯四元数其中的虚部给出新坐标。单位四元数的逆 q − 1 q ∗ ( cos θ 2 , − x sin θ 2 , − y sin θ 2 , − z sin θ 2 ) q^{-1}q^*(\cos\frac{\theta}{2},-x\sin\frac{\theta}{2},-y\sin\frac{\theta}{2},-z\sin\frac{\theta}{2}) q−1q∗(cos2θ,−xsin2θ,−ysin2θ,−zsin2θ)
例程C语言
旋转 (1, 0, 0) 向量 绕 Y 轴旋转 90°。 计算后结果应该接近 (0, 0, -1)即 X 轴向量变成 Z 轴负方向。
#include stdio.h
#include math.h// 定义四元数结构体
typedef struct {double w, x, y, z;
} Quaternion;// 定义向量结构体
typedef struct {double x, y, z;
} Vector3;// 归一化四元数单位四元数
Quaternion normalize(Quaternion q) {double magnitude sqrt(q.w * q.w q.x * q.x q.y * q.y q.z * q.z);q.w / magnitude;q.x / magnitude;q.y / magnitude;q.z / magnitude;return q;
}// 计算四元数的共轭
Quaternion conjugate(Quaternion q) {Quaternion conj {q.w, -q.x, -q.y, -q.z};return conj;
}// 计算两个四元数的乘法
Quaternion multiply(Quaternion q1, Quaternion q2) {Quaternion result;result.w q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z;result.x q1.w * q2.x q1.x * q2.w q1.y * q2.z - q1.z * q2.y;result.y q1.w * q2.y - q1.x * q2.z q1.y * q2.w q1.z * q2.x;result.z q1.w * q2.z q1.x * q2.y - q1.y * q2.x q1.z * q2.w;return result;
}// 旋转向量 v 使用四元数 q
Vector3 rotate_vector(Vector3 v, Quaternion q) {Quaternion p {0, v.x, v.y, v.z}; // 将向量转换为纯四元数Quaternion q_conj conjugate(q); // 计算四元数共轭// 计算旋转后的四元数 p q * p * q^(-1)Quaternion temp multiply(q, p);Quaternion rotated multiply(temp, q_conj);// 结果的虚部即为旋转后的向量Vector3 result {rotated.x, rotated.y, rotated.z};return result;
}// 生成绕 (ux, uy, uz) 轴旋转 theta 角度的四元数
Quaternion from_axis_angle(double ux, double uy, double uz, double theta) {Quaternion q;double half_theta theta * M_PI / 360.0; // 角度转弧度并除以 2double sin_half_theta sin(half_theta);q.w cos(half_theta);q.x ux * sin_half_theta;q.y uy * sin_half_theta;q.z uz * sin_half_theta;return normalize(q);
}int main() {// 定义一个向量 (1, 0, 0)Vector3 v {1, 0, 0};// 绕 Y 轴旋转 90 度的四元数Quaternion q from_axis_angle(0, 1, 0, 90);// 旋转向量Vector3 rotated_v rotate_vector(v, q);// 输出旋转后的结果printf(旋转后向量: (%f, %f, %f)\n, rotated_v.x, rotated_v.y, rotated_v.z);return 0;
}代码解析
定义数据结构 Quaternion 结构体存储四元数w, x, y, z Vector3 结构体存储 3D 向量x, y, z归一化四元数 旋转四元数必须是 单位四元数所以 normalize() 函数保证四元数的模长为 1。计算四元数共轭 conjugate() 计算 对于单位四元数逆就是共轭。四元数乘法 multiply() 执行两个四元数的乘法用于计算旋转变换。向量旋转 rotate_vector() 采用公式 计算旋转后的向量。从轴-角度转换为四元数 from_axis_angle() 计算沿任意轴旋转 theta 角度的旋转四元数。
如预期原来的 (1, 0, 0) 经过 绕 Y 轴旋转 90° 后变成了 (0, 0, -1)