오늘 학습할 내용으로는 언리얼 엔진에서 좌표를 표현하는 방식과 학습할 때 좌표를 표현하는 방식이 서로 다르기 때문에 사용해야할 좌표변환에 대해서 알아보려고 한다. 사실 이전에 학습했던 포인트 클라우드 내용으로도 어느정도 눈치챌수 있는 내용이지만 정확하게 기준 좌표계부터 벡터의 여러가지 변환에 대해 어떤 행렬을 사용하는지 알아보자
예시 코드 작성해보기
FRotator Rot(0, 90, 0); // Yaw 90도 회전
FVector Forward(1, 0, 0);
FVector Rotated = Rot.RotateVector(Forward);
UE_LOG(LogTemp, Warning, TEXT("Rotated Vector: %s"), *Rotated.ToString());
// 결과: (0, 1, 0)
R(θ) = [ cosθ -sinθ ]
[ sinθ cosθ ]
Rx(θ) = [ 1 0 0 ]
[ 0 cosθ -sinθ ]
[ 0 sinθ cosθ ]
Ry(θ) = [ cosθ 0 sinθ ]
[ 0 1 0 ]
[ -sinθ 0 cosθ ]
Rz(θ) = [ cosθ -sinθ 0 ]
[ sinθ cosθ 0 ]
[ 0 0 1 ]
3D 그래픽스, 로보틱스, 게임 엔진(언리얼/유니티 등)에서 물체의 회전을 표현할 때 흔히 오일러 각(Euler Angle) 또는 회전 행렬(Rotation Matrix) 를 사용한다고 한다.
하지만 이 두 방식에는 단점이 있는데
이를 해결하기 위해 사용되는 것이 쿼터니언이다.
쿼터니언은 4차원 복소수 기반 회전 표현 방식으로, 짐벌락을 피하면서 안정적이고 효율적으로 회전을 계산할 수 있다.
쿼터니언은 실수부 하나와 허수부 세 개로 이루어진 수 이다.
q=w+xi+yj+zk
여기서
즉, 쿼터니언은 4개의 실수 (w, x, y, z) 로 표현된다.
회전용 단위 쿼터니언은 이렇게 정의된다.
q=cos(θ/2)+(xi+yj+zk)sin(θ/2)
여기서θ는 회전 각도, (x,y,z)는 회전축 단위벡터이다.
"어떤 축을 기준으로 얼마만큼 돌릴지"를 압축적으로 담아둔 수학적 표현이 바로 쿼터니언.
동차 좌표계(Homogeneous Coordinates)는 이동(Translation), 회전(Rotation), 투영(Projection) 같은 다양한 기하학적 변환을 하나의 행렬 곱으로 통합하기 위해 사용된다. 고등학교 기하학 수업에서 학습한 투영과 같은 원리이기에 상대적으로 쉽게 이해할수 있을 것이다.
기존의 3D 좌표 (x, y, z)는 동차 좌표계에서 (x, y, z, 1)로 확장된다.
이 마지막 성분 w(1) 는 “스케일링”과 “투영”을 처리하는 데 중요한 역할을 한다.
단순히 좌표를 움직이는 방법이라고 생각하자.
아래 코드는 하나의 점 (1,2,3)을
1)이동, 2) 회전, 3) 투영하는 과정이다.
import numpy as np
# 1. 원래 3D 점 (동차 좌표로 표현: w=1)
point = np.array([1, 2, 3, 1]) # (x=1, y=2, z=3)
# 2. 이동 변환 (x+3, y+2, z+5)
T = np.array([
[1, 0, 0, 3],
[0, 1, 0, 2],
[0, 0, 1, 5],
[0, 0, 0, 1]
])
# 3. z축 회전 (90도)
theta = np.radians(90)
Rz = np.array([
[np.cos(theta), -np.sin(theta), 0, 0],
[np.sin(theta), np.cos(theta), 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]
])
# 4. 원근 투영 행렬 (focal length = 2, d=5)
f, d = 2, 5
P = np.array([
[f, 0, 0, 0],
[0, f, 0, 0],
[0, 0, 1, 0],
[0, 0, 1/d, 0]
])
# 5. 전체 변환 (투영 회전 이동)
point_transformed = P @ Rz @ T @ point
# 6. 동차 좌표 → 3D 복원 (w로 나눔)
point_final = point_transformed[:3] / point_transformed[3]
print("원래 점 (world):", point[:3])
print("변환 후 동차 좌표:", point_transformed)
print("투영 후 최종 좌표 (카메라 평면):", point_final)
원래 점 (world): [1 2 3]
변환 후 동차 좌표: [ -2. 4. 8. 2.6]
투영 후 최종 좌표 (카메라 평면): [-0.769 1.538 3.077]
최종적으로 점은 화면 좌표 (-0.769, 1.538) 근처에 나타나게 된다.
| Unreal Engine Point Cloud 실시간 렌더링하기 (0) | 2025.10.25 |
|---|---|
| Unreal Engine 좌표변환 이해하기(2) (0) | 2025.10.20 |
| 완전히 새로 정리된 Unreal + ONNX 통합 코드 (객체 감지 + 지형 파악) Part1 (0) | 2025.09.20 |
| Unreal Engine에서 학습한 ONNX 모델 불러와 실시간 추론하기 (0) | 2025.09.13 |
| Unreal Engine에서 CUDA와 OpenCV 사용 시행착오 정리하기 (5) | 2025.08.30 |