언리얼엔진을 통한 드론을 구현하던 중, 마우스 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

다익스트라

  • 가중 그래프에서 최단경로를 찾는 알고리즘
  • 모든 링크의 가중치는 양의 정수여야 한다.
  • 단일 시작점에서 시작하여 그래프의 모든 정점으로의 최단 경로를 계산하는 One To All 방식
  • 시간복잡도 O((V+E) log V)

 

 

동작 방식

 

 

다익스트라 알고리즘 - https://ko.wikipedia.org/wiki/%EB%8D%B0%EC%9D%B4%ED%81%AC%EC%8A%A4%ED%8A%B8%EB%9D%BC_%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98

 

  1. 출발 노드 설정, 최단 거리 테이블 초기화
    1. 모든 버텍스 간의 최단거리 값 무한대 설정. 시작 버텍스는 0
  2. 방문하지 않은 노드 중 최단거리가 가장 짧은 노드 선택
  3. 해당 노드를 거쳐 다른 노드로 가는 비용(최단거리 값 + 가중치)업데이트
    1. 기존 최단 거리 값보다 작을 시 테이블 업데이트
  4. 2~3의 과정 반복
  5. 각 정점에 대한 최단 거리 값 반환

 

다익스트라 (+ 우선순위 큐) 구현 코드

#define INF 1e9


// 거리(가중치) / 노드 번호
vector<vector<pair<int, int>>> graph; 

// 최단거리 테이블
vector<int> distances;



void Dijkstra(int start, int numVertices)
{


	// 우선순위 큐 (거리 , 노드 인덱스)
	priority_queue<pair<int, int>> pq;

	// 시작 정점의 거리 0 설정
	distances[start] = 0;	
	pq.push({ 0, start });

	while (!pq.empty())
	{
		// 현재 정점까지의 거리
		int currentDistance = pq.top().first;
		// 현재 정점
		int currentVertex = pq.top().second;
		pq.pop();

		// 이미 처리된 정점일 경우
		if (currentDistance > distances[currentVertex])
			continue;

		// 현재 정점의 모든 인접 정점 확인
		for (pair<int, int>& edge : graph[currentVertex])
		{
			int weight = edge.first;
			int neighbor = edge.second;

			// 비용이 더 적은 경로 발견된 경우
			if (distances[currentVertex] + weight < distances[neighbor])
			{
				distances[neighbor] = distances[currentVertex] + weight;
				pq.push({ distances[neighbor], neighbor });
			}
		}
	}
}
	graph.resize(6 + 1);
	distances.assign(6 + 1, INF);



	graph[0].emplace_back(7, 1);
	graph[0].emplace_back(9, 2);
	graph[0].emplace_back(14, 5);
	graph[1].emplace_back(10, 2);
	graph[1].emplace_back(15, 3);
	graph[2].emplace_back(2, 5);
	graph[2].emplace_back(11, 3);
	graph[3].emplace_back(6, 4);
	graph[5].emplace_back(9, 4);


	Dijkstra(0, 6);

	for (int i = 0; i <= 5; i++)
	{
		if (distances[i] == INF)
		{
			cout << i+1 << ": Unreachable" << endl;
		}
		else
		{
			cout << i+1 << ": " << distances[i] << endl;
		}
	}

삼각함수를 학습하는 이유

언리얼 엔진을 통한 클라이언트 개발 시 물체의 위치,회전,이동(Transform)과 물리 계산등 다양한 계산에 삼각함수에 대한 계산이 필요했습니다.

  1. 마우스 커서가 가리키는 방향을 바라보게하려면 아크탄젠트를 사용해 각도 계산하기
  2. 캐릭터나 물체를 특정 궤적을 따라 이동시키기
  3. 조명, 그림자, 반사효과 등 광원의 세기 등

 

 

삼각함수

  • 각의 크기를 삼각비로 나타내는 함수
  • 동경의 크기에 따라 변화하는 함수
  • 직각삼각형에서 각도와 변의 비율을 나타내는 함수
    • Sin,Cos,Tan
  • 각도를 나타내는 방법
    • 도(Degree), 라디안(Radian)
  • 주어진 함수에 대한 각을 구하는 함수
    • 역함수 (Arcsin, Arccos Arctan)
  • 세변과 그에 인접한 각도 간의 관계를 나타내는 법칙.
    • 두 점간의 거리를 구할 때
    • 코사인법칙

 

 

삼각함수 - 특수각

 

 

직각삼각형을 통한 정의 Sin, Cos, Tan

직각삼각형 a,b,h에 대한 Cos,Sin,Tan

  • Sine(Sin)
    • 직각삼각형에서 각의 대변과 빗변의 비율
    • y축 관련 계산에서 사용된다.
    • Sin A = a/h
  • Cosine(Cos)
    • 직각삼각형에서 각 인접변의 비율
    • x축 관련 계산에서 사용된다.
    • CosA = b/h
  • Tangent(Tan)
    • 각의 대변과 인접변의 비율
    • 기울기 계산에 사용된다.
    • TanA = a/b

코사인 법칙

코사인 제 2법칙

코사인 제 1법칙

  • c = b Cos A + a COS B
    • 양 변의 길이와 알고자 하는 변 사이의 두 각의 크기를 아는 경우, 다른 한변의 길이를 알아낼 때 사용할 수 있다.

코사인 제 2법칙

  • b^2 = c^2 + a^2 - 2caCosB
    • 두 변의 길이와 끼인각의 크기를 알 때 삼각형의 나머지 한 변의 길이를 구할 때 쓸 수 있다.

 

 

단위원을 통한 정의 Sin θ , Cos θ , Tan θ

단위원

    • sin θ = y/r
    • cos θ = x/r
    • tan θ = y/x = sin θ / cos θ

특수각

  • 각 중에서도 0,30,45,60,90도와 같은 각도로 삼각비 값을 계산하거나 기억하기 쉽게 정리되 각도
  • 특정한 수치로 계산된다.

특수각

 

 

 

호도법 Radian

  • 호의 길이로 각도를 표현하는 방법
  • 라디안(Radian) : 호도법으로 표현하는 각의 크기
    • 각에 대응하는 호의 길이를, 원의 반지름으로 나눈 값
    • 호의길이 = 반지름 길이, 360 = PI = 180
    • 원 위의 점이 원점을 중심으로 반지름의 길이만큼 한 방향으로 움직였을 때 대응하는 각의 크기 : 1 라디안

 

삼각함수 항등식

  • 삼각함수가 나오는 항등식

 

 

Sin Cos 그래프

Tan 그래프

 

 

 


사진출처 - https://ko.wikipedia.org/wiki/%EC%82%BC%EA%B0%81_%ED%95%A8%EC%88%98

 

삼각 함수 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 원함수는 여기로 연결됩니다. 어떤 함수를 도함수로 하는 함수에 대해서는 부정적분 문서를 참고하십시오. 코사인은 여기로 연결됩니다. 아프리카 남부의 민

ko.wikipedia.org

삼각함수-1 : https://note.mmmsk.myds.me/Study/%EC%88%98%ED%95%99/%EC%82%BC%EA%B0%81%ED%95%A8%EC%88%98/%EC%82%BC%EA%B0%81%ED%95%A8%EC%88%98-%EA%B8%B0%EB%B3%B8

 

삼각함수 기본

삼각함수 개념 (Trigonometric Function) 각의 크기를 삼각비로 나타내는 함수 동경의 크기에 따라 변화하는 함수 가장 근본적인 주기 함수 직각 삼각형을 통한 정의 C가 직각인 삼각형 ABC에서, 각 A, B,

note.mmmsk.myds.me

삼각함수-2 : 

https://designerd.tistory.com/entry/DirectX12-%EC%82%BC%EA%B0%81%ED%95%A8%EC%88%98

 

[게임수학] 삼각함수

호도법(Radian 라디안) 각의 크기를 재는 SI 유도 단위이다. 호의 길이로 각도를 나타내는 방법이다. 기호는 rad 또는 c이며 이는 자주 생략된다. 어떤 각의 라디안 값은 같은 크기의 단위원 중심각

designerd.tistory.com

 

'게임수학' 카테고리의 다른 글

게임수학 - Matrix (행렬)  (0) 2025.01.13
게임수학 - 왼손좌표계, 오른손좌표계  (1) 2025.01.02
게임수학 - Vector(기하)  (0) 2024.12.31

+ Recent posts