skeleton_anim.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. import sys
  2. from common import *
  3. reload( sys.modules["common"] )
  4. from Blender.Mathutils import *
  5. # MulMatrix
  6. def MulMatrix( m, b ):
  7. c = Matrix()
  8. c[0][0] = m[0][0]*b[0][0] + m[0][1]*b[1][0] + m[0][2]*b[2][0] + m[0][3]*b[3][0]
  9. c[0][1] = m[0][0]*b[0][1] + m[0][1]*b[1][1] + m[0][2]*b[2][1] + m[0][3]*b[3][1]
  10. c[0][2] = m[0][0]*b[0][2] + m[0][1]*b[1][2] + m[0][2]*b[2][2] + m[0][3]*b[3][2]
  11. c[0][3] = m[0][0]*b[0][3] + m[0][1]*b[1][3] + m[0][2]*b[2][3] + m[0][3]*b[3][3]
  12. c[1][0] = m[1][0]*b[0][0] + m[1][1]*b[1][0] + m[1][2]*b[2][0] + m[1][3]*b[3][0]
  13. c[1][1] = m[1][0]*b[0][1] + m[1][1]*b[1][1] + m[1][2]*b[2][1] + m[1][3]*b[3][1]
  14. c[1][2] = m[1][0]*b[0][2] + m[1][1]*b[1][2] + m[1][2]*b[2][2] + m[1][3]*b[3][2]
  15. c[1][3] = m[1][0]*b[0][3] + m[1][1]*b[1][3] + m[1][2]*b[2][3] + m[1][3]*b[3][3]
  16. c[2][0] = m[2][0]*b[0][0] + m[2][1]*b[1][0] + m[2][2]*b[2][0] + m[2][3]*b[3][0]
  17. c[2][1] = m[2][0]*b[0][1] + m[2][1]*b[1][1] + m[2][2]*b[2][1] + m[2][3]*b[3][1]
  18. c[2][2] = m[2][0]*b[0][2] + m[2][1]*b[1][2] + m[2][2]*b[2][2] + m[2][3]*b[3][2]
  19. c[2][3] = m[2][0]*b[0][3] + m[2][1]*b[1][3] + m[2][2]*b[2][3] + m[2][3]*b[3][3]
  20. c[3][0] = m[3][0]*b[0][0] + m[3][1]*b[1][0] + m[3][2]*b[2][0] + m[3][3]*b[3][0]
  21. c[3][1] = m[3][0]*b[0][1] + m[3][1]*b[1][1] + m[3][2]*b[2][1] + m[3][3]*b[3][1]
  22. c[3][2] = m[3][0]*b[0][2] + m[3][1]*b[1][2] + m[3][2]*b[2][2] + m[3][3]*b[3][2]
  23. c[3][3] = m[3][0]*b[0][3] + m[3][1]*b[1][3] + m[3][2]*b[2][3] + m[3][3]*b[3][3]
  24. return c
  25. class bone_pose_t:
  26. def __init__(self):
  27. self.rotation = Quaternion( 1.0, 0.0, 0.0, 0.0 )
  28. self.translation = Vector( 0.0, 0.0, 0.0 )
  29. class bone_anim_t:
  30. def __init__(self):
  31. self.keyframes = [] # before the "write to file" phase this array is ether empty
  32. # if the bone doesnt have animation or an array of poses
  33. class skeleton_anim_t:
  34. def __init__(self):
  35. self.bones = []
  36. self.keyframes = []
  37. #===================================================================================================
  38. # ScriptAnim =
  39. #===================================================================================================
  40. def ScriptAnim( obj, b_cmnts ):
  41. if obj.getType() != "Armature":
  42. ERROR( "Select a skeleton and not a(n) " + obj.getType() )
  43. return 0
  44. skeleton = obj.getData( 0, 0 )
  45. # init and populate the instances
  46. skeleton_anim = skeleton_anim_t()
  47. skeleton_anim.keyframes = action.getFrameNumbers()
  48. bone_names = skeleton.bones.keys()
  49. bone_names.sort()
  50. for i in range( 0, len(bone_names) ):
  51. skeleton_anim.bones.append( bone_anim_t() )
  52. for j in range( 0, len(skeleton_anim.keyframes) ):
  53. skeleton_anim.bones[i].keyframes.append( bone_pose_t() )
  54. # now populate with the correct data
  55. # for all the kframes
  56. for i in range( 0, len(skeleton_anim.keyframes) ):
  57. kframe = skeleton_anim.keyframes[i]
  58. Blender.Set( "curframe", kframe )
  59. Blender.Redraw()
  60. pose = obj.getPose()
  61. # for all bones
  62. for j in range( 0, len(bone_names) ):
  63. bone_name = bone_names[j]
  64. pose_bone = pose.bones[bone_name]
  65. bone = skeleton.bones[bone_name]
  66. # rotation
  67. rot = pose_bone.quat.toMatrix()
  68. rot.resize4x4()
  69. # translation
  70. tra = Matrix()
  71. tra.identity()
  72. for m in range(0, 3):
  73. tra[m][3] = pose_bone.loc[m]
  74. # bone matris at armature space aka MA
  75. MA = Matrix( bone.matrix["ARMATURESPACE"] )
  76. MAi = Matrix( MA )
  77. MAi.invert()
  78. # calc the m4 = MA * tra * rot * MAi
  79. rot.transpose()
  80. tra.transpose()
  81. MA.transpose()
  82. MAi.transpose()
  83. m4 = MulMatrix( rot, MAi )
  84. m4 = MulMatrix( tra, m4 )
  85. m4 = MulMatrix( MA, m4 )
  86. m4.transpose()
  87. # get the final quat and loc
  88. quat = m4.rotationPart()
  89. quat = quat.toQuat()
  90. loc = m4.translationPart()
  91. quat = pose_bone.quat
  92. loc = pose_bone.loc
  93. for k in range(0, 4):
  94. skeleton_anim.bones[j].keyframes[i].rotation[k] = quat[k]
  95. for k in range(0, 3):
  96. skeleton_anim.bones[j].keyframes[i].translation[k] = loc[k]
  97. Blender.Set( "curframe", 1 )
  98. Blender.Redraw()
  99. # now do the apropriate for the bones without translation or rotation
  100. zero_vec = Vector( 0.0, 0.0, 0.0 )
  101. ident_quat = Quaternion( 1.0, 0.0, 0.0, 0.0 )
  102. # for all the bones
  103. for i in range( 0, len(bone_names) ):
  104. no_anim_num = 0 # how many times we found that the bone has no anim
  105. bone = skeleton_anim.bones[i]
  106. # for all the keyframes
  107. for j in range( 0, len(skeleton_anim.keyframes) ):
  108. if bone.keyframes[j].rotation == ident_quat and bone.keyframes[j].translation == zero_vec:
  109. no_anim_num = no_anim_num + 1
  110. if no_anim_num == len( skeleton_anim.keyframes ):
  111. print "Bone \"%s\" has no animation" % bone_names[ i ]
  112. bone.keyframes = []
  113. # write to ftxt
  114. ftxt = ""
  115. # the keyframes
  116. if b_cmnts:
  117. ftxt += "/*KEYFRAMES_NUM*/ "
  118. ftxt += len(skeleton_anim.keyframes) + "\n"
  119. if b_cmnts:
  120. ftxt += "/*KEYFRAMES*/ "
  121. for kf in skeleton_anim.keyframes:
  122. ftxt += str(kf - 1)
  123. ftxt += "\n"
  124. # the bones num
  125. if b_cmnts:
  126. ftxt += "/*BONES_NUM*/ "
  127. ftxt += str( len(bone_names) )
  128. for i in range( 0, len(bone_names) ):
  129. bone = skeleton_anim.bones[i]
  130. if b_cmnts:
  131. ftxt += "\t/*BONE_NAME " + bone_names[i] + "*/\n"
  132. if len( bone.keyframes ):
  133. if b_cmnts:
  134. ftxt += "\t\t/*HAS_ANIM*/ "
  135. ftxt += "1\n"
  136. for j in range( 0, len( skeleton_anim.keyframes ) ):
  137. file.write( "\t\tKEYFRAME %d\n" % (skeleton_anim.keyframes[j] - 1) ) # -1 cause my keyframes start from 0
  138. if b_cmnts:
  139. ftxt += "\t\t/*KEYFRAME" + str(skeleton_anim.keyframes[j] - 1) + "*/\n"
  140. # write rotation
  141. if b_cmnts:
  142. ftxt += "\t\t\t/*ROTATION*/ "
  143. for k in range( 0, 4 ):
  144. ftxt += str( bone.keyframes[j].rotation[k] ) + " "
  145. ftxt += "\n"
  146. # write translation
  147. if b_cmnts:
  148. ftxt += "\t\t\t/*TRANSLATION*/ "
  149. for k in range( 0, 3 ):
  150. ftxt += str( bone.keyframes[j].translation[k] ) + " "
  151. ftxt += "\n"
  152. else:
  153. if b_cmnts:
  154. ftxt += "\t\t/*HAS_ANIM*/ "
  155. ftxt += "0\n"
  156. return ftxt
  157. #===================================================================================================
  158. # ExportAnim =
  159. #===================================================================================================
  160. def ExportAnim( path, obj, b_cmnts ):
  161. print obj.__class__.__name__
  162. action = obj.getAction()
  163. if action == 0:
  164. ERROR( "Empty action for obj " + obj.getName() )
  165. return false
  166. INFO( "Trying to export skeleton animation \"" + skeleton.name + "\"" )
  167. filename = path + action.name + "." + obj.getName() + ".anim"
  168. WriteFile( filename, ScriptAnim( obj, b_cmnts ) )
  169. INFO( "Skeleton animation exported!! \"" + filename + "\"" )