skeleton animation.py 6.1 KB

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