intro
파트 1,2에서는 Assimp 라이브러리를 사용하여 골격 정보를 로드하는 법을 다루었고, 각 정점이 가중치와 함께 정점에 영향을 미치는 본에 대응하는 법을 다루었다.
이 파트에서는 스켈레톤 애니메이션 기법의 핵심인 행렬 변환에 대해 다룬다.
blender에서는 애니메이션을 생성할 때 key-frames에 있는 본의 위치와 각도를 조절하는 키 프레임을 사용한다.
- 모든 정점들의 위치를 저장하여, 각 프레임마다 해당하는 위치에 정점들을 배치하는 것은 비효율적임.(vertex buffer 등에 문제)
How Assimp manages the animation
aiNodeAnim
- positionKey, scaleKey, rotationKey 의 정보들을 가지고 있음.
이 변환 정보를 가지고 행렬을 만들어야함.
- 그리고 이 행렬을 모델에 적용하여 모델을 움직인다.
하지만 이는 단순하지 않다.
- parent bone의 움직임이 child bone 에 영향을 주게해야한다.
Bone Coordinate System
- 이처럼 계층구조로 움직이게 하려면 새로운 좌표시스템을 도입해야함.(bone space, bone coordinate)
원점은 본의 기저부분(the base of the bone) (blender에서 amature -> viewport display에서 볼 수 있음)
- 뼈 자체는 y축을 가리킴
- x축과 z축은 y축에 수직에 수직이고 서로 수직임
- 일반적으로 메쉬의 정점은 로컬 좌표계를 참조함
- 로컬 좌표계와 본 좌표계의 관계를 알아야함.
The bone hierarchy
- 본 계층구조는 아래와 같다.
리깅할 때 보통 모델의 일부 본을 루트로 지정한다.
- 나머지 본들은 이 루트에서 나누어진 자식 또는 손자
- 보통 척추를 루트로 사용한다.
- 척추에서 사지로 뻗어나감.
- 루트의 본 공간은 로컬 공간을 참조함.
- 로컬 공간은 기본적인 좌표 시스템이라 생각할 수 있음 (원점이 {0,0,0}인, 축이 {1,0,0}, {0,1,0}, {0,0,1})
여기서 루트 본의 기저부는 로컬 공간에서 일반적인 정점과 동일하며, 루트본의 축은 벡터가 된다.
- 아래는 로컬에서 (1, 1)에 위치한 루트 공간
루트의 자식의 본 공간은 로컬이 아니라 루트를 참조하게 된다.
- 아래는 루트에서 (1,1)에 위치한 자식 공간
- 즉, 실제 좌표(로컬에서 볼 때)는 (2, 2)
- 이렇게 각 본 공간은 부모를 참조한다.
Chain of transformation
부모를 참조하는 본 공간을 정의함으로써 우리는 이제 변환 체인을 만들 수 있다.
- 체인은 각 본에서 루트로 흘러감
한 노드에서 (new T0) 변환에 변화가 생기면 모든 하위 개체에 영향을 주지만, 상위 개체에는 영향을 미치지 않음.
흔한 예제로 태양계 예제가 있다. (태양 - 지구 - 달 / 공전)
달의 위치가 지구를 기준으로 봤을 때
(x, y, z)
라면 태양을 기준으로 봤을 때는T0 * (x, y, z)
은하를 기준으로 보면
T1 * T0 * (x, y, z)
Starting the transformation
스켈레톤 애니메이션은 바인딩 포즈에서 로컬에 있는 정점의 위치를 본 좌표계로 변환함으로써 시작한다.(아래 이미지는 평소와 같이 제공되는 정점의 위치)
영향을 미치는 본의 좌표계로 변환하는 것으로 시작
- Bone1 을 참조
- Bone2 를 참조
- 부모에서부터 계층구조의 루트까지 적용하면, 다시 로컬 공간으로 오게됨
- 이 로컬공간에서 월드 공간, 그리고 뷰 공간으로 변환되어 화면에 나타남.
그리고 Assimp에는 global_inverse transform 이라는 것이 있는데 이는 나중에 다룰 것임. (글로벌 역변환)
- 또한 각 정점은 둘 이상의 본의 영향을 받기 때문에 실제로 여러 본의 변환에 대한 가중 평균을 계산해야한다.
- 각 본 변환은 루트까지 동일한 방식으로 계산된다.
- 이런 변환은 애니메이션 중에 조정됨.
- 이렇게 애니메이션하기 위해 Assimp 는 두 개의 행렬을 제공한다. (offset, node transformation)
Assimp offset matrix
offset matrix
: local to bone space- 본 구조체에 있음.(본에는 또한 정점들에 대한 정보가 포함된다.)
- 루트에서 본까지의 모든 변환이 이미 포함됨.
- 따라서 계층 구조에 대해서는 걱정할 필요없음.
물론 영향 받는 본에 대해서 여러 좌표를 얻게됨.
- 이를 하나의 최종 행렬로 계산해야함
- 가중 평균을 구해서 하나의 행렬로 만들어야함.
blender example
본의 기저부가 로컬 공간의 원점에 있고, 본 공간의 축이 로컬 공간의 축과 같으면 기본적으로 아무것도 하지 않음 => 단위 행렬
만약 한단위 이동한곳에 본이 있으면..
- -1만큼 이동해야 원점에 위치하게 되므로 translate(0, -1, 0) 이 적용된 행렬이 offset행렬로 결과가 나온다.
만약 각도가 45도 회전됬으면..
- rotate 가 적용된 행렬이 offset 행렬로 나타남
Assimp node transformation matrix
- 아래는 Assimp 노드 계층구조이다.
- 노드는 장면의 한 개체를 나타냄
- 이 때 한 개체의 위치와 방향은 부모를 원점으로 가지는 좌표계의 값이다. (상대적인 값들)
- 개체는 메시, 본, 카메라, 조명 등에 해당한다.
The aiNode structure
노드 계층구조는 단일 루트 노드로 시작한다.
각 노드는 다음과 같은 정보를 포함한다.
mChildren
: 0개 이상의 자식에 대한 포인터 배열mMeshes
: 0개 이상의 메시에 대한 포인터 배열mParent
: 부모에 대한 포인터mTransformation
: 벡터를 상위 좌표계로 변환해주는것. (예시: 지구의 좌표계에서 태양의 좌표계로 변환해줌)- 로컬위치벡터에 오프셋 행렬을 곱한후에는 본 좌표계가 됨.
- 다음 단계는 계층 구조에서 해당 노드를 찾고 이 노드의 mTransformation 행렬을 적용하고 계속해서 루트까지 이를 반복함.
본들은 노드의 이름과 대응됨.