目录
万向锁的来源
简单而言,万向锁就是由于物体在进行旋转时(前提是通过欧拉角进行旋转),当旋转到某个特定角度会导致两个旋转轴处于同一个平面,导致旋转不能到达自己的预期效果,产生这种现象的原因是因为轴与轴之间存在父子关系。
视频展示链接:https://www.bilibili.com/video/av76536794/
Unity中最简单的万向锁
将x轴设为90度,旋转y轴和旋转z轴有相同效果
UE4最简单万向锁
将y轴设为90度,旋转x轴和旋转z轴有相同效果
旋转角度为0时:
绕y轴旋转90度时:
x轴和z轴的值都奇怪的变成了180度,或者当y轴设为90度时,旋转x轴和z轴效果相同,
解决方案
1 使用x轴旋转代替y轴旋转,首先将z值设置为90度,然后旋转x轴即可产生绕y轴旋转的效果
不过此方案只适用于比较规则的物体,如长方体,正方体
2 使用四元数旋转来代替欧拉角
四元数与欧拉角之间的转换
四元数的定义
四元数与欧拉角的转换
下面展示使用UE4,通过四元数处理物体旋转的代码:
// An highlighted block
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "RotationByQuaternion.generated.h"
/**
*
*/
UCLASS()
class TWODTEST_API URotationByQuaternion : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
UFUNCTION(BlueprintCallable, meta = (DisplayName = "Euler To Quaternion", keywords = "rotation,quaterion"), Category = "Quaternion Rotation")
static FQuat Euler_To_Quaternion(FRotator Current_Rotation);
UFUNCTION(BlueprintCallable, meta = (DisplayName = "Set World Rotation", keywords = "rotation,quaterion"), Category = "Quaternion Rotation")
static void SetWorldRotationQuat(USceneComponent *SceneComponent, const FQuat &Target_Rotation);
UFUNCTION(BlueprintCallable, meta = (DisplayName = "Set Relative Rotation", keywords = "rotation,quaterion"), Category = "Quaternion Rotation")
static void SetRelativeRotationQuat(USceneComponent *SceneComponent, const FQuat &Target_Rotation);
UFUNCTION(BlueprintCallable, meta = (DisplayName = "AddLocalRotationQuat", keywords = "rotation,quaterion"), Category = "Quaternion Rotation")
static void AddLocalRotationQuat(USceneComponent *SceneComponent,const FQuat &DeltaRotation);
};
// An highlighted block
// Fill out your copyright notice in the Description page of Project Settings.
#include "RotationByQuaternion.h"
#include "Math/Quat.h"
FQuat URotationByQuaternion::Euler_To_Quaternion(FRotator Current_Rotation)
{
FQuat q;
float yaw = Current_Rotation.Yaw*PI / 180;
float roll = Current_Rotation.Roll*PI / 180;
float pitch = Current_Rotation.Pitch*PI / 180;
double cy = cos(yaw*0.5);
double sy = sin(yaw*0.5);
double cr = cos(roll*0.5);
double sr = sin(roll*0.5);
double cp = cos(pitch*0.5);
double sp = sin(pitch*0.5);
q.W = cy * cr*cp + sy * sr*sp;
q.X = cy * sr*cp - sy * cr*sp;
q.Y = cy * cr*sp + sy * sr*cp;
q.Z = sy * cr*cp - cy * sr*sp;
return q;
}
void URotationByQuaternion::SetWorldRotationQuat(USceneComponent * SceneComponent, const FQuat & Target_Rotation)
{
if (SceneComponent)
{
SceneComponent->SetWorldRotation(Target_Rotation);
}
}
void URotationByQuaternion::SetRelativeRotationQuat(USceneComponent * SceneComponent, const FQuat & Target_Rotation)
{
if (SceneComponent)
{
SceneComponent->SetRelativeRotation(Target_Rotation);
}
}
void URotationByQuaternion::AddLocalRotationQuat(USceneComponent * SceneComponent, const FQuat & DeltaRotation)
{
if (SceneComponent)
{
SceneComponent->AddLocalRotation(DeltaRotation);
}
}
参考链接
https://blog.csdn.net/AndrewFan/article/details/60981437
https://blog.csdn.net/u012700322/article/details/52252305
来源:CSDN
作者:绿洲守望者
链接:https://blog.csdn.net/qq_36696486/article/details/103953039