엔진프로그래밍

[3dsmax-plugin]애니메이션 time0일땐 되고 나머지는 다 망가질 때 해결법

doyyy_0 2025. 11. 21. 12:08

스키닝이 꼬이는 문제는 정말 많지만. 아무리 생각해도 값 완벽하게 들어갔는데 뭔가 스키닝이 꼬이는 경우가 있을 수 있다.

 

max에서는 애니메이션이 잘 작동하는데 내 엔진에서는 이렇게 꼬일 수도 있다. 근데 이걸 time을 0으로 맞춰놓고 찍어보면 그냥 가만히 서있는 model로서 잘 나온다. 즉 값은 잘 들어갔다는 것이다. 그런데 

 

time을 0으로 찍지말고 800으로 찍어보니까 

 

이렇게 엄청 뒤틀린다. 분명 0과 800샘플링 된 값을 비교해 봤을때 아주 미세한 움직임인데 왜 저렇게 많이 뒤틀릴까? 

그리고 내 엔진에서 행렬값을 잘 찍어봐도 다 명확하게 잘 들어갔다.

 

특히 time이 0일때는 잘 그려지는데 나머지는 망가질때 첫번째로 의심해야할 부분은 이것이다.

"bone과 bind-pose가 정확히 매칭이 됐는가?" 

즉 bone의 위치와 그에 해당하는 mesh들을 띄워놨을때 

 

 

이렇게 되면 안된다는 것이다.

그리고 잘 binding된것같아도, mesh를 드래그한다음에 bone을 다시 움직여보면, 스키닝이 이미 잘 되어있기 때문에 mesh가 알아서 bone에 binding된 모습을 볼 수 있다.

 

하지만 데이터를 뽑을 땐 내가 mesh를 움직인 마지막 위치로 뽑아지기 때문에 엔진에서 이상하게 나올 수 있다. 그걸 방지하기 위해 bone과 mesh를 0,0,0에 위치시킨 후 뽑아주면 문제가 없다.

여기서 0,0,0으로 맞춰야한다는 의미다.

 

마지막으로 확인해야할게, offset구할 때

offsetMatrix[ boneIndex ] = MeshFrame.ToRoot * MatrixInverse( boneFrame.ToRoot );

https://blog.naver.com/jidon333/220234407805

 

이러한 공식이 있는데, MeshFrame.ToRoot은 max에서 Geometry노드의 월드행렬을 뜻한다. 이걸 offset구할 때 넣어주던가 아니면 vertex자체를 뺄 때 이걸 곱해서 빼든가 해서 vertex에 곱해줘야한다. 난 offsetMatrix는 그냥 bone의 월드행렬의 역행렬을 취해줬고, vertex를 뺄 때 

Matrix3 Aftertm = node->GetObjTMAfterWSM(t); 
v = VectorTransform(Aftertm, mesh->verts[nVertexNum]);

이런식으로 미리 계산 후 출력해 주었다.

 

마지막으로 최종 애니메이션이 잘 출력된 것을 볼 수 있다.