assimp의 offsetMatrix의 주석을 살펴보면,
Matrix that transforms from mesh space to bone space in bind pose..
뭐 이렇다고한다. 이게 정확히 무슨 의미이고 왜 필요할까?
애니메이션의 bone을 gpu에보낼때 마지막에
m_FinalBoneMatrices[index] = offset * globalTransformation 이렇게 처리한다.
globalTransformation은 현재 nodeTransform * parentTransform이다.
여기서 nodeTransform은 localSpace이고, parentTransform은 worldTransform(=globalTransform)이다. parentTransform은 localTransform들의 계산 합의 결과이다. 따라서 globalTransformation = nodeTransform * parentTransform 즉, globalTransform또한 worldSpace이다.
그럼 우리가 계산하고자 하는 vertex를 한번 살펴보자. 예를들어, 현재 node가 팔이고 그 팔의 globalTransformation의 Translation부분은 대충(0.7,0.7,0.7)이라고 하자. 그 팔 주위에 붙어있는 vertex는 뭐 (0.75, 0.75, 0.75) 이 정도 될 것이다. 그럼,
만약 offset없이 m_FinalBoneMatrices[index] = globalTransformation 이렇게 하면 어떻게 될까? vertex에 globalTranslation을 곱해서 좌표가 (1.4,1.4,1.4)이렇게 훅 점프해버릴것이다. offsetMatrix는 그걸 방지하기 위해 vertex를 worldSpace가 아닌, boneSpace(localSpace)로 변환해주는 것이다. 그럼 offsetMatrix는 뭐가 돼야할까? 바로, 현재 node의 worldMatrix의 역행렬이 돼야한다. 그렇다고 globalTransformation의 역행렬이 아니고, T-pose일 때 현재 노드의 역행렬을 넣어주면 된다. 예를들어 그러면 팔 노드의 역행렬은 (-0.7,-0.7,-0.7)이 되겠고, vertex * 팔노드의 역행렬을 계산하면 (0.05, 0.05, 0.05)이렇게 나와서 결국 팔 노드로부터 vertex까지의 떨어진 거리. 즉, bone space(localSpace)로의 위치가 되는것이다.
max sdk에서 보낼때
//LocalTM이란 (자신의 월드행렬) * (부모월드행렬의 역행렬)
Matrix3 LocalTM, WorldTM;
LocalTM = node->GetNodeTM(GetStaticFrame()) * Inverse(node->GetParentTM(GetStaticFrame()));
WorldTM = node->GetNodeTM(GetStaticFrame()); //이거의 역행렬이 offsetMatrix가 될것
이렇게 보내면 된다.
로컬과 월드가 좀 이해가 어려울 수 있는데, 유니티에서 모델 3개 띄워놓고 자식오브젝트로 붙여가면서 이해하면 LocalTM이 왜 저렇게 나오는지, 그리고 나머지 부분도 이해가 다시 될 것이다.
'엔진프로그래밍' 카테고리의 다른 글
| assimp node 구조 이해하기 (0) | 2025.11.04 |
|---|---|
| 외부 애니메이션 씬 파일 뽑아서 엔진에 넣을 때 case 구분 (0) | 2025.11.04 |
| 3ds max sdk learning path 버전 문제 (0) | 2025.10.20 |
| 3ds max sdk plug-in wizard visual studio에서 안보일때 (0) | 2025.10.18 |
| [메모리관리] 전방선언 잘 사용하기 (0) | 2025.10.09 |