DirectX에서의 회전 작업(LookAt 메소드 구현)에 대해서

2025. 2. 14. 01:34·공부/DirectX12

얼마 전에 잠시 여행을 다녀오면서 작업이 멈춰있던 관계로 이번주는 더욱 작업에 박차를 가했다. 이번주에 마무리하려고 했던 부분은 ConstantBuffer와 Camera 클래스의 구현으로 크게 나눌 수 있었는데, 이 큰 덩어리들을 처리하기 이전에 Transform 컴포넌트 클래스를 구현하고 Scale, Rotation, Translation이라 불리는 세 가지 요소에 대한 메소드를 구현해야했다. 아무래도 Camera 클래스를 구현해놓고 회전을 하드코딩으로 구현해두면 나중에 리팩토링할 때 더 고생할 것 같앝기 때문.

 

대부분의 메소드는 잘 구현했는데 특정 타겟을 바라보도록 회전시키는 LookAt 메소드를 구현하는 것이 제대로 진행되지 않았다. 다음은 LookAt 메소드를 디버깅하며 깨닳았던 중요한 정보(?)들이다.

 

각 축에 대한 회전 방향

LookAt 메소드를 구현하고 디버깅하는 과정은 이랬다.

  1. 먼저 카메라를 "시계방향"으로 90도 돌린다.
  2. LookAt 메소드를 사용해서 원점(0, 0, 0)으로 시점을 돌리게 한다.
  3. 정상적으로 작업이 수행되었는지 확인한다. (원점에 오브젝트를 두어 이를 확인할 수 있게 함)

하지만 물체는 전혀 보이지 않았고 각 회전 값들을 확인했다. 문제는 바로 알 수 있었는데, y축에 대한 회전값이 0이 아닌 180에 근접한 값을 가지고 있었다.

 

여기서 잠시 회전 방향, 즉 우리가 시계 방향 반시계 방향이라고 정의하는 기준은 무엇인가? 회전하는 축의 벡터가 정면을 향하고 있다고 가정했을 때 그 물체가 돌아가는 방향을 결정하는 것이다.

만약 우리가 카메라를 오른쪽으로 90도 돌리고자 한다면 어느 방향으로 돌려야하는 것일까? 나는 관찰자의 입장에서 카메라를 위에서 보고있다고 생각했고, 당연히 시계방향으로 90도 돌린다고 생각했다. 이는 y축을 기준으로 90도 돌리면 되는 것이다. 하지만 카메라는 정 반대인 왼쪽을 바라보고 있었다. 왜냐하면 애초에 y축을 위에서 바라보면 y축 벡터가 정면이 아닌 후면을 바라보게 되기 때문이다.

 

항상 이런 위치변경이나 회전에 대해 다룰 때는 상대적인 값을 고려해야하는데, 아직 많이 익숙해지지 못한 것 같다..

 

LookAt에서 회전에 관여하면 안되는 축

이게 진짜 골머리 앓았던 문제였다. 특정 벡터가 어떤 타겟을 바라보도록 회전시키려면 어떻게 해야할까? 필자는 단순하게 그냥 두 벡터 사이의 각을 구해서 회전을 나타내는 벡터 성분인 x, y, z에 적용해주면 될 것이라 생각했다.

이런식으로....?

사실 뭐 이제와서 생각해보면 접근방식이 틀렸던건 아닌듯 하다만.. 회전을 적용할 때 x, y, z 세 가지 성분을 모두 건드려서는 안됐다. 일상생활에서도 찾아볼 수 있는 너무나도 당연한 이유인데, 우리가 어떤 사물을 바라보려고 고개를 돌릴 때 특수한 경우를 제외하고 고개를 좌우로 기울이는가? 그렇다. 특정 좌표를 바라보도록 할 때는 z축의 회전이 적용되어서는 안되었다.

이것도 사실 상대적인 접근이라고 생각되기 때문에 "z축의 회전은 금지다!" 라고 생각하기 보다는 "특정 지점을 바라보는 회전에는 세 가지 축 중에서 두 가지 축의 회전만 고려해야한다" 가 더 알맞은 표현이 될 듯 싶다. 뭔가 수학적인 근거가 분명히 있을 듯 싶은데 아직 리팩토링해야할 부분이 많으므로 일단 이정도로 넘어가자...

 

복수의 형변환에 따른 값 손실

원래는 Transform의 rotation에 값을 저장할 때 직관적이고 일반적인 각도법을 적용했다. 때문에 호도법을 사용하는 회전 연산에서는 이에 맞춰 변환이 필요했고, 연산이 다 끝난 후에는 다시 이를 각도법으로 변환해서 저장하는 과정을 거쳤다. 당연히 코드를 작성하면서도 적잖게 찝찝하기는 했지만 별다른 문제가 발생하지 않았기 때문에 대수롭지 않게 여기고 있었다.

 

앞선 두 가지 큰 문제를 해결하고 다시 디버깅을 하는데, 90도 -90도와 같이 어떤 한 좌표축에 직교하도록 도형을 회전시켜둔 경우에는 LookAt 메소드가 엉뚱한 결과를 뱉어냈다. 앞선 변환의 과정들에서 값의 손실이 일어났고 결과적으로 연산에 사용되는 벡터들이 미세하게 다른 방향을 가리키게 됐던 것. 이 문제는 최초에 회전 값을 세팅하는 부분에만 각도법을 호도법으로 변환하도록 바꿔서 해결됐다.

 

 

참 기하분야는 일상생활에 대입하면 이해가 쉬운데 막상 구현을 하려고 하면 금세 잊어버리게 되는 것 같다..

'공부 > DirectX12' 카테고리의 다른 글

툰 셰이딩에서 얼굴 명암 처리에 대해서  (0) 2025.04.04
앞으로의 개발 목표 정리  (0) 2025.03.29
DirectX 인덱스 버퍼 버그 해결  (0) 2025.03.23
DirectX12 인덱스 버퍼 데이터 버그 디버깅 중..  (0) 2025.03.23
DirectX12에서의 Descriptor Heap 크기에 대해  (0) 2025.03.09
'공부/DirectX12' 카테고리의 다른 글
  • 앞으로의 개발 목표 정리
  • DirectX 인덱스 버퍼 버그 해결
  • DirectX12 인덱스 버퍼 데이터 버그 디버깅 중..
  • DirectX12에서의 Descriptor Heap 크기에 대해
ayuriK152
ayuriK152
주로 게임 클라이언트 개발 공부를 해요 상용엔진이나 알고리즘 포스팅도 해요
  • ayuriK152
    아유릭공방
    ayuriK152
  • 전체
    오늘
    어제
    • 분류 전체보기 (24)
      • 공부 (19)
        • DirectX12 (11)
        • 유니티 (2)
        • 알고리즘(PS) (5)
      • 게임 (0)
        • 후기 (0)
      • 프로젝트 (5)
        • 리듬게임 프로젝트 (5)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
ayuriK152
DirectX에서의 회전 작업(LookAt 메소드 구현)에 대해서
상단으로

티스토리툴바