Reading Skinning information from COLLADA document

  •  예전에 모델의 skeleton과 마찬가지로 geometry (vertices attributes information, materials, texture filename) 도 잘 읽었었다. 이제 어떻게 skeleton을 skin(Geometry)에 연결하는지 알 필요가 있다. 우리는 많은 조인트와 스켈레톤을 읽었다. 그러나 아직은 Joint가 어디의 vertex에 영향을 주는지 알수 없다. 다소의 joint는 vertex에 조금도 영향을 끼치지 않을 것이다. 그러나 만약 위에서 했던 가정을 기억한다면 모든 Joint는 skin이 더해져야만 한다고 했던것을 기억 할 것이다. 그러한 case에서 모든 joint는 이론적으로 반드시 skin에 영향을 미친다.
  • skeleton에 알맞게 skin(geometry)를 연결하는 것은 skinning information을 필요로 하고, 이섹션은 그것이 COLLADA 의 어디에 있는 정보인지 찾도록 이해하기 쉽게 도와줄것이다.
  •  설명에 앞서 염두해 둘 것이 있다. 만약 각vertex가 한개의Joint에만 연결된 캐릭터가 있다고 하자. 그땐 항상 Joint가 움직이는 대로 vertex가 연결되어 따라서 움직일 것이다. 그리고 아주 경직된 애니메이션을 보게 될것이다. 그러나 이것은 일반적이지 않다. 일반적으로 대부분의 vertex는 한개 이상의 joint에 연결된다. 그리고 우리는 각각의 joint가 vertex를 변화시키는 가중치 효과를 일부러 만들 것이다. 각각의 joint는 개개의 vertex에 1 이하의 퍼센테이지로 영향을 줄 것이다. 그래서 vertex weight(가중치)는 skinning Information에서 매우 중요한 파트이다.

 

<library_controllers>

  •  <library_controllers>는 joint의 영향을 받고 그들에게 접촉된 모든 모델의 vertex weights를 포함시키고 있다. 우리의 가정에 따라 오직 하나의 mesh와 하나의 skeleton을 가진다. 그래서 우린 <library_controllers>의 자식 리스트에 오직 하나의 <controller> 노드를 가질 것이다. 우리는 오직 <controller>를 한번 찾을때, 자식인 <skin>노드를 찾을 것이다. <skin>노드 안에, <technique_common>의 <accessor>의 자식인<param>어트리뷰트의 "name"값이 "JOINT"인 <source>를 찾을 수 있다. 그리고 <NAME_array>는 skeleton안의 모든 joint의 이름들을 알려줄 것이다. 이제 아래의 소스를 통해 <NAME_array>노드의 "count" 어트리뷰트 사용하여 뼈의 number를 찾는 것을 알아보자. 한 example인 <source>는 다음과 같다.

 

<source id="boyShape-skin-skin-joints">

<NAME_array id="skin-joints-array" count="5">Bone1 Bone2 Bone3 Bone4 Bone5<NAME_array />

<technique_common>

<acessor source="#skin-joints-array" count="5" stride="1">

                        <param name="JOINT" type="Name" />

</acessor>

</technique_common>

</source>

  •  만약 <library_visual_scene>로 돌아가 skeleton의 <node>를 보면, 실제로는 그들 <node>가 가지는 SID인 <NAME_array>속의 모든 이름을 볼수 있을 것이다.
  •  skinning data를 올바르게 읽기 위하여, 우리는 먼저 통상 <skin> 노드의 첫번째 자식인 (skeleton의 skin의) 외형 행렬을 읽는것이 필요하다. 만약 첫번째 자식이 아니라면 자식을 반복하여 찾아서 저장해 두어야 한다. 그리고 우리가 <vertex_weights>라 불리우는 노드를 읽기 시작하면, 그 노드의 "count" 어트리뷰트의 값은 가중치의 수를 나타낸다. 이 count는 우리가 일찍이 읽었던 Geometry data의 모델의 vertices의 수와 같아야만 한다. 왜냐하면 우리는 vertex의 가중치를 각각 모든 vertex에 최소와 최대로 정의하였기 때문이다.
  • 만약  <vertex_weights>노드의 구조체를 본다면 적어도 2개의 <input>노드를 볼것이다. 하나는 semantic = "JOINT"와 그리고 두번째는 semantic = "WEIGHT"인 것들이다. 또 한 <vcount> 노드와 한 <v> 노드가 있다.
  • 우리가 각vertex의 가중치를 읽을때 우리는  <vertex_weight>의 "count" 어트리뷰트 숫자 만큼씩 반복해가면서 <vcount> 만큼읽을 것이다. 그리고 <vcount>의 각각의 값은 Joints(현재 반복한 각각의 세밀한 vertex)를 움직이는 수를 나타낸다. 그래서 <vcount> (number of joints time)의 간격에 따라 반복하여  <v> 의 값의 쌍을 읽어야한다. (Here I assume we have only two <input> nodes in <vertex_weight>)
  •  The first one index the "JOINT" name in the "JOINT" <source>'s <NAME_array> (Here I assume that the value of "offset" attribute of the <input> who's semantic="JOINT" is "0"), we mentioned how to find this source earlier as well, but here you can get the ID of this source from the "source" attribute of the <input> child of the <vertex_weight> node with semantic="JOINT".
  • And the second one index the weight value from the <source> who's ID you can get from the "source" attribute of the <input> child of the <vertex_weight> node with semantic="WEIGHT" (Here I assume that the value of "offset" attribute of the <input> who's semantic="WEIGHT" is "1").

    <vertex_weights count="4">

    <input semantic="JOINT" source="#joints" offset="0"/>

    <input semantic="WEIGHT" source="#weights" offset="1"/>

    <vcount>3 2 2 3</vcount>

    <v>

    1 0 0 1 1 2

    1 3 1 4

    1 3 2 4

    1 0 3 1 2 2

    </v>

    </vertex_weights>

  •  이 예제는 <vertex_weight> 노드가 정의하는 (4개의 vertices에 대한) 가중치(작용)를 보여준다. 첫번째 vertex는 세개의 작용을 가지고 있고, 첫번째 vertex의 첫번째 작용의 joint index(JOINTS <source>의 <NAME_array> 값의 index)는 1이다. 그리고 그것의 가중치의<source>의 <float_array>의 Weight 인덱스는 0이다.
  • 다른 매우 중요한 점은 <joint>라고 불리우는 <skin>노드의 자식 노드와, 그것이 통상 두개의 <input>노드를 가지고 있고, 첫번째는 semantic="JOINT"로 Joint이름을 가진 <source>노드를 참조하고, "source" 어트리뷰트를 가리킨다는 것이다. 그리고 두번째 <input>은 semantic="INV_BIND_MATRIX"로 "source"어트리뷰트를 향하는 각각의 Joint의 할당된 역 행렬을 참조 한다는 것이다. 역행렬의 source는 Joints_count의 역행렬을 생성하는 (Joints_count*16) 값을 가진다. 이 역행렬은 skinning을 위해 필요하다. 그리고 우리가 임플리멘테이션 파트를 읽을떈 삭제할 값이다.
  • <controller> 노드를 읽는것이 한번 완료되면 반드시  한 shape matrix를 할당해야 한다. Joints의 개수와 그들의 역행렬값, 그리고 위에서 이야기한 <visual_scene>의 Joint matrices을 읽어야한다. 각각의 vertex는 반드시 한개 혹은 이상의 bone에 영향을 주어야한다. (Remember 거꾸로 이야기 하면 각각의 Joint는 반드시 적어도 한개 이상의 Vertex에 영향을 주어야한다고 생각할 수 있지만, 이것은 사실이 아니다. vertices에 영향을 주지 않을 수도 있다.) 그리고 그런 까닭에 반드시 weights를 가져야 한다.
  • 만약 위의 것들을 잘 따라오고, geometry data를 읽을수 있다면, skeleton과 skinning data를 COLLADA document로부터 잘 가져올 수 있다. 그리고 raw triangles의 모델을 그릴수 있어야 skeleton을 잘 그릴수 있다. 비록 debugging 목적으로 각각의 Joint와 그들이 그리는 world coordinates의 world 행렬을 축적 시킬수 있을 지라도, parent joint's world matrix를 현재의 Joint에 곱하고 결과를 현재 joint의 world matrix에 저장시키라는 hint를 주었다고 생각한다. 우리는 이러한 프로세스를 root bone으로부터 시작해야 한다. 그래서 parents 로부터 때묻은 world를 가지지 않게 되고, 그리고 root Joint의 world matrix는 Joint matrix가 된다. 적어도 root는 어떤 parent도 없다. 만약 너또한 COLLADA specification version 1.5를 읽는다면 너는 skinning equation(균등)하드는 것을 찾을수 있고, 그렇게 shape를 할당한 model을 넣을 수 있다. 
    어떻게 우리가 아직 조금도 커버되지 않은 이 모델을 animate하고 커버(coverd)할 수 있는지 다음 섹션에서 봅시다.

이 글은 스프링노트에서 작성되었습니다.

Posted by BLUE-NOTE