언리얼엔진을 통한 드론을 구현하던 중, 마우스 X,Y에 대한 값을 입력받아 각각 Yaw와 Pitch를 회전하는 로직을 구현했습니다.

해당 방식에서는 bUseControllerRotationYaw,Pitch = true를 설정하여 컨트롤러 입력에 따른 Pawn이 회전 할 수 있도록 AddActorLocalRotation() 함수를 사용하였습니다.

제가 의도한 결과는 마우스 입력에 따른 Pawn이 각각 Pitch,Yaw만 움직이게 하는것입니다.

 

그러나 실행 결과는 Roll이 값이 같이 회전하는 문제가 발생하여 이러한 문제가 어떤것인지 학습하였습니다.

학습 결과 이러한 현상을 짐벌 락(Gimbal Lock)이라고 할 수 있으며, 이러한 문제가 발생한 이유에 대해 알아보았습니다.

 

이번 포스팅에서는 오일러 각과 짐벌 락, 해결방법 등에 대해 알아보겠습니다.

 

오일러각

Euler - Wikipedia

  • 3D회전을 세가지 축(X,Y,Z)을 기준으로 나눠서 표현하는 방식
  • 언리얼 엔진 내부에서 최종 업데이트시 행렬을 사용하는 것을 직관적이고 효율적으로 사용하기위해
    • 기존의 회전 행렬은 추가 데이터 요구 및 계산량이 많다.
  • Roll  (X축 회전)
  • Pitch(Y축 회전)
  • Yaw (Z축 회전)
  • X,Y,Z 세가지 축을 순서대로 돌린 각도의 정보를 저장하여 3개의 숫자로 표현하는 방식
  • 회전 각도를 숫자 (0~360 / -180 ~ 180)으로 표현하여 직관적이다.
  • 오일러 각의 회전 순서에 따라 다른 결과가 나올 수 있다.

오일러 각의 적용 순서

  • 오일러 각은 한번에 적용되는것이 아닌, 각 표전 기저 벡터 축을 중심으로 독립적으로 일어나는 회전
  • 3가지 축에 적용 순서를 어떠한 순서로 적용할 지에 따라 6가지의 경우의 수가 있다.
    • Yaw -> Pitch -> Roll
    • Yaw -> Roll -> Pitch
    • Pitch -> Roll -> Yaw
    • Pitch -> Yaw -> Roll
    • Roll -> Yaw -> Pitch
    • Roll -> Pitch -> Yaw
  • 언리얼 엔진 : Yaw -> Roll -> Pitch 순서의 각 적용
    • 실제 연산 순서 : Pitch -> Yaw -> Roll
    • FQuat(쿼터니언)은 축과 각도를 한번에 표현하여 회전 순서와 무관하게 정확한 회전 제공
  • 적용 순서에 따라 축이 변경되며, 최종 회전 방향 적용 순서에 따라 결과가 다르다.

 

FRotator : Engine/Source/Runtime/Core/Public/Math/Rotate.h

struct TRotator
{

	// Can't have a UE_REQUIRES in the declaration because of the forward declarations, so check for allowed types here.
	static_assert(std::is_floating_point_v<T>, "TRotator only supports float and double types.");

public:
	using FReal = T;

	/** Rotation around the right axis (around Y axis), Looking up and down (0=Straight Ahead, +Up, -Down) */
	T Pitch;

	/** Rotation around the up axis (around Z axis), Turning around (0=Forward, +Right, -Left)*/
	T Yaw;

	/** Rotation around the forward axis (around X axis), Tilting your head, (0=Straight, +Clockwise, -CCW) */
	T Roll;

 

언리얼 엔진의 실제 연산 순서 : Engine/.../Math/UnrealMath.cpp

template<typename T>
UE::Math::TRotator<T> UE::Math::TRotator<T>::MakeFromEuler(const UE::Math::TVector<T>& Euler)
{
	return UE::Math::TRotator<T>(Euler.Y, Euler.Z, Euler.X);
}



 

 

 

짐벌락

짐벌(Gimbal)

Gimbal - Wikipedia

  • 물체가 회전하도록 중심축을 가진 구조물
  • 3차원 공간에 놓인 강체의 방향은 오일러 각도를 사용하여 세번의 회전을 통해 얻을 수 있다.

 

짐벌락(Gimbal Lock)

  • 오일러 각을 사용한 회전 중 두 개 또는 세개의 축이 겹치게되어 회전각이 소실되는 상황
  • 특정 방향으로 회전하려고 할 때 의도하지 않은 회전이 발생하거나, 특정 방향으로의 회전이 불가능해지는 문제
  • 고리가 다른 고리에 자식으로 붙어있는 관계이기때문에 각 축은 서로 종속적이다.

 

짐벌락 발생 예시

  1. 초기상태 (Yaw 30, Pitch 45, Roll 0)
  2. Pitch += 90 회전 (Yaw 0, Pitch 90, Roll 0) -> Yaw Roll 축이 겹쳐진 짐벌락 발생
    1. X축과 Z축이 동일한 평면에 놓이게 된다.
  3. Yaw / Roll 적용
    1. Z축과 Y축이 같은 축을 기준으로 회전
    2. 회전 방향이 원화는 회전을 표현하지 못하거나, 왜곡된다.

 

해결방법

  • Pitch 제한
    • 값을 +- 90 범위로 제한하여 짐벌락 상황을 제외하는 방어코드 작성
  •  쿼너니언(Quaternion)
    • FQuat
    • 오일러 각처럼 순차적으로 회전을 적용하지 않는다.
    • 회전 축(Vector3)과 각도(Scalar)를 단일 벡터로 표현하므로, 회전 순서에 영향을 받지 않는다.
  • 행렬 (Matrix)
    • FMatrix, FTransform
    • 회전 순서를 적용하지 않고, 모든 회전을 동시에 처리
    • 새로운 회전의 대한 연산은 기존행렬과 곱셈으로 누적
    • 회전이 축에 독립적으로 표현되어 정렬로 인한 문제 발생하지 않음

 


출처

 

https://daekyoulibrary.tistory.com/entry/%EA%B2%8C%EC%9E%84-%EC%88%98%ED%95%99-18-%EC%98%A4%EC%9D%BC%EB%9F%AC-%EA%B0%81Euler-angle

 

[게임 수학] #18 | 오일러 각(Euler angle)

*인프런  강의를 듣고 공부한 글입니다.   1. 회전 행렬 구현에서의 문제점3차원 공간에는 세 개의 표준 기저 벡터 \(e_1\), \(e_2\), \(e_3\) 가 존재합니다. 이 세 개의 기저 벡터를 통해 회전을 구현

daekyoulibrary.tistory.com

https://continue96.tistory.com/138

 

게임 수학 | 3부 3차원 콘텐츠 제작 | 10장 3차원 공간

10장 3차원 공간: 입체 공간의 생성10.1 3차원 공간의 설계3차원 공간 좌표계는 두 가지로 구분한다.오른손 좌표계(right-handed coordinate system)왼손 좌표계(left-handed coordinate system) 3차원 공간 좌표계를

continue96.tistory.com

 

'Unreal Engine > Etc' 카테고리의 다른 글

UE5 - Destructible Mesh(Dynamic Mesh Component)  (0) 2024.12.27

프로젝트를 진행하기 전에 내가 어떤 프로젝트를 만들고 어떤 기능을 구현할까.. 라고 생각을 하던 도중

제가 플레이 했던 FPS게임 중 벽이 파괴되어 사실적인 전투를 묘사할 수 있는 게임이 있었습니다.

이러한 기능들을 프로젝트를 진행할 때 구현하고싶어 다양한 방법을 찾아보았습니다.

해당 기법은 Destructible Mesh라고 부르며, 다양한 방법들이 있었습니다.

이번 포스팅에서는 블루프린트를 사용해 구현한 파괴가능한 메시들에 대해 알아보겠습니다.

 

Destructible Mesh

  • 물리적으로 파괴 가능한 3D 모델
  • 특정 이벤트에 의해 분해, 재구성되는 특성을 가진다
  • 충격, 폭발, 물리적 충돌 등을 통해 모델이 분해되는 방식으로 구현된다
  • 파괴된 상태는 메모리에 저장되어 게임 내 파괴된 물체를 다시 불러오는 작업을 할 수 있다.

 

장점 및 단점

  • 플레이어가 물체를 파괴할수있어 게임 내 몰입감을 높이고 물리적 상호작용을 더 다양한 방식으로 표현할 수 있다.
  • 런타임 환경에서 파괴하여 플레이 시 생동감있는 표현을 보여줄 수 있다.
  • 나무, 금속, 유리 등 각기 다른 재질들의 파괴방식을 다르게 구현하는데 있어 설계의 난이도가 높다.
  • 파괴 시 계산하는 작업에 있어 메모리 사용량이 증가하며 성능에 영향을 줄 수 있다.

 

Dynamic Mesh Component

  • 동적 변형이 가능한 메쉬
  • 런타임 환경에서 물리적 충격, 폭발 등으로 해당 메쉬를 동적으로 변경할 수 있다 - 1
  • 파괴된 조각들이나 물리적 충돌을 처리하는 방식에 있어 성능 최적화가 가능하다.
  • 해당 물체의 각 부분을 세밀하게 제어할 수 있기때문에 물리적 처리를 더 디테일하게 조절할 수 있다.
  • 런타임 환경에서 실시간 렌더링을 하는 과정 중 성능에 문제가 생길 수 있다 - 2

1. Dynamic Mesh Coponent를 활용한 Destructible Mesh

 

2. 실시간 렌더링 프레임 순간적으로 20~30프레임으로 변형된다. - https://link.springer.com/article/10.1007/s11042-022-13049-x

 

 

 

Dynamic Mesh Actor을 사용한 블루프린트 클래스 내 구현

1. BeginPlay

 

Allocate Compute Mesh : 동적 메쉬의 메모리 할당 및 변형 처리를 담당한다.

Append Sphere Box : Sphere와 Box 두 가지 다른 형태의 충돌 영역을 하나로 결합하며, Sphere와 Box가 충돌될 경우를 처리하기 위해 사용한다.

 

 

2.OnRebuildGenerateMesh

OnRebuildGeneratedMesh : 동적 메쉬가 재구성 시 발생하는 이벤트

Append Box : 여러개의 박스 충돌 영역을 결합하여 충돌범위를 최적화 하는데 사용한다.

Enable Complex as Simple Collision : 복잡한 메쉬 충돌들을 단순한 충돌체로 대체한다. 복잡한 Dynamic Mesh 모델에 대한 물리적 계산을 더 빠르게 처리할 수 있다.

 

3. Destruction(인터페이스)

Break Hit Result : Collision 발생 시 그것에 대한 정보들을 가지고 있는 구조체

  • Location : 충돌이 발생한 위치
  • Normal : 충돌 지점에서의 법선 벡터
  • Impact Point : 충돌이 발생한 좌표
  • Impact Normal : 충돌 지점에서 물체의 표면 법선
  • Hit Actor : 충돌한 액터
  • Hit Component : 충돌한 컴포넌트

Apply Mesh Boolean : Boolean 연산을 메쉬에 적용하는데 사용되는 함수로 메쉬의 결합, 차집합, 교집합의 작업을 설정할 수 있다.

  • Union : 두 메쉬가 겹치는 부분을 포함한 전체 메쉬를 생성한다.
  • Subtract : 한 메쉬에서 다른 메쉬의 영역을 빼고 남은 부분을 생성한다.
  • Intersection : 두 메쉬가 겹치는 부분만을 포함하는 새로운 메쉬를 생성한다.

https://link.springer.com/article/10.1007/s11042-022-13049-x

 

+ Recent posts