UE4解决万向锁问题

回眸只為那壹抹淺笑 提交于 2020-01-17 02:29:22

目录

万向锁的来源

简单而言,万向锁就是由于物体在进行旋转时(前提是通过欧拉角进行旋转),当旋转到某个特定角度会导致两个旋转轴处于同一个平面,导致旋转不能到达自己的预期效果,产生这种现象的原因是因为轴与轴之间存在父子关系。

视频展示链接: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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!