游戏开发之旅 3D数学学习 (1) 四元数的运用

为什么要用四元数?

首先,在一般的游戏引擎中,通常会以欧拉角作为物体旋转的参考或者操作物体旋转的手段。但是,众所周知,欧拉角虽然简单易懂,易于操作。但是,使用欧拉角进行游戏编写过程中,会遇到万向锁的情况,而四元数恰恰能帮我们解决这个问题。

  1. 无需担心万向锁问题
  2. 可以使用球面插值进行旋转
  3. 清晰简明的表达

如何理解四元数

我们都知道,如果你以前没有接触过四元数,那么初次使用会让你感觉到无从下手。
按笔者的理解,三维空间中的任何对象、参与者或向量都有一个方向,而四元数就是这样定义的。但与此同时,方向可以定义为从“零”方向到当前方向的旋转。它与向量相同,可以定义为空间中的某个位置或从“零”到该位置的位置增量或方向。

在UE4中,我们可以很轻松的获得某一个actor的四元数
FQuat currentQuat = GetOwner()->GetActorQuat();

一个例子

同时我们也可以旋转一个X轴单位向量
FVector forward = GetOwner()->GetActorQuat() * FVector(1.0f, 0.0f, 0.0f);
image

效果如上图,方块上的箭头为方框的正方向,旁边的箭头为独立的箭头,使用下面的代码控制。
FQuat currot = GetActorQuat();
FVector forward = currot * FVector(1,0,0);
ArrowComponent->SetWorldRotation(UKismetMathLibrary::MakeRotFromX(forward.GetSafeNormal()));

从0创建四元数

通常你不需要这样做,但是如果你需要,比如当你需要在Z轴上对对象应用90度顺时针旋转时,我们可以在UE4中实现如下:

  • 我们可以考虑向量X(1,0,0)和向量Y(0,1,0)
  • 在这两个向量之间找到旋转即为Yaw
  • 我们可以要求我们的引擎找到将第一个转换为第二个的四元数。它将是:
    FQuat quat = FQuat::FindBetween(vectorX, vectorY);

同时,我们要注意到在使用FindBetween的时候顺序问题
FindBetween(vectorY, vectorX); 结果是逆时针方向的
如果我想要一个48°的旋转呢?我们无法知道确切的向量,但是我们可以用四元数 × 浮点数得到我们想要的度数
48 / 90 约等于 0.53
quat = quat * 0.53f;
然后归一化
quat.Normalize();
这样我们就得到了一个48°的旋转

posted @ 2023-01-25 01:30  moonstoneG  阅读(447)  评论(0)    收藏  举报