🎨DirectX

[DX] Animator 작업 : Create Clip Transform (bones 연산)

공대 컴린이 2023. 6. 27. 10:44
728x90

Model에서 Bone 정보를 넘기기 위해선 Cbuffer를 사용했지만, Animation에서는 Cbuffer를 사용할 수 없다.

Tranfrom이 250개이고, Frame이 500개라고 한다면 125,000개의 데이터가 필요한데, CBuffer에서 넘겨줄 수 있는 최댓값은 4996개이다. 

따라서 Animation을 CBuffer로 넘기는 것은 불가능하기 때문에 Texture로 만들어서 보내야 한다.

Texture는 GB급 Texture가 아닌 이상, 데이터가 얼마나 커지든 상관없다.

 

Texture의 행에는 Keyframe 정보를 넣고, 열에는 Bone 정보를 넣는다. 면에는 Clip 정보를 넣어둔다.


 

ModelAnimator에서 bone 정보를 저장하는 과정을 이해하기 위해선 Converter 클래스 중 위 소스코드를 이해해야 한다.

 

bone->Transform * matParent의 결과를 다시 bone->Tramsform에 넣어주는 부분이 중요하다.

bone은 Relative 값이고, Parent는 Global값인데, 결과 Bone은 다시 Global값이 나온다.

즉, Relative 곱하기 Global은 Global 값으로 도출된다는 의미이다.

 

이러한 개념을 토대로 ModelAnimator를 다시 보자.

 

bones[b] 값을 구하는 과정도 Converter와 동일하게 연산된다.

bones[b]는 Relative 값인 Animation과, Global 값인 Parent가 곱해져서 Global값으로 도출된다.

이는, 다음에 bones[b]의 값을 Parent로써 사용하기 위해 Global 값으로 만든것이다.

 

invGlobal * bones[b]는 풀어서 보면, invGlobal * (animation * parent)이다. 

해당 식은 Converter에서 본 것과 같은 bones를 구하는 식이다.

bones의 결과가 Global이었기 때문에, invGlobal * bones[b]는 Global 값 * Global값이다.

 

그런데 Global * Global값이 곱해지면, 원하던 값이 도출되지 않는다.

위 예제를 통해 보자면, 50 + 20의 Relative값으로 움직여서 Global값인 70에 도달한 후, 50의 Relative값을 더해서 최종적으로 120의 Global값을 도출해내고자 했다.

여기서 Global * Global값이 연산되면, 결과는 120(70 + 50)이 아닌, 70 + 120 값이 되어 190이 도출된다.

 

이러한 상황을 막기 위해 invGlobal 변수를 역행렬을 취한 것이다. (79번 줄 참조)

invGlobal의 역행렬은 다시 Relative값이 되어, G = R * G 연산이 다시 성립하여 성공적으로 bones[b]의 결과가 도출될 수 있는것이다.

 

이런식으로 bones의 값을 계속 구하고, 해당 bones의 값을 토대로 ClipTransform을 초기화하여 애니메이션의 프레임마다 출력될 bone 정보가 정상적으로 연산될 수 있는것이다.

728x90