mesh.py 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. import sys
  2. from common import *
  3. reload( sys.modules["common"] )
  4. #===================================================================================================
  5. # mesh_init_t =
  6. #===================================================================================================
  7. class mesh_init_t:
  8. mesh = NULL
  9. skeleton = NULL
  10. material_filename = "*put material filename*"
  11. write_comments = false
  12. save_path = ""
  13. #===================================================================================================
  14. # GetMesh =
  15. #===================================================================================================
  16. def GetMesh( obj ):
  17. if( obj.__class__.__name__ != "Blender Object" ):
  18. ERROR( "The given func param is not a \"Blender Object\" class but a \"" + obj.__class__.__name__ + "\"" )
  19. return 0
  20. if obj.getType() != "Mesh":
  21. ERROR( "The obj \"" + obj.getName() + "\" must link to a mesh and not to a(n) " + obj.getType() )
  22. return 0
  23. mesh = obj.getData( 0, 1 )
  24. return mesh
  25. #===================================================================================================
  26. # ScriptVWeights =
  27. #===================================================================================================
  28. def ScriptVWeights( mesh_init ):
  29. mesh = mesh_init.mesh
  30. skeleton = mesh_init.skeleton
  31. b_cmnts = mesh_init.write_comments
  32. #check if mesh is the correct class
  33. if( mesh.__class__.__name__ != "Blender Mesh" ):
  34. ERROR( "The given func param is not a \"Blender Mesh\" class but a \"" + mesh.__class__.__name__ + "\"" )
  35. return "error"
  36. #check if skeleton is the correct class
  37. if( skeleton.__class__.__name__ != "Armature" ):
  38. ERROR( "The given func param is not a \"Armature\" class but a \"" + skeleton.__class__.__name__ + "\"" )
  39. return "error"
  40. bone_names = skeleton.bones.keys()
  41. bone_names.sort()
  42. # init text
  43. ftxt = ""
  44. # link the vert groups to the bone ids
  45. vgroup2bone_id = {} # we give the vgroup name and we get the bone's id in the skeleton
  46. vgroup_names = mesh.getVertGroupNames()
  47. for vgroup_name in vgroup_names:
  48. bone_id = -1
  49. for bone_name in bone_names:
  50. if bone_name == vgroup_name:
  51. bone_id = bone_names.index( bone_name )
  52. break
  53. if bone_id == -1:
  54. WARNING( "Vert group \"" + vgroup_name + "\" cant link to a bone" )
  55. vgroup2bone_id[ vgroup_name ] = bone_id
  56. if( b_cmnts ):ftxt += "/*VERT_WEIGHTS*/ "
  57. ftxt += str( len( mesh.verts ) ) + "\n"
  58. # for every vert do some shit
  59. for vert in mesh.verts:
  60. influences = mesh.getVertexInfluences( vert.index )
  61. influences_num = 0
  62. sumw = 0.0
  63. # calc the influences num and the total weight (NOTE:we may have...
  64. # ...a vert group that doesnt connect to a bone)
  65. for influence in influences:
  66. vgroup = influence[0]
  67. weight = influence[1]
  68. if vgroup2bone_id[ vgroup ] != -1:
  69. influences_num = influences_num + 1
  70. sumw = sumw + weight
  71. # a check
  72. if( influences_num > 4 ):
  73. ERROR( "Cannot have more than 4 bones per vert" );
  74. return "error"
  75. # write to file
  76. if( b_cmnts ): ftxt += "\t/*VERT_ID " + str( vert.index ) + "*/\n"
  77. if( b_cmnts ): ftxt += "\t/*BONE_CONNECTIONS*/ "
  78. ftxt += str( influences_num ) + "\n"
  79. for influence in influences:
  80. vgroup = influence[0]
  81. weight = influence[1]
  82. if vgroup2bone_id[ vgroup ] != -1:
  83. if( b_cmnts ): ftxt += "\t\t/*BONE_ID*/ "
  84. ftxt += str( vgroup2bone_id[ vgroup ] ) + " "
  85. if( b_cmnts ): ftxt += "/*WEIGHT*/ "
  86. ftxt += str( weight/sumw ) + "\n"
  87. # end for all verts
  88. return ftxt
  89. #===================================================================================================
  90. # ScriptMesh =
  91. #===================================================================================================
  92. def ScriptMesh( mesh_init ):
  93. mesh = mesh_init.mesh
  94. b_cmnts = mesh_init.write_comments
  95. skeleton = mesh_init.skeleton
  96. #check if mesh is the correct class
  97. if( mesh.__class__.__name__ != "Blender Mesh" ):
  98. ERROR( "The given func param is not a \"Blender Mesh\" class but a \"" + mesh.__class__.__name__ + "\"" )
  99. return "error"
  100. # check verts number
  101. if len(mesh.verts) < 3:
  102. ERROR( "The mesh named \"" + mesh.name + "\" has insufficient vert num. Skipping" )
  103. return "error"
  104. # check UVs
  105. """if not mesh.faceUV:
  106. ERROR( "The mesh named \"" + mesh.name + "\" doesnt have UVs" )
  107. return "error"""
  108. # init txt
  109. ftxt = ""
  110. # material
  111. if(b_cmnts): ftxt += "/*MATERIAL*/ "
  112. ftxt += "\"" + mesh_init.material_filename + "\"\n"
  113. # the verts
  114. if(b_cmnts): ftxt += "/*VERTS*/ "
  115. ftxt += str( len(mesh.verts) ) + "\n"
  116. for vert in mesh.verts:
  117. vec = Vector( vert.co )
  118. if(b_cmnts): ftxt += "\t/*VERT_ID "+str(vert.index)+" COORDS*/ "
  119. ftxt += str( vec.x ) + " " + str( vec.y ) + " " + str( vec.z ) + "\n"
  120. # the faces
  121. # first calc the triangles num
  122. tris_num = 0
  123. for face in mesh.faces:
  124. if len(face.v) == 3:
  125. tris_num = tris_num + 1 # if tris
  126. else:
  127. tris_num = tris_num + 2 # if quad
  128. if(b_cmnts): ftxt += "/*FACES*/ "
  129. ftxt += str( tris_num ) + "\n"
  130. # for every face
  131. i = 0
  132. for face in mesh.faces:
  133. if(b_cmnts): ftxt += "\t/*FACE_ID " + str(i) + " VERT_IDS*/ "
  134. order = [0,1,2]
  135. # print index
  136. for j in order:
  137. ftxt += str( face.v[j].index ) + " "
  138. i = i+1
  139. ftxt += "\n"
  140. # if the face is quad then triangulate
  141. if( len( face.v ) == 4 ):
  142. order = [0,2,3]
  143. if(b_cmnts): ftxt += "\t/*FACE_ID " + str(i) + " VERT_IDS*/ "
  144. for j in order:
  145. ftxt += str( face.v[j].index ) + " "
  146. ftxt += "\n"
  147. i = i+1
  148. # the uvs
  149. # create and populate the vertuvs array
  150. vertuvs = {}
  151. # if has UVs
  152. if mesh.faceUV:
  153. for vert in mesh.verts:
  154. vertuvs[ vert.index ] = [ -1000.0, -1000.0 ]
  155. for face in mesh.faces:
  156. order = [0,1,2] # verts order
  157. for j in order:
  158. vert_id = face.verts[j].index
  159. uvx = face.uv[j].x
  160. uvy = face.uv[j].y
  161. # if we put a new value in the array OR the values already set and they are the same then
  162. if vertuvs[ vert_id ][0]==-1000.0 or ( vertuvs[ vert_id ][0] == uvx and vertuvs[ vert_id ][1] == uvy ):
  163. vertuvs[ vert_id ][0] = uvx
  164. vertuvs[ vert_id ][1] = uvy
  165. else:
  166. ERROR( "The mesh \"" + mesh.name + "\" More than 1 coords for the " + str(vert_id) + " vert" )
  167. mesh.verts[vert_id].sel=1
  168. #return "error"
  169. print " %f %f %f %f" % ( vertuvs[ vert_id ][0], vertuvs[ vert_id ][1], uvx, uvy )
  170. # do the same if quat for the other forming triangle
  171. if( len( face.verts ) == 4 ):
  172. order = [0,2,3]
  173. for j in order:
  174. vert_id = face.verts[j].index
  175. uvx = face.uv[j].x
  176. uvy = face.uv[j].y
  177. # if we put a new value in the array OR the values already set and they are the same then
  178. if vertuvs[ vert_id ][0]==-1000.0 or ( vertuvs[ vert_id ][0] == uvx and vertuvs[ vert_id ][1] == uvy ):
  179. vertuvs[ vert_id ][0] = uvx
  180. vertuvs[ vert_id ][1] = uvy
  181. else:
  182. ERROR( "The mesh \"" + mesh.name + "\" More than 1 coords for the " + str(vert_id) + " vert" )
  183. mesh.verts[vert_id].sel=1
  184. #return "error"
  185. print " %f %f %f %f" % ( vertuvs[ vert_id ][0], vertuvs[ vert_id ][1], uvx, uvy )
  186. # endif has UVs
  187. # now put the UVs in the ftxt
  188. if(b_cmnts): ftxt += "/*VERT_TEX_COORDS*/ "
  189. ftxt += str( len(vertuvs) ) + "\n"
  190. for i in range( 0, len(vertuvs) ):
  191. if(b_cmnts): ftxt += "\t/*VERT_ID " + str(i) + " UV_COORDS*/ "
  192. ftxt += str( vertuvs[i][0] ) + " " + str( vertuvs[i][1] ) + "\n"
  193. # and now the vertex weights
  194. if skeleton != NULL:
  195. ftxt += ScriptVWeights( mesh_init )
  196. else:
  197. if b_cmnts:
  198. ftxt += "/*VERT_WEIGHTS*/ "
  199. ftxt += "0"
  200. return ftxt
  201. #===================================================================================================
  202. # ExportMesh =
  203. #===================================================================================================
  204. def ExportMesh( mesh_init ):
  205. mesh = mesh_init.mesh
  206. skeleton = mesh_init.skeleton
  207. #check if mesh is the correct class
  208. if mesh.__class__.__name__ != "Blender Mesh":
  209. ERROR( "The given func param is not a \"Blender Mesh\" class but a \"" + mesh.__class__.__name__ + "\"" )
  210. return false
  211. if skeleton != NULL:
  212. #check if skeleton is the correct class
  213. if( skeleton.__class__.__name__ != "Armature" ):
  214. ERROR( "The given func param is not a \"Armature\" class but a \"" + skeleton.__class__.__name__ + "\"" )
  215. return false
  216. INFO( "Trying to export mesh \"" + mesh.name + "\"" )
  217. filename = mesh_init.save_path + mesh.name + ".mesh"
  218. WriteFile( filename, ScriptMesh( mesh_init ) )
  219. INFO( "Mesh exported!! \"" + filename + "\"" )