BPython:
[blender-staging.git] / release / scripts / DirectXExporter.py
1 #!BPY
2
3 """ Registration info for Blender menus:
4 Name: 'DirectX'
5 Blender: 232
6 Group: 'Export'
7 Submenu: 'Only mesh data...' mesh
8 Submenu: 'Animation(not armature yet)...' anim
9 Tip: 'Export to DirectX text file format format.'
10 """
11 # DirectX.py version 1.0
12 # Copyright (C) 2003  Arben OMARI -- aromari@tin.it 
13 #
14 # This program is free software; you can redistribute it and/or modify
15 # it under the terms of the GNU General Public License as published by
16 # the Free Software Foundation; either version 2 of the License, or
17 # (at your option) any later version.
18 #
19 # This program is distributed in the hope that it will be useful,
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 # GNU General Public License for more details.
23
24 # This script export meshes created with Blender in DirectX file format
25 # it exports meshes,materials,normals,texturecoords and and animations
26
27 # Grab the latest version here :www.omariben.too.it
28
29 import Blender
30 from Blender import Types, Object, NMesh, Material
31 #import string
32 from math import *
33
34
35
36         
37 #***********************************************
38 #***********************************************
39 #                EXPORTER
40 #***********************************************
41 #***********************************************
42
43 class xExport:
44         def __init__(self, filename):
45                 self.file = open(filename, "w")
46
47         #***********************************************
48         #  Export animations
49         #***********************************************
50         def exportAnim(self):
51                 tex = []
52                 print "exporting ..."
53                 self.writeHeader()
54                 for name in Object.Get():
55                         obj = name.getData()
56                         if type(obj) == Types.NMeshType :
57                                 self.writeMaterials(name,tex)   
58                                 self.writeFrames(name, obj)     
59                                 self.writeMeshcoord(name, obj )
60                                 self.writeMeshMaterialList(name, obj, tex)
61                                 self.writeMeshNormals(name, obj)
62                                 self.writeMeshTextureCoords(name, obj)
63                                 self.file.write("}\n")
64                                 self.file.write("}\n")
65                                 self.writeAnimation(name, obj)
66                         
67                 self.writeEnd()
68
69         #***********************************************
70         #  Export geometry
71         #***********************************************
72         def exportTex(self):
73                 tex = []
74                 print "exporting ..."
75                 self.writeHeader()
76                 for name in Object.Get():
77                         obj = name.getData()
78                         if type(obj) == Types.NMeshType :
79                                 self.writeMaterials(name,tex)           
80                                 self.writeMeshcoord(name, obj )
81                                 self.writeMeshMaterialList(name, obj, tex)
82                                 self.writeMeshNormals(name, obj)
83                                 self.writeMeshTextureCoords(name, obj)
84                                 self.file.write("}\n")
85
86                 self.writeEnd()
87     
88         #***********************************************
89         #HEADER
90         #***********************************************  
91         def writeHeader(self):
92                 self.file.write("xof 0302txt 0064\n")
93                 self.file.write("\n")
94                 self.file.write("Header{\n")
95                 self.file.write("1;0;1;\n")
96                 self.file.write("}\n")
97
98         #***********************************************
99         #CLOSE FILE
100         #***********************************************
101         def writeEnd(self):
102                 self.file.close()
103                 print "... finished"
104         #***********************************************
105         #EXPORT MATERIALS
106         #***********************************************
107         def writeMaterials(self,name,tex):
108                 for mat in Material.Get():
109                         self.file.write("Material")
110                         self.file.write(" %s "% (mat.name))
111                         self.file.write("{\n")
112                         self.file.write("%s; %s; %s;" % (mat.R, mat.G, mat.B))
113                         self.file.write("%s;;\n" % (mat.alpha))
114                         self.file.write("%s;\n" % (mat.spec))
115                         self.file.write("%s; %s; %s;;\n" % (mat.specR, mat.specG, mat.specB))
116                         self.file.write("0.0; 0.0; 0.0;;\n")
117                         self.file.write("TextureFilename {\n")
118                         self.file.write('none ;')
119                         self.file.write("}\n")
120                         self.file.write("}\n") 
121                 self.writeTextures(name, tex)
122                 
123
124         #***********************************************
125         #EXPORT TEXTURES
126         #***********************************************
127         def writeTextures(self,name, tex):
128                 mesh = name.data
129                 for face in mesh.faces:
130                         if face.image and face.image.name not in tex:
131                                 tex.append(face.image.name)
132                                 self.file.write("Material Mat")
133                                 self.file.write("%s "% (len(tex)))
134                                 self.file.write("{\n")
135                                 self.file.write("1.0; 1.0; 1.0; 1.0;;\n")
136                                 self.file.write("1.0;\n")
137                                 self.file.write("1.0; 1.0; 1.0;;\n")
138                                 self.file.write("0.0; 0.0; 0.0;;\n")
139                                 self.file.write("TextureFilename {\n")
140                                 self.file.write('"%s" ;'% (face.image.name))
141                                 self.file.write("}\n")
142                                 self.file.write("}\n") 
143                 
144
145         #***********************************************
146         #EXPORT MESH DATA
147         #***********************************************
148         def writeMeshcoord(self, name, obj ):
149                 
150                 self.file.write("Mesh Mesh_%s {\n" % (name.name))    
151                 numfaces=len(obj.faces)
152                 #POSITION
153                 loc = name.getMatrix()
154                 x = loc[3][0]
155                 y = loc[3][1]
156                 z = loc[3][2]
157                 #VERTICES NUMBER
158                 mesh = name.data
159                 numvert = 0
160                 for face in mesh.faces:
161                         numvert = numvert + len(face.v)
162                 self.file.write("%s;\n" % (numvert))
163                 #VERTICES COORDINATES
164                 counter = 0
165                 for face in mesh.faces:
166                         counter += 1
167                         if counter == numfaces:
168                                 if len(face.v) == 4:
169                                         self.file.write("%s; %s; %s;,\n" % ((face.v[0].co[0] + x), face.v[0].co[1] + y, face.v[0].co[2] + z))
170                                         self.file.write("%s; %s; %s;,\n" % ((face.v[1].co[0] + x), face.v[1].co[1] + y, face.v[1].co[2] + z))           
171                                         self.file.write("%s; %s; %s;,\n" % ((face.v[2].co[0] + x), face.v[2].co[1] + y, face.v[2].co[2] + z))
172                                         self.file.write("%s; %s; %s;;\n" % ((face.v[3].co[0] + x), face.v[3].co[1] + y, face.v[3].co[2] + z))
173                                 elif len(face.v) == 3 :
174                                         self.file.write("%s; %s; %s;,\n" % ((face.v[0].co[0] + x), face.v[0].co[1] + y, face.v[0].co[2] + z))
175                                         self.file.write("%s; %s; %s;,\n" % ((face.v[1].co[0] + x), face.v[1].co[1] + y, face.v[1].co[2] + z))           
176                                         self.file.write("%s; %s; %s;;\n" % ((face.v[2].co[0] + x), face.v[2].co[1] + y, face.v[2].co[2] + z))
177                                         
178                         else :
179                                 if len(face.v) == 4:
180                                         self.file.write("%s; %s; %s;,\n" % ((face.v[0].co[0] + x), face.v[0].co[1] + y, face.v[0].co[2] + z))
181                                         self.file.write("%s; %s; %s;,\n" % ((face.v[1].co[0] + x), face.v[1].co[1] + y, face.v[1].co[2] + z))           
182                                         self.file.write("%s; %s; %s;,\n" % ((face.v[2].co[0] + x), face.v[2].co[1] + y, face.v[2].co[2] + z))
183                                         self.file.write("%s; %s; %s;,\n" % ((face.v[3].co[0] + x), face.v[3].co[1] + y, face.v[3].co[2] + z))
184                                 elif len(face.v) == 3:
185                                         self.file.write("%s; %s; %s;,\n" % ((face.v[0].co[0] + x), face.v[0].co[1] + y, face.v[0].co[2] + z))
186                                         self.file.write("%s; %s; %s;,\n" % ((face.v[1].co[0] + x), face.v[1].co[1] + y, face.v[1].co[2] + z))           
187                                         self.file.write("%s; %s; %s;,\n" % ((face.v[2].co[0] + x), face.v[2].co[1] + y, face.v[2].co[2] + z))
188                                         
189
190
191                 #FACES NUMBER 
192                 
193                 self.file.write("%s;\n" % (numfaces))  
194                 #FACES INDEX
195                 numface=len(obj.faces)
196                 coun,counter = 0, 0
197                 for face in mesh.faces :
198                         coun += 1
199                         if coun == numface:
200                                 if len(face.v) == 3:
201                                         self.file.write("3; %s; %s; %s;;\n" % (counter, counter + 1, counter + 2))
202                                         counter += 3
203                                 else :
204                                         self.file.write("4; %s; %s; %s; %s;;\n" % (counter, counter + 1, counter + 2, counter + 3))
205                                         counter += 4
206                         else:
207                                 
208                                 if len(face.v) == 3:
209                                         self.file.write("3; %s; %s; %s;,\n" % (counter, counter + 1, counter + 2))
210                                         counter += 3
211                                 else :
212                                         self.file.write("4; %s; %s; %s; %s;,\n" % (counter, counter + 1, counter + 2, counter + 3))
213                                         counter += 4
214                 
215
216                 
217                 
218                 
219                 
220         #***********************************************
221         #MESH MATERIAL LIST
222         #***********************************************
223         def writeMeshMaterialList(self, name, obj, tex):
224                 self.file.write("//LET'S BEGIN WITH OPTIONAL DATA\n")
225                 self.file.write(" MeshMaterialList {\n")
226                 #HOW MANY MATERIALS ARE USED
227                 count = 0
228                 for mat in Material.Get():
229                         count+=1
230                 self.file.write("%s;\n" % (len(tex) + count))
231                 #HOW MANY FACES IT HAS
232                 numfaces=len(obj.faces)
233                 self.file.write("%s;\n" % (numfaces))
234                 ##MATERIALS INDEX FOR EVERY FACE
235                 counter = 0
236                 for face in obj.faces :
237                         counter += 1
238                         mater = face.materialIndex
239                         if counter == numfaces:
240                                 if face.image and face.image.name in tex :
241                                         self.file.write("%s;;\n" % (tex.index(face.image.name) + count))
242                                 else :
243                                         self.file.write("%s;;\n" % (mater))
244                         else :
245                                 if face.image and face.image.name in tex :
246                                         self.file.write("%s,\n" % (tex.index(face.image.name) + count))
247                                 else :
248                                         self.file.write("%s,\n" % (mater))
249                         
250                 ##MATERIAL NAME
251                 for mat in Material.Get():
252                         self.file.write("{%s}\n"% (mat.name))
253                 
254                 for mat in tex:
255                         self.file.write("{Mat")
256                         self.file.write("%s}\n"% (tex.index(mat) + 1))
257                 self.file.write("}\n")
258         #***********************************************
259         #MESH NORMALS
260         #***********************************************
261         def writeMeshNormals(self,name,obj):
262                 self.file.write(" MeshNormals {\n")
263                 #VERTICES NUMBER
264                 numvert=len(obj.verts)
265                 self.file.write("%s;\n" % (numvert))
266                 #VERTICES NORMAL
267                 counter = 0
268                 for vert in obj.verts:
269                         counter += 1  
270                         if counter == numvert:
271                                 self.file.write("%s; %s; %s;;\n" % (vert.no[0], vert.no[1], vert.no[2]))
272                         else :
273                                 self.file.write("%s; %s; %s;,\n" % (vert.no[0], vert.no[1], vert.no[2]))
274                 #FACES NUMBER 
275                 numfaces=len(obj.faces)
276                 self.file.write("%s;\n" % (numfaces))  
277                 #FACES INDEX
278                 counter = 0
279                 for face in obj.faces :
280                         counter += 1
281                         if counter == numfaces:
282                                 if len(face.v) == 3:
283                                         self.file.write("3; %s; %s; %s;;\n" % (face[0].index, face[1].index, face[2].index))
284                                 elif len(face.v) == 4:
285                                         self.file.write("4; %s; %s; %s; %s;;\n" % (face[0].index, face[1].index, face[2].index, face[3].index))
286                         else:
287                                 if len(face.v) == 3:
288                                         self.file.write("3; %s; %s; %s;,\n" % (face[0].index, face[1].index, face[2].index))
289                                 elif len(face.v) == 4 :
290                                         self.file.write("4; %s; %s; %s; %s;,\n" % (face[0].index, face[1].index, face[2].index, face[3].index))
291                 self.file.write("}\n")
292         #***********************************************
293         #MESH TEXTURE COORDS
294         #***********************************************
295         def writeMeshTextureCoords(self, name, obj):
296                         if obj.hasFaceUV():
297                                 self.file.write("MeshTextureCoords {\n")
298                                 #VERTICES NUMBER
299                                 mesh = name.data
300                                 numvert = 0
301                                 for face in mesh.faces:
302                                         numvert = numvert + len(face.v)
303                                 self.file.write("%s;\n" % (numvert))
304                                 #UV COORDS
305                                 counter = -1
306                                 for face in mesh.faces:
307                                         counter += 1
308                                         if len(face.v) == 4:
309                                                 self.file.write("%s;%s;,\n" % (mesh.faces[counter].uv[0][0], -mesh.faces[counter].uv[0][1]))
310                                                 self.file.write("%s;%s;,\n" % (mesh.faces[counter].uv[1][0], -mesh.faces[counter].uv[1][1]))
311                                                 self.file.write("%s;%s;,\n" % (mesh.faces[counter].uv[2][0], -mesh.faces[counter].uv[2][1]))
312                                                 self.file.write("%s;%s;,\n" % (mesh.faces[counter].uv[3][0], -mesh.faces[counter].uv[3][1]))
313                                         elif len(face.v) == 3:
314                                                 self.file.write("%s;%s;,\n" % (mesh.faces[counter].uv[0][0], -mesh.faces[counter].uv[0][1]))
315                                                 self.file.write("%s;%s;,\n" % (mesh.faces[counter].uv[1][0], -mesh.faces[counter].uv[1][1]))
316                                                 self.file.write("%s;%s;,\n" % (mesh.faces[counter].uv[2][0], -mesh.faces[counter].uv[2][1]))
317
318                                 self.file.write("}\n")
319
320         #***********************************************
321         #FRAMES
322         #***********************************************
323         def writeFrames(self, name, obj):
324                 matx = name.getMatrix()
325                 self.file.write("Frame Fr_")  
326                 self.file.write("%s {\n" % (obj.name))
327                 self.file.write(" FrameTransformMatrix {\n")
328                 self.file.write(" %s,%s,%s,%s,\n" %
329                                                         (round(matx[0][0],6),round(matx[0][1],6),round(matx[0][2],6),round(matx[0][3],6)))
330                 self.file.write(" %s,%s,%s,%s,\n" %
331                                                         (round(matx[1][0],6),round(matx[1][1],6),round(matx[1][2],6),round(matx[1][3],6)))
332                 self.file.write(" %s,%s,%s,%s,\n" %
333                                                         (round(matx[2][0],6),round(matx[2][1],6),round(matx[2][2],6),round(matx[2][3],6)))
334                 self.file.write(" %s,%s,%s,%s;;\n" %
335                                                         (round(matx[3][0],6),round(matx[3][1],6),round(matx[3][2],6),round(matx[3][3],6)))
336                 self.file.write(" }\n")
337         #***********************************************
338         #WRITE ANIMATION KEYS
339         #***********************************************
340         def writeAnimation(self, name, obj):
341                 startFr = Blender.Get('staframe')
342                 endFr = Blender.Get('endframe')
343                 self.file.write("AnimationSet animset_")
344                 self.file.write("%s {\n" % (obj.name))
345                 self.file.write(" Animation anim_")
346                 self.file.write("%s { \n" % (obj.name))
347                 self.file.write("  {Fr_")
348                 self.file.write("%s }\n" % (obj.name))
349                 self.file.write("   AnimationKey { \n")
350                 self.file.write("   0;\n")
351                 self.file.write("   %s; \n" % (endFr))
352                 for fr in range(startFr,endFr + 1) :
353                         self.file.write("   %s; " % (fr))
354                         self.file.write("4; ")
355                         Blender.Set('curframe',fr)
356                         rot = name.rot
357                         rot_x = rot[0]
358                         rot_y = rot[1]
359                         rot_z = rot[2]
360                         quat = self.euler2quat(rot_x,rot_y,rot_z)
361                         self.file.write("%s, %s, %s,%s;;" % 
362                                                         (quat[0],quat[1],quat[2],quat[3]))
363                         if fr == endFr:
364                                 self.file.write(";\n")
365                         else:
366                                 self.file.write(",\n")
367                 self.file.write("   }\n")
368                 self.file.write("   AnimationKey { \n")
369                 self.file.write("   2;\n")
370                 self.file.write("   %s; \n" % (endFr))
371                 for fr in range(startFr,endFr + 1) :
372                         self.file.write("   %s; " % (fr))
373                         self.file.write("3; ")
374                         Blender.Set('curframe',fr)
375                         loc = name.loc
376                         self.file.write("%s, %s, %s;;" %
377                                                         (loc[0],loc[1],loc[2]))
378                         if fr == endFr:
379                                 self.file.write(";\n")
380                         else:
381                                 self.file.write(",\n")
382                 self.file.write("   }\n")
383                 self.file.write("   AnimationKey { \n")
384                 self.file.write("   1;\n")
385                 self.file.write("   %s; \n" % (endFr))
386                 for fr in range(startFr,endFr + 1) :
387                         self.file.write("   %s; " % (fr))
388                         self.file.write("3; ")
389                         Blender.Set('curframe',fr)
390                         size = name.size
391                         self.file.write("%s, %s, %s;;" %
392                                                         (size[0],size[1],size[2]))
393                         if fr == endFr:
394                                 self.file.write(";\n")
395                         else:
396                                 self.file.write(",\n")
397                 self.file.write("   }\n")
398                 self.file.write("  }\n")
399                 self.file.write(" }\n")
400
401         def euler2quat(self,rot_x,rot_y,rot_z):
402                 c_x = cos(rot_x / 2)
403                 c_y = cos(rot_y / 2)
404                 c_z = cos(rot_z / 2)
405
406                 s_x = sin(rot_x / 2)
407                 s_y = sin(rot_y / 2)
408                 s_z = sin(rot_z / 2)
409
410                 cy_cz = c_y * c_z
411                 sy_sz = s_y * s_z
412  
413                 quat_w = c_x * cy_cz - s_x * sy_sz
414                 quat_x = s_x * cy_cz + c_x * sy_sz
415                 quat_y = c_x * s_y * c_z - s_x * c_y * s_z
416                 quat_z = c_x * c_y * s_z + s_x * s_y * c_z
417
418                 return(quat_w,quat_x,quat_y,quat_z)
419
420 #***********************************************
421 # MAIN
422 #***********************************************
423
424         
425 def my_callback(filename):
426         if filename.find('.x', -2) <= 0: filename += '.x' # add '.x' if the user didn't
427         xexport = xExport(filename)
428         arg = __script__['arg']
429         if arg == 'anim':
430                 xexport.exportAnim()
431         else:
432                 xexport.exportTex()
433
434 Blender.Window.FileSelector(my_callback, "Export DirectX")