animation.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. import Blender
  2. import os.path
  3. from Blender.Mathutils import *
  4. ######################
  5. #### matrix funcs ####
  6. ######################
  7. def PrintMatrix( matrix ):
  8. for i in range(0, 4):
  9. print "[",
  10. for j in range(0, 4):
  11. f = matrix[i][j]
  12. if f >= 0 :
  13. print " %04f" % f,
  14. else:
  15. print "%04f" % f,
  16. print "]"
  17. def MulMatrix( m, b ):
  18. c = NewMatrix()
  19. 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]
  20. 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]
  21. 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]
  22. 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]
  23. 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]
  24. 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]
  25. 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]
  26. 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]
  27. 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]
  28. 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]
  29. 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]
  30. 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]
  31. 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]
  32. 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]
  33. 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]
  34. 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]
  35. return c
  36. def NewMatrix():
  37. m4 = Matrix( [1., 0., 0., 0.], [0., 1., 0., 0.], [0., 0., 1., 0.], [0., 0., 0., 1.] )
  38. return m4
  39. def CpyMatrix( matfrom, matto ):
  40. for i in range(0, 4):
  41. for j in range(0, 4):
  42. matto[i][j] = round( matfrom[i][j], 5 )
  43. def CpyQuat( qfrom, qto ):
  44. for i in range(0, 4):
  45. qto[i] = qfrom[i]
  46. def CpyVec( vfrom, vto ):
  47. for i in range(0, 3):
  48. vto[i] = vfrom[i]
  49. identity_mat = NewMatrix()
  50. #################
  51. #### classes ####
  52. #################
  53. class pose_t:
  54. def __init__(self):
  55. self.keyframe = 0
  56. self.matrix = NewMatrix()
  57. self.quat = Quaternion()
  58. self.loc = Vector( 0.0, 0.0, 0.0 )
  59. self.scale = Vector( 0.0, 0.0, 0.0 )
  60. class bone_ipo_t:
  61. def __init__(self):
  62. self.poses = []
  63. ###############
  64. #### main ####
  65. ###############
  66. def main():
  67. print "\n\n---- Exporting Bone IPO ----"
  68. obj = Blender.Object.GetSelected()
  69. keyframes_num = 0
  70. bone_ipos = {}
  71. ######################################
  72. ########## extract the data ##########
  73. ######################################
  74. if len( obj ) < 1:
  75. print "-->ERROR: Object not selected"
  76. return
  77. obj = obj[0]
  78. if obj.getType() != "Armature":
  79. print "-->ERROR: The selected object must link to an armature and not in a(n) " + obj.getType()
  80. return
  81. armat = obj.getData(0,1)
  82. if obj.getAction() == 0:
  83. print "-->ERROR: No action selected"
  84. return
  85. kframes = obj.getAction().getFrameNumbers()
  86. # for every nodal keyframe aka keyframe
  87. for kframe in kframes:
  88. Blender.Set( "curframe", kframe )
  89. Blender.Redraw()
  90. #determin if it is the first or the last frame
  91. first_kframe = 0
  92. last_kframe = 0
  93. if kframe == obj.getAction().getFrameNumbers()[0]: first_kframe = 1
  94. if kframe == obj.getAction().getFrameNumbers()[ len(obj.getAction().getFrameNumbers())-1 ]: last_kframe = 1
  95. # for all bones
  96. pb_names = obj.getPose().bones.keys()
  97. for pb_nam in pb_names:
  98. pb = obj.getPose().bones[ pb_nam ]
  99. pose = pose_t()
  100. if first_kframe:
  101. bone_ipos[pb_nam] = bone_ipo_t()
  102. ############
  103. # matrix #
  104. ############
  105. CpyMatrix( pb.localMatrix, pose.matrix )
  106. ############
  107. # kframe #
  108. ############
  109. pose.keyframe = kframe
  110. ################
  111. # quaternion #
  112. ################
  113. m4rot = pb.quat.toMatrix() # the quat to mat3...
  114. m4rot.resize4x4() # and now to mat4
  115. ma = NewMatrix() # bone's matrix in armature space
  116. mai = NewMatrix() # and the inverted
  117. # set ma and mai
  118. CpyMatrix( armat.bones[pb_nam].matrix["ARMATURESPACE"], ma )
  119. CpyMatrix( armat.bones[pb_nam].matrix["ARMATURESPACE"], mai )
  120. mai.invert()
  121. # calc the rotation in armature space cause its in bone space
  122. # use my mul matrix cause blenders produces wrong results
  123. ma.transpose()
  124. m4rot.transpose()
  125. mai.transpose()
  126. m4total = MulMatrix( ma, m4rot)
  127. m4total = MulMatrix( m4total, mai)
  128. # now convert total m4 to quaternion
  129. m3tmp = Matrix( [1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0] )
  130. for ii in range( 0, 3 ):
  131. for jj in range( 0, 3 ):
  132. m3tmp[ii][jj] = m4total[ii][jj] # the matrix is transposed
  133. m3tmp.transpose()
  134. qtotal = m3tmp.toQuat()
  135. CpyQuat( qtotal, pose.quat )
  136. ##############
  137. # location #
  138. ##############
  139. # the pose bone gives the loc in bones space thats why we have to convert it...
  140. # to armatur space. This means that...
  141. # new_loc = ToVec( bone.mat_armatspace * ToMat(posebone.loc) * bone.mat_armatspace.inverted() )
  142. ma = NewMatrix()
  143. mai = NewMatrix()
  144. m4tmp = NewMatrix()
  145. vectotal = Vector(0.0, 0.0, 0.0)
  146. # init them
  147. CpyMatrix( armat.bones[pb_nam].matrix["ARMATURESPACE"], ma )
  148. CpyMatrix( ma, mai )
  149. mai.invert()
  150. # load the pose's loc to a mat4
  151. m4tmp[0][3] = pb.loc[0]
  152. m4tmp[1][3] = pb.loc[1]
  153. m4tmp[2][3] = pb.loc[2]
  154. # now calc the m4tmp = ma * m4tmp * mai
  155. ma.transpose()
  156. mai.transpose()
  157. m4tmp = MulMatrix( ma, m4tmp )
  158. m4tmp = MulMatrix( m4tmp, mai )
  159. # now create the total vec3
  160. vectotal[0] = m4tmp[0][3]
  161. vectotal[1] = m4tmp[1][3]
  162. vectotal[2] = m4tmp[2][3]
  163. CpyVec( vectotal, pose.loc )
  164. # now put them
  165. bone_ipos[ pb_nam ].poses.append( pose )
  166. # we want to check the 2 previous matrices
  167. # and if the middle matrice is the same withe the crnt and the
  168. # pre-previous we delete the pose
  169. """i = len( bone_ipos[pb_nam].poses )-1
  170. if i-2 >= 0:
  171. prev = bone_ipos[pb_nam].poses[i-1].matrix
  172. pprev = bone_ipos[pb_nam].poses[i-2].matrix
  173. crnt = pose.matrix
  174. if prev == pprev and prev == crnt:
  175. #print "I will delete the %d keyframe from %s " % ( kframes[i-1], pb_nam )
  176. del bone_ipos[pb_nam].poses[i-1]"""
  177. ###################################
  178. ########## write to file ##########
  179. ####################################
  180. path = "c:\\src\\VisualC++\\gmdl_3d_format\\models\\satan\\"
  181. if not os.path.exists( path ):
  182. path = "c:\\data\\projects\\VisualC++\\gmdl_3d_format\\models\\satan\\"
  183. filename = path + obj.getAction().name + ".animation.txt"
  184. file = open( filename, "w" )
  185. file.write( "FRAMES_NUM %d\n" % kframes[-1] )
  186. file.write( "KEYFRAMES_NUM %d KEYFRAMES " %len(kframes) )
  187. for kf in kframes:
  188. file.write( "%d " %(kf-1) )
  189. file.write("\n")
  190. file.write( "POSEBONES_NUM %d\n" % len(bone_ipos) )
  191. bi = 0
  192. names = bone_ipos.keys()
  193. names.sort()
  194. for nam in names:
  195. ipo = bone_ipos[ nam ]
  196. file.write( "\tBONE %d NAME %s " % (bi, nam) )
  197. file.write( "POSES_NUM %d\n" % (len(ipo.poses)) )
  198. p = 0
  199. for pose in ipo.poses:
  200. file.write( "\t\tPOSE %d\n" % p )
  201. file.write( "\t\t\tKEYFRAME %d\n" % (pose.keyframe-1) )
  202. mat = pose.matrix
  203. file.write( "\t\t\tMATRIX " )
  204. for i in range(0, 4):
  205. for j in range(0, 4):
  206. file.write( "%f " % mat[j][i] )
  207. file.write( "\n" )
  208. p = p+1
  209. file.write( "\t\t\tLOCATION " )
  210. for i in range(0, 3):
  211. file.write( "%f " % pose.loc[i] )
  212. file.write( "\n" )
  213. file.write( "\t\t\tQUATERNION " )
  214. for i in range(0, 4):
  215. file.write( "%f " % pose.quat[i] )
  216. file.write( "\n" )
  217. bi = bi+1
  218. file.close()
  219. print "Done! File \"%s\" created successfuly" %filename
  220. main()