Home [opengl] OGLDEV: Skeleton Animation In OpenGL using Assimp 3
Post
Cancel

[opengl] OGLDEV: Skeleton Animation In OpenGL using Assimp 3

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 행렬을 적용하고 계속해서 루트까지 이를 반복함.
  • 본들은 노드의 이름과 대응됨.

references

Skeletal Animation In OpenGL using Assimp - Part 3

This post is licensed under CC BY 4.0 by the author.

[opengl] OGLDEV: Skeleton Animation In OpenGL using Assimp 2

SCPC 2021 Round 1