본문 바로가기

DirectX11

3ds Max SDK Export(Object Animation) -2-

1. 이전 글에서 애니메이션을 하는 방법에서 생기는 문제점<
  이전에 쓰는 방식은 정점과 ObjectTM 두 정보를 출력하여 다이렉트에서 사용하는 방법이었다. 하지만 이 방법에는 두 가지 큰 단점을 가지고 있다. 첫번째로 출력하는 데이터(받아오는 데이터)가 너무 커진다는 점과 두번째로 Max상에서 나뉘어졌던 오브젝트들을 나눠서 사용하지 못한다는 점이 있다.
  첫 번째 단점은 행렬을 그대로 출력한다는 점 때문에 생기는 문제이다. 행렬은 float 값을 4x4만큼 가지고 있다. 즉 4byte 데이터를 16개나 쓰고 있으므로, 행렬 하나 당 64byte를 소모해야 된다는 점이다. 이것을 매 프레임마다 출력해서 가지고 있기 때문에 애니메이션을 가지고 있는 오브젝트가 많을 수록 데이터가 극한으로 커진다. Max상에서 Object마다 이러한 애니메이션 행렬을 가지고 있었으므로 당연히 데이터를 엄청나게 많이 쓰게 되는 것이다. 매시를 가지고 있는 오브젝트 뿐만 아니라 애니메이션을 보조하는 더미, 본 오브젝트들도 이 행렬들을 가지고 있다.
  만약 10개가 되는 Object를 가진 90 frame짜리 애니메이션 데이터를 뽑는다고 가정해보자. 그러면 그 애니메이션 데이터의 크기를 다음과 같이 계산할 수 있다.
 
Object = 10
Frame = 90
Matrix = 65
 
Memory  = Object * Frame * Matrix
= 5850 Byte
= 58.5KB
 
  이것도 하나의 애니메이션이기 때문에 캐릭터 애니메이션과 기타 애니메이션등 해서 애니메이션이 100개만 들어가도 5850KB가 된다. 그럼 약 5.8MB의 크기가 되는 것이다.
  두 번째 단점은 Max상에 나뉘었던 Object를 나눠서 활용하지 못한다는 점이다. 이 부분에 대해서는 이전 글에서 봤던 수식을 한번 다시 보고 이야기 해보도록 하자.
 
Vertex = Local * ObjectTM(Tick)
Vertex = Local * OffsetTM * NodeTM(Tick)
 
  이 수식을 보면 NodeTM이 그대로 출력된다는 점을 알 수가 있다. 이렇게 되면 Max에서 Object 간의 부모 자식 관계가 무조건 유지가 되어야 한다. NodeTM이 부모의 NodeTM이 곱해져 있는 상태이기 때문이다. 이렇게 되면 자식 오브젝트 혹은 부모 오브젝트를 바꾸고 싶어도 출력된 데이터를 가지고 못 바꾸는 사태가 발생한다.

2. 해결 방법
  첫 번째 문제의 해결방법은 아핀변환을 이용하는 것이다. 다행히도 Max SDK에서는 행렬을 아핀 행렬로 바꿔주는 함수가 존재한다. 이렇게되면 Position 3차원 벡터, Rotation 사원수, Scale은 임의의 축 Scale이니 3차원 벡터와 사원수, 총 float 변수 14개를 사용하여 애니메이션이 가능해진다.
  이러한 의문이 드는 사람도 있을 것이다. 어차피 float 변수 2개 차이인데 그렇게 많이 차이날 것인가에 대해서이다. 여기서 한가지 더 봐야할 부분이 있다. 과연 애니메이션에 무조건 Position, Rotation, Scale이 다 들어가게 될 것인가이다. 사실 이러한 경우는 거의 없다고 봐야한다. 일단 Scale일 경우 Animation할 때 잘 안들어가기 때문에 Scale Animation은 거의 안 들어간다고 보면 된다.
그러면 보통은 float 변수 7개를 쓴다고 보면 된다. 거기에 각 본에 해당하는 오브젝트가 Position만 들어가는 경우, Rotation만 들어가는 경우가 있다. 그러면 float 변수 3-4개만 사용하는 경우도 있다는 뜻이 된다. 그러면 float 형을 16개 쓴 행렬에서 적으면 2개에서 많으면 13개를 줄일 수 있게 된다.
  두 번째 문제의 해결방법은 NodeTM을 출력할 때 부모의 역행렬을 곱한 상태로 출력하는 것이다. 이 방법에 대해 이야기 하기 전에 다음 그림을 보도록 하자
 

 
  이전 글에서도 보여줬던 그림이다. 전에도 설명했듯이 오브젝트의 월드 좌표가 LocalTM * ParentNodeTM으로 이루어져 있다. 이 상태로 자신의 NodeTM에 부모의 NodeTM의 역행렬을 곱한다면 LocalTM만 남을 것이다.
  그러면 상속관계가 없어진 이 행렬들을 어떻게 써야할까? 그 상속구조를 우리가 만든 프로그램 내에서 만들어주면 그만이다. 각 오브젝트들의 부모 자식 관계를 설정한 후에는 할 일은 정해졌다. 상속관계 중 제일 위에 있는 오브젝트부터 순차대로 자식한테 행렬을 넘겨주면서 자식이 그 행렬을 자신의 행렬과 곱하게 하면 그만이다. 애니메이션도 애니메이션이 적용된 행렬을 순차적으로 넘겨준다면 애니메이션도 문제 없이 될 것이다.