前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >UE5中四元数的旋转技巧

UE5中四元数的旋转技巧

作者头像
Jean
发布2021-09-07 11:23:02
2.8K0
发布2021-09-07 11:23:02
举报
文章被收录于专栏:Web行业观察Web行业观察

UE4_欧拉角

UE4中角度的表示通常为欧拉角

表示形式(X,Y,Z)

欧拉角在Lerp过程中起点和终点都是正确的,但是中间插值的过程是不够顺滑的

UE4的旋转计算过程是(Yaw[Z]→Pitch[Y]→Roll[X])

旋转角过渡:测试角度: 0,45,0旋转到 120,90,100【可以看到旋转绕了一圈】

UE4_万向锁

在欧拉角的情况下

当Y轴为90、-90的时候,X、Z轴旋转肉眼看上去是错误的,也就是万向锁问题

“欧拉角旋转”产生“万向锁”的来源,以及如何避免万向锁_哔哩哔哩_bilibiliwww.bilibili.com/video/BV1YJ41127qe?from=search&seid=15710488198256819120


UE4_四元数

四元数知识参考:

YivanLee:虚幻4渲染编程(数学篇)【第四卷:游戏中的旋转变换——四元数和欧拉角】50 赞同 · 1 评论文章

四元数可视化讲解:

四元数的可视化_哔哩哔哩_bilibiliwww.bilibili.com/video/BV1SW411y7W1

四元数也能表示旋转

四元数的表示形式(x,y,z,w)

旋转角过渡:测试角度: 0,45,0 旋转到 120,90,100【可以看到非常的平滑,直接就转过去了】

四元数的插值方式有线性插值和球面插值

四元数插值参考:

四元数定义、运算、插值_studylearnjava的博客-CSDN博客_四元数运算blog.csdn.net/studylearnjava/article/details/79978141

0.创建四元数

1.欧拉角怎么转换为四元数

UE4的C++和蓝图中都有欧拉角转四元数的方法;如果像自己实现的话可以参考第三种,或者看UE4的源码

代码语言:javascript
复制
FRotator r;
FQuat q = r.Quaternion();

或者

或者

代码语言:javascript
复制
struct Quaternion
{
    double w, x, y, z;
};

Quaternion ToQuaternion(double yaw, double pitch, double roll) // yaw (Z), pitch (Y), roll (X)
{
    // Abbreviations for the various angular functions
    double cy = cos(yaw * 0.5);
    double sy = sin(yaw * 0.5);
    double cp = cos(pitch * 0.5);
    double sp = sin(pitch * 0.5);
    double cr = cos(roll * 0.5);
    double sr = sin(roll * 0.5);

    Quaternion q;
    q.w = cy * cp * cr + sy * sp * sr;
    q.x = cy * cp * sr - sy * sp * cr;
    q.y = sy * cp * sr + cy * sp * cr;
    q.z = sy * cp * cr - cy * sp * sr;

    return q;
}

2.四元数/旋转体怎么线性插值

UE4C++中提供了四元数线性插值的方法、蓝图中提供了旋转体的简单插值节点,两种插值的效果是一样的

代码语言:javascript
复制
FQuat q1;   //起始旋转
FQuat q2;   //终点旋转
float f;    //插值参数
FQuat q3 = FQuat::FastLerp(q1, q2, f);

3.四元数/旋转体怎么球面插值【让物体或镜头平滑过渡/旋转】【推荐】

球面插值能做到角速度很平滑的旋转

UE4C++中也提供了四元数球面插值的方法、蓝图中旋转体插值节点启用最短路径,两种插值的效果一样

代码语言:javascript
复制
//c++
FQuat q1;   //起始旋转
FQuat q2;   //终点旋转
float f;    //插值参数
FQuat q3 = FQuat::Slerp(q1, q2, f);

4.四元数怎么转换为欧拉角

C++中也能直接进行转换,蓝图中一个节点自动完成转换,或者你可以用C++自己写

代码语言:javascript
复制
FQuat q1;
FRotator r = q1.Rotator();

或者【图中两种方法都可以】

或者

代码语言:javascript
复制
#define _USE_MATH_DEFINES
#include <cmath>
struct Quaternion {
    double w, x, y, z;
};

struct EulerAngles {
    double roll, pitch, yaw;
};

EulerAngles ToEulerAngles(Quaternion q) {
    EulerAngles angles;

    // roll (x-axis rotation)
    double sinr_cosp = 2 * (q.w * q.x + q.y * q.z);
    double cosr_cosp = 1 - 2 * (q.x * q.x + q.y * q.y);
    angles.roll = std::atan2(sinr_cosp, cosr_cosp);

    // pitch (y-axis rotation)
    double sinp = 2 * (q.w * q.y - q.z * q.x);
    if (std::abs(sinp) >= 1)
        angles.pitch = std::copysign(M_PI / 2, sinp); // use 90 degrees if out of range
    else
        angles.pitch = std::asin(sinp);

    // yaw (z-axis rotation)
    double siny_cosp = 2 * (q.w * q.z + q.x * q.y);
    double cosy_cosp = 1 - 2 * (q.y * q.y + q.z * q.z);
    angles.yaw = std::atan2(siny_cosp, cosy_cosp);

    return angles;
}

5.用欧拉角递增x/y/z轴(使用飞行模板,解决飞行器万向锁问题)

代码语言:javascript
复制
void UMyBlueprintFunctionLibrary::SetWorldRotationQuat(AActor* Actor, const FQuat& Target_Rotation)
{
    if (Actor)
    {
        Actor->SetActorRotation(Target_Rotation);
    }
}

void UMyBlueprintFunctionLibrary::SetRelativeRotationQuat(AActor* Actor, const FQuat& Target_Rotation)
{
    if (Actor)
    {
        
        Actor->SetActorRelativeRotation(Target_Rotation);
    }
}

void UMyBlueprintFunctionLibrary::AddLocalRotationQuat(AActor* Actor, const FQuat& DeltaRotation)
{
    if (Actor)
    {
        Actor->AddActorLocalRotation(DeltaRotation);
    }
}

6.其实自己也尝试了其他的旋转方案,发现都没有球面插值好,就不献丑了


物体围绕任意轴旋转【物体旋转的同时,会将一面永远朝向轴心】

思路:

1.获取物体A、中心B位置,计算向量BA;

2.向量BA旋转Ф角度加上中心B位置,得到新位置C;

3.设置原来物体A的到新位置C,和旋转增量Ф;

这是不修改物体与轴之间的距离

自定义物体与轴之间的距离

轴旋转节点

RotateVector / UnrotateVector

旋转向量 / 未旋转向量

向量A旋转B / 向量A反向旋转B

RotateVectorAroundAxis

围绕轴旋转向量

向量 A 绕着 Axis 轴旋转了 Angle Deg 度

Rotator from Axis and Angle

轴和角中的旋转体

以轴A经过Angle旋转后的旋转角

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-08-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 WebHub 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • UE4_欧拉角
  • UE4_四元数
  • 物体围绕任意轴旋转【物体旋转的同时,会将一面永远朝向轴心】
  • 轴旋转节点
    • RotateVector / UnrotateVector
      • RotateVectorAroundAxis
        • Rotator from Axis and Angle
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档