Super Kawaii Cute Cat Kaoani blender bvh load 관련 알아낸 사실 정리 (2)

연구/Blender

blender bvh load 관련 알아낸 사실 정리 (2)

치킨고양이짱아 2023. 4. 18. 17:12
728x90
728x90

blender에 한달 가까이 고통받고, bvh load하는 코드까지 뜯어내면서 알아낸

"blender bvh load 관련" 알아낸 사실들을 세세하게 정리하고자 한다. 시작!

1) armature coordinate에서 rest pose에 대한 정보는 matrix_local에 담겨있다!

blender에서 각 pose.bone에 대한 회전값을 생성할때 rest pose에 대해 계산을 하기 때문에 각 bone의 rest pose에 대한 정보가 필요하다. armature coordinate에 대해서 표현된 rest pose는 다음과 같이 확인할 수 있다.

bpy.data.armature["object 이름"].bones[i].matrix_local

pose.bone.matrix에는 armature coordinate에 대해 표현된 posebone의 transformation matrix가 담겨있는데 matrix_local은 character가 rest state일때의 pose.bone.matrix 값이라고 생각하면 된다.

2) bone local coordinate에서 rotation matrix 정보는 matrix_basis에 담겨있다!

(즉 Rest pose에 대해 표현된 bone의 상태)

bone local coordinate에서 rotation 정보는 pose.bone.matrix_basis에 담겨있다. bone local coordinate는 parent joint coordinate라고 생각하면 된다.

하지만 단순하게 bvh file에 적힌 Motion data 값으로 euler 객체를 생성하고 이를 matrix 로 변환한 값이랑은 차이가 있다. 이는 matrix_basis가 어떻게 생성되는지 알면 조금 더 이해가 될 것이다.

matrix_basis = (boneNode coordinate 상에서 rest pose).inv @ (Motion data 값으로 만들어낸 matrix 값) @ (boneNode coordinate 상에서 rest pose)

bone local coordinate 상에서 rest pose matrix의 경우, matrix_local과 같은 경우도 있고 다른 경우도 있다. io_bvh/import_bvh 코드에서 출력해서 확인해보는 것이 가장 정확하다.

나의 경우 io_bvh 코드에서 bvh_node_dict2armature 함수의 마지막 부분에

bpy.ops.object.transform_apply(location=False, rotation=False, scale=False)

로 세팅했을 때는 rest pose matrix가 bone의 matrix_local값과 동일했고, 위의 함수 옵션에서 rotation을 True로 줬을 때는 축변환이 일어나면서 matrix_local값과 rest pose  matrix값이 달라졌다. 나는 그냥 생각하기 귀찮아서.. rotation옵션을 False로 고정해놓았다..ㅋㅋ


부가적으로 정보를 조금 더 덧붙이자면,

 matrix_basis는 boneNode coordinate에 대해 표현된 pose의 transformation matrix이고, root를 제외한 bodyNode의 경우에는 아무리 character가 움직이더라도 parent joint의 위치가 bodyNode coordinate의 원점에 위치하므로 matrix_basis[:3, 3] = [0., 0., 0.]으로 세팅되어있다. 반면에 root bodyNode의 경우에는 armature coordinate에 대해 표현되므로 matrix_basis[:3, :3]의 값은 armature coordinate의 원점으로부터 얼마나 이동하였는지에 대한 값으로 세팅된다.

그냥 하던대로 bvh 파일을 parsing하여 joint의 (parent_local_transformation matrix)을 구성하고

root bodyNode의 경우 matrix_local 값을 가져와 (matrix_local.T) @ (parent_local_transformation matrix) @ (matrix_local) 값을 matrix_basis에 세팅해주고

root bodyNode가 아닌 경우에는

M = <Matrix 4x4 (-0.0000,  1.0000, 0.0000, 0.0000)
            	(-1.0000, -0.0000, 0.0000, 0.0000)
            	( 0.0000,  0.0000, 1.0000, 0.0000)
            	( 0.0000,  0.0000, 0.0000, 1.0000)>

M.T @ (parent_local_transformation_matrix) @ M을 matrix_basis에 세팅해주어 쓰면 될듯하다.

 

진짜 너무 고생하면서 찾은 정보들인데, 정리해보니 별로 없어 보여서 쫌 그렇지만..

누군가에게 도움이 되길!

Reference)

https://blender.stackexchange.com/questions/44637/how-can-i-manually-calculate-bpy-types-posebone-matrix-using-blenders-python-ap/121495#121495

 

How can I manually calculate bpy.types.PoseBone.matrix using Blender's Python API?

I have this .blend file which has a simple scene, and a python script. There's a readme section in the script, but to give a general idea: There are two identical meshes in the scene, one skinned, ...

blender.stackexchange.com

728x90
728x90