자문자답 공부

[DirectX11] 공전, 자전, 부모 Mat

Roka_is_back 2024. 1. 2.

[이전 포스팅]

https://rokaisback.tistory.com/49

 

[Directx11] 태양계 과제

1. 코드 리딩 2. 텍스쳐 입히기 3. 공전 , 자전 3 공전 자전 공전을 구현할 때 부모의 자전 속도와 다르게 공전 속도를 가져야 하기 때문에 어떻게 할까 고민하다가 Unity 처럼 RotateAround를 구현하였

rokaisback.tistory.com

 

공전 - RotateAround 함수 구현


_v3CenterPos : 중심으로 삼을 위치 정보이다.

_v3OriginDir : 중심으로 삼을 위치의 축 normal 정보이다.(Front,Up,Right)

_vecDir : 중심으로 삼은 점 그리고 축에 대해서 어떤 축 회전을 할지 normal 정보이다.

_fAngle : 회전을 얼마나 할것인지의 각도이다.


아이디어

매개변수로 주어진 정보들로 임의의 Matrix들을 만든 후 연산을 한다.

이 연산으로 구해진 Matrix의 pos 정보를 Object의 pos로 설정한다.


구현

전체 구현 코드

 

1.
중심이 되는 위치(_v3CenterPos)와 해당 위치의 기준 축(_v3OriginDir)에 대한 정보를 토대로 

임시 Matrix를 생성한다.

임시 Matrix

 

_v3OriginDir 정보를 토대로 해당 축이 얼마나 회전했는지 구하려면 내적을 이용한다.

cos(setha) = dot 스칼라 값이다. (왜냐하면 _v3OriginDir은 normal임을 가정하기 때문.)

 

왜 NormalDirVec.dot(xy)가 z의 각도이며, NormalDirVec. dot(xz)가 y의 각도 이고 , NormalDirVec.dot(yz)가 x의 각도일까?

아래 그림을 보면 y가 회전할때는 y의 각도의 변화는 없고 x,z가 같은 각도만큼 회전한다.

이 x축과 z축의 회전량이 곧 y의 회전량이다.

기본적으로 축은 Vector3(1.0f,1.0f,1.0f)로 이루어져 있다.
이러한 기본 축과 매개변수로 들어온 _v3OriginDir 값을 내적하면 회전량을 구할 수 있다.

이렇게 구한 회전량으로 RotateMatrix를 만든다.

 

2.

회전하고자 하는 축(_vecDir)에 대한 현재 오브젝트의 임시 Matrix 를 생성한다.

3.

중점이 되는 회전축 Matrix(matOriginRot)와 중점의 회전축 중 어느 곳을 회전할지 정보 Matrix(CurRot)을 곱한다.

4.

얻어낸 회전 정보와 Object의 worldMatrix(m_matWorld)와 곱한 후 Pos 정보를 저장한다. 

 

 

행렬의 연산은 순서가 중요한데 A*B != B*A 이다.

보통 Parent * Child 연산이 일어나는데 이는 Child 좌표를 Parent 좌표계로 변환해서 사용하겠다는 의미이다.

따라서 m_matWorld * around_world 는 기존 Object의 좌표계로 around_world 행렬을 변환해서 적용시키겠다는 의미이다.

즉, A*B 일 때 B 먼저 적용한 후 해당 결과를 A로 변환하여 적용하는 것 이다.

 


사용

 

 

실행

문제

태양을 이동시키면 문제가 발생한다.

좌표가 0일때는 문제가 없지만 1인 경우 무한히 증가하고 -1 인 경우 무한히 감소한다.

강제로 pos 를 설정해버리기 때문에 그럴수 밖에 없다. 아래와 같이 되면서 무한히 증가하게 될 것임.

그런데 그렇다고 태양이 이동했는데 다른 행성이 가만히 있는것은 아니지 않나 싶다.

유니티는 어떻게 구현했나 테스트 해봤는데 유니티도 태양계 같은 케이스에는 별로 적합하지 않은 것 같다.

왜냐하면 중심점 위치를 바꿀때마다 중점과 오브젝트 사이의 거리값이 늘어난다.

 

 

c# 코드

바뀐 좌표에서 바뀐 중심으로 도는 것 같다.

고정 offset 값을 저장해두고 그 값은 유지하게 하는식으로 하면 사용 가능할 것 같긴한데,

태양계는 그냥 일반적인 구현처럼 부모 자식 관계로 돌게 하는게 맞는 것 같다.

 

Transform 수정

scale이 부모보다 자식이 크더라도 위치를 따로 지정한게 아닌 0,0,0 이라면 부모의 위치와 같아야 한다.

하지만 기존 코드는 다르게 동작했다.

시작 좌표가 다르게 되는 것을 볼 수 있다.

따라서 부모 좌표 - 부모좌표 * scale 한 값을 행렬에 넣어주었다.

겉(자식)의 오브젝트와 안(부모)의 오브젝트가 잘 중첩됐다.

 

'자문자답 공부' 카테고리의 다른 글

Struct와 Class 의 차이  (0) 2024.02.23
Virtual 키워드  (0) 2024.02.21
[Directx11] 태양계 과제  (1) 2023.12.30
strcpy(vector.data) / unicode length / 지역 변수 참조 리턴  (0) 2023.12.27
ThreadPool  (1) 2023.11.24

댓글