skeleton.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. import sys
  2. import os
  3. from copy import deepcopy
  4. from Blender import Mathutils
  5. from Blender.Mathutils import *
  6. import Blender
  7. #=======================================================================================================================
  8. # multMatrix =
  9. #=======================================================================================================================
  10. def multMatrix(m, b):
  11. c = Matrix()
  12. 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]
  13. 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]
  14. 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]
  15. 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]
  16. 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]
  17. 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]
  18. 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]
  19. 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]
  20. 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]
  21. 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]
  22. 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]
  23. 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]
  24. 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]
  25. 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]
  26. 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]
  27. 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]
  28. return c
  29. #=======================================================================================================================
  30. # rotMat =
  31. #=======================================================================================================================
  32. rotMat = Matrix()
  33. rotMat[0][0] = 1.0
  34. rotMat[0][1] = 0.0
  35. rotMat[0][2] = 0.0
  36. rotMat[0][3] = 0.0
  37. rotMat[1][0] = 0.0
  38. rotMat[1][1] = 0.0
  39. rotMat[1][2] = 1.0
  40. rotMat[1][3] = 0.0
  41. rotMat[2][0] = 0.0
  42. rotMat[2][1] = -1.0
  43. rotMat[2][2] = 0.0
  44. rotMat[2][3] = 0.0
  45. rotMat[3][0] = 0.0
  46. rotMat[3][1] = 0.0
  47. rotMat[3][2] = 0.0
  48. rotMat[3][3] = 1.0
  49. rotMat.transpose()
  50. #=======================================================================================================================
  51. # Initializer =
  52. #=======================================================================================================================
  53. class Initializer:
  54. def __init__(self):
  55. self.blSkeleton = None # Blender Armature
  56. self.saveDir = "" # the name of the saved file
  57. self.flipYZ = 0 #convert from bl to right handed coord system
  58. #======================================================================================================================
  59. # getBlSkeletonFromBlObj =
  60. #=======================================================================================================================
  61. def getBlSkeletonFromBlObj(obj):
  62. # check if obj is correct class
  63. if(obj.__class__.__name__ != "Blender Object"):
  64. raise RuntimeError("The given func param is not a \"Blender Object\" class but a \"" + obj.__class__.__name__ + "\"")
  65. # check modifiers
  66. if len(obj.modifiers) < 1:
  67. raise RuntimeError("Obj \"" + obj.getName() + "\" doesnt have modifiers so no armature found")
  68. # search for modifier of skeleton type
  69. for mod in obj.modifiers:
  70. if mod.type == Blender.Modifier.Types.ARMATURE:
  71. aobj = mod[Blender.Modifier.Settings.OBJECT]
  72. skeleton = Blender.Object.Get(aobj.name).getData(0, 1) # set skeleton
  73. return skeleton
  74. raise RuntimeError("Obj \"" + obj.getName() + "\" has no modifier of type armature")
  75. #=======================================================================================================================
  76. # getAnkiSkeletonScript =
  77. #=======================================================================================================================
  78. def getAnkiSkeletonScript(skeleton, flipYZ):
  79. ftxt = "" # file text
  80. # write the file
  81. boneNames = skeleton.bones.keys()
  82. boneNames.sort() # the bones are written in alpabetical order
  83. ftxt += str(len(boneNames)) + "\n"
  84. for boneName in boneNames:
  85. bone = skeleton.bones[boneName]
  86. # name
  87. ftxt += "\"" + bone.name + "\"\n"
  88. # head
  89. co = bone.head["ARMATURESPACE"]
  90. if flipYZ:
  91. ftxt += str(co.x) + " " + str(co.z) + " " + str(-co.y) + "\n"
  92. else:
  93. ftxt += str(co.x) + " " + str(co.y) + " " + str(co.z) + "\n"
  94. # tail
  95. co = bone.tail["ARMATURESPACE"]
  96. if flipYZ:
  97. ftxt += str(co.x) + " " + str(co.z) + " " + str(-co.y) + "\n"
  98. else:
  99. ftxt += str(co.x) + " " + str(co.y) + " " + str(co.z) + "\n"
  100. # matrix
  101. m4 = bone.matrix["ARMATURESPACE"].copy()
  102. if flipYZ:
  103. m4 = multMatrix(m4, rotMat)
  104. for i_ in range(0, 4):
  105. for j_ in range(0, 4):
  106. ftxt += str(m4[j_][i_]) + " "
  107. ftxt += "\n"
  108. # write the parent
  109. if not bone.parent:
  110. ftxt += "NULL\n"
  111. else:
  112. ftxt += str(boneNames.index(bone.parent.name)) + "\n"
  113. # write the childs
  114. ftxt += str(len(bone.children)) + "\n"
  115. for child in bone.children:
  116. ftxt += str(boneNames.index(child.name)) + " "
  117. ftxt += "\n"
  118. return ftxt
  119. #=======================================================================================================================
  120. # export =
  121. #=======================================================================================================================
  122. def export(skeletonInit):
  123. skeleton = skeletonInit.skeleton
  124. #check if mesh is the correct class
  125. if(skeleton.__class__.__name__ != "Armature"):
  126. raise RuntimeError("The given func param is not a \"Armature\" class but a \"" + skeleton.__class__.__name__ + "\"")
  127. print("Trying to export skeleton \"" + skeleton.name + "\"")
  128. filename = skeletonInit.saveDir + skeleton.name + ".skel"
  129. file = open(filename, "w")
  130. file.write(getAnkiSkeletonScript(skeleton, skeletonInit.flipYZ))
  131. print("Skeleton exported!! \"" + filename + "\"")