Unreal 中的四元数 FQuat

本文介绍了四元数在三维空间中的应用,特别是如何通过四元数描述三维旋转,包括其与三维向量的关系、自乘规则的设定以及轴角到四元数的转换方法。文中给出了计算公式和虚幻引擎中的相关代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

四元数:Quaternion,四维数域内的数,可用于描述点在三维空间内的旋转(因为三维的旋转可以理解为绕某个轴旋转一个角度,所以需要4个维度的信息)
注意这里的旋转的轴,指的是从原点到 ( x , y , z ) (x,y,z) (x,y,z),也就是单纯的旋转信息,不包含位移信息(绕着不通过原点的线,可以先把点和轴平移,再旋转,再把点平移回去)

来源:

二元数: a + b i a+bi a+bi表示二维坐标系内的向量 v ⃗ = ( a , b ) \vec v =(a,b) v =(a,b),当这个向量为单位向量的时候,也可以表示为旋转这个操作,旋转的角度: θ = < ( 1 , 0 ) , v ⃗ > \theta = <(1,0),\vec v> θ=<(1,0),v >。例如:
v ⃗ = ( 1 , 0 ) n = 3 2 + 1 2 i ,表示逆时针旋转 3 0 ∘ v ⃗ ∗ n = 3 2 + 1 2 i ( 3 0 ∘ ) v ⃗ ∗ n ∗ n = 1 2 + 3 2 i ( 6 0 ∘ ) v ⃗ ∗ n ∗ n ∗ n = 0 + 1 i ( 9 0 ∘ ) v ⃗ ∗ n ∗ n ∗ n ∗ n = − 1 2 + 3 2 i ( 12 0 ∘ ) . . . \vec v = (1,0) \\ n = \frac{\sqrt 3}{2}+\frac{1}{2}i,表示逆时针旋转30^\circ\\ \vec v *n=\frac{\sqrt 3}{2}+\frac{1}{2}i (30^\circ)\\ \vec v *n*n=\frac{1}{2}+\frac{\sqrt 3}{2}i(60^\circ)\\ \vec v *n*n*n=0+1i(90^\circ)\\ \vec v *n*n*n*n=-\frac{1}{2}+\frac{\sqrt 3}{2}i(120^\circ)\\ ... v =(1,0)n=23 +21i,表示逆时针旋转30v n=23 +21i30v nn=21+23 i60v nnn=0+1i90v nnnn=21+23 i120...

那三维坐标系内呢?假设定义三元数: a + b i + c j a+bi+cj a+bi+cj,表示三维向量 v ⃗ = ( a , b , c ) \vec v =(a,b,c) v =(a,b,c),同时表示一个三维空间的旋转,那么自乘的结果内,有一项为 2 b c ∗ i j 2bc*ij 2bcij。而数学家无法给这个 i j ij ij设定一个值完成逻辑自洽(例如 i ∗ i = − 1 i*i=-1 ii=1)。
为了完成逻辑自洽,引入了 k = i j k=ij k=ij,也就是变成了四元数: q = a + b i + c j + d k q=a+bi+cj+dk q=a+bi+cj+dk,同时加上以下设定:(不满足交换律)

i × j = k j × k = i k × i = j j × i = − k k × j = − i i × k = − j i × j × k = k × k = − 1 i\times j=k\\ j\times k=i\\ k\times i=j\\ j\times i=-k\\ k\times j=-i\\ i\times k=-j\\ i\times j\times k=k\times k=-1 i×j=kj×k=ik×i=jj×i=kk×j=ii×k=ji×j×k=k×k=1
这样子,我们就可以让乘法的结果也是 a + b i + c j + d k a+bi+cj+dk a+bi+cj+dk

在这里插入图片描述

几何意义:

定义四元数 q = a + b i + c j + d k q=a+bi+cj+dk q=a+bi+cj+dk,参考二元数的共轭值定义, q ∗ = a − b i − c j − d k q^*=a-bi-cj-dk q=abicjdk

轴为 n ⃗ = ( x , y , z ) \vec n=(x,y,z) n =(x,y,z),角为 θ \theta θ时,可以推出各个系数为(系数推理参考):
a = c o s θ 2 ( F Q u a t : : W ) b = s i n θ 2 x ( F Q u a t : : X ) c = s i n θ 2 y ( F Q u a t : : Y ) d = s i n θ 2 z ( F Q u a t : : Z ) a=cos\frac{\theta}{2} (FQuat::W)\\ b=sin\frac{\theta}{2}x(FQuat::X)\\ c=sin\frac{\theta}{2}y(FQuat::Y)\\ d=sin\frac{\theta}{2}z(FQuat::Z) a=cos2θFQuat::Wb=sin2θxFQuat::Xc=sin2θyFQuat::Yd=sin2θzFQuat::Z

参考虚幻的轴角转化为四元数的代码:

template<typename T>
FORCEINLINE TQuat<T>::TQuat(TVector<T> Axis, T AngleRad)
{
	const T half_a = 0.5f * AngleRad;
	T s, c;
	FMath::SinCos(&s, &c, half_a);

	X = s * Axis.X;
	Y = s * Axis.Y;
	Z = s * Axis.Z;
	W = c;

	DiagnosticCheckNaN();
}

对于一个点 p ( x , y , z ) p(x,y,z) p(x,y,z),使其绕 n ⃗ \vec n n 逆时针旋转 θ \theta θ

  • 按照上文得出 q = c o s θ 2 + s i n θ 2 i + s i n θ 2 j + s i n θ 2 k q=cos\frac{\theta}{2}+sin\frac{\theta}{2}i+sin\frac{\theta}{2}j+sin\frac{\theta}{2}k q=cos2θ+sin2θi+sin2θj+sin2θk
  • 将虚部记为 v ⃗ \vec v v ,实部记为 w w w,即: q = w + v ⃗ q=w+\vec v q=w+v
  • 使用公式(推理参考 p ′ = p + 2 w ( v × q ) + 2 v × ( v × q ) p' = p + 2w(v \times q) + 2v \times (v \times q) p=p+2w(v×q)+2v×(v×q)

参考虚幻的旋转代码:

template<typename T>
FORCEINLINE TVector<T> TQuat<T>::RotateVector(TVector<T> V) const
{	
	const TVector<T> Q(X, Y, Z);
	const TVector<T> TT = 2.f * TVector<T>::CrossProduct(Q, V);
	const TVector<T> Result = V + (W * TT) + TVector<T>::CrossProduct(Q, TT);
	return Result;
}

参考:
Some Notes on Unit Quaternions and Rotation
中文维基
四元数和旋转(Quaternion & rotation)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值