스키닝(skinning)-1
- 프로그래밍/3D그래픽스 & 쉐이더
- 2011. 1. 7. 13:38
V(스킨 world) = V(스킨 local) * M0(뼈대 애니) * W0(가중치)
+ V(스킨 local) * M1(뼈대 애니) * W1(가중치) ....
이따구 식이 책에 나와있었다. 찢어버릴까보다.
책을 봐도 이해가 안갔다 뼈대 애니를 그대로 곱한다니... 스킨의 로컬 정점에 다가...
결국 알아낸 진짜 계산식...
V(최종 world) = V(스킨 world) * M0(월드 상에서 뼈가 움직인 만큼의 애니) * W0(가중치) ....
그럼 저 M0는 어떻게 구하느냐...
일단 뼈의 움직임을 월드 상의 움직임으로 바꾸어야 한다.
뼈 AniTm을 그대로 적용하면 뼈가 A만큼 움직였다고 해서 스킨도 A만큼 움직이지지 않는다.
왜냐?
뼈 AniTm은 뼈의 로컬 정점이 월드에 적용되는 AniTm 값이기 때문에 이를 그대로 스킨의 로컬 정점에 적용하면 각 메시들의 변환 행렬의 차이로 다른 움직임을 보인다.그렇기 때문에 월드 상에서 뼈가 움직인 AniTm만큼 월드 상에 스킨 정점을 이동하는 방법을 찾아야 한다.
월드 상에서 시작 기준이 될 행렬 OffsetTm을 구한다
OffsetTm = 뼈의 초기 월드 행렬(움직임이 없는 고정된 상태에서 계산된 뼈 월드 행렬)의 역행렬
월드 상에서 뼈의 움직임 값을 구한다
(월드 상의 뼈 움직임) = OffsetTm * Bone AniTm
이를 월드 상의 정점에 적용
V(최종 world) = V(스킨 world) * (월드 상의 뼈 움직임)
스킨 로컬 상에서 뼈의 로컬 상의 움직임만큼 스킨 정점을 이동 후 월드화 해주는 방법도 있다.
아마 책에서 말했던 위의 식에서 말하는 뼈대 애니란 로컬 상에서의 뼈의 움직임을 말하는 것일 듯...
그럼 그렇게 적어놔야지 뼈대 애니 행렬이라고만 적으면 어떻하냐~
스키닝 정리
스키닝공식을 살펴보면
V_world = V_local * M[INDEX0] * W_0 + V_local * M[INDEX1] * W_1 + .... V_local * M[INDEXn] * W_n
이렇게 되어있다.
이게 무슨 개소리인가라고 싶은 사람이 있을 것이다.
식을 쫘악 풀어보면 머리속에 가득찬 스모그가 사라질것이다.
V_world
= V_local(메시의 로컬좌표) * M_world(메시의 월드행렬)
* M_world의 역행렬(본의 월드의 역행렬) * M_Animation(본의 애니메이션 월드행렬) * W_0( 0번째 가중치값 )
을 구할 수 있다.
이건 0번째에 해당하는 스키닝공식을 적용한 것이다.
V_local * M_world(메시의 월드행렬)을 통해 우선 메시의 월드공간으로 정점을 옮긴다.
그리고나서, M_world의 역행렬(본의 월드의 역행렬)을 통해 본의 좌표공간으로 옮길 수 있다.
왜 이렇게 옮겨야 되냐면 메시는 자신의 로컬좌표계기준을 가지고 있고 본 또한 자신의 로컬좌표계기준을 가지고 있기 때문이다.
로컬 좌표계는 각 자 하나씩 가지고 있는 좌표계가 아니던가.
이렇게 본의 로컬좌표계기준으로 옮겼기때문에 본의 애니메이션 월드행렬을 곱해주면 애니메이션 행렬연산을 적용받을 수 있게 된것이다.
그리고나서 W_0(0번째 가중치)만큼 곱해주면 우리는 0번째 스키닝행렬을 구한 것이다.
이런식으로 가중치 수가 4개라면 4개를 구한다음 더해주면 되는것이다.
이해하기가 힘들다면 로컬 좌표계는 노드마다 무조건 하나씩 가지고있는 공간으로서
어떤 V_world의 월드공간의 정점을 a라는 노드가 자신의 로컬좌표공간에서 참고하고 싶다면,
V_local = V_world * (a라는 노드의 월드공간의 역행렬)
으로 이해하면 되겠다.
(아하!!!!!!!!!!!!!!!!!!!!!!!!!!!)
그래도 모르겠다면 해골책의 소프트웨어 스키닝을 보면서 한번 따라가보길 바란다.
이래서 소프트웨어가 좋다구나.
<<tip!!!>>
잠깐! 방금 생각이 났는데 혹시 스티칭공부중인 사람이라면 왜 스티칭을 할때에는 M_world의 역행렬(본의 월드의 역행렬)을 안해주지라는 의문을 가진 사람이 있을수도 있다.
그건 최적화의 개념으로 보면 된다.
뭐냐하면...
V_world = V_local * M_World(메시의 월드행렬) * M_world의 역행렬(본의 월드의 역행렬) * M_Animation(본의 애니메이션 월드행렬) 가된다.
풀어보면 이렇다.
스키닝의경우 하나의 정점에 영향을 주는 본이 여러개인데 반해서
즉, V_local * M_World(메시의 월드행렬) * M_world의 역행렬(본의 월드의 역행렬) 이 식을 미리 계산해서 가져놓은 상태에서 바로 애니메이션 행렬을 곱할 수가 없다.
물론 어떻게든 할수 있겠지만 그만큼 메모리도 늘어날지도 모르겠다.
하지만 스티칭의 경우는 영향을 주는 본이 하나로 제한되어있기때문에 미리 정점을
V_local * M_World(메시의 월드행렬) * M_world의 역행렬(본의 월드의 역행렬)을 한 상태로 저장해놓고
애니메이션행렬을 계산해주면 될것이다.
SMD를 공부할 때 정점을 이런식으로 해준다면 성능에 많은 도움을 줄 것이므로 참고하시라.
출저:
이 글을 공유하기