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