Merged 15170:15635 from trunk (no conflicts or even merges)
[blender.git] / release / scripts / DirectX8Exporter.py
1 #!BPY
2
3 """
4 # Name: 'DirectX (.x)...'
5 # Blender: 242
6 # Group: 'Export'
7 # Tooltip: 'Export to DirectX text file format format for XNA Animation Component Library.'
8 """
9 __author__ = "vertex color exporting feature is added by mnemoto (original:minahito (original:Arben (Ben) Omari))"
10 __url__ = ("blender", "elysiun", "Adjuster's site http://sunday-lab.blogspot.com/, Author's site http://www.omariben.too.it","Adjuster's site http://ex.homeunix.net/")
11 __version__ = "3.1"
12
13 __bpydoc__ = """\
14 This script exports a Blender mesh with armature to DirectX 8's text file
15 format.
16
17 Notes:<br>
18     Check author's site or the elYsiun forum for a new beta version of the
19 DX exporter.
20 """
21 # DirectXExporter.py version 3.0
22 # Copyright (C) 2006  Arben OMARI -- omariarben@everyday.com 
23 #
24 # This program is free software; you can redistribute it and/or modify
25 # it under the terms of the GNU General Public License as published by
26 # the Free Software Foundation; either version 2 of the License, or
27 # (at your option) any later version.
28 #
29 # This program is distributed in the hope that it will be useful,
30 # but WITHOUT ANY WARRANTY; without even the implied warranty of
31 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
32 # GNU General Public License for more details.
33
34 # This script export meshes created with Blender in DirectX8 file format
35 # it exports meshes,armatures,materials,normals,texturecoords and animations
36
37 # Grab the latest version here :www.omariben.too.it
38
39 # [Notice]
40 # This script is the custom version of Mr.Arben Omari's great work.
41 # If you have a question about the adjusted part, visit http://sunday-lab.blogspot.com/.
42
43 import Blender
44 from Blender import Types, Object, NMesh, Material,Armature,Mesh
45 from Blender.Mathutils import *
46 from Blender import Draw, BGL
47 from Blender.BGL import *
48 import math
49
50 global mat_flip,index_list,space,bone_list,mat_dict
51 global anim,flip_norm,swap_zy,flip_z,speed,ticks,no_light,recalc_norm,Bl_norm
52 bone_list =[]
53 index_list = []
54 mat_dict = {}
55 space = 0;flip_z = 1;anim=0;swap_yz=0;flip_norm=0;speed=0;ticks= 25
56 Bl_norm = 1;recalc_norm = 0;no_light = 0
57
58 toggle_val = 0
59 toggle1_val = 0
60 toggle2_val = 0
61 toggle3_val = 1
62 toggle4_val = 0
63 toggle5_val = 1
64 toggle6_val = 0
65 toggle7_val = 0
66 anim_tick = Draw.Create(25)
67
68 #***********************************************
69 # DirectX file spec only allows letters, digits, and 
70 # underscore in Names.
71 #***********************************************
72 def make_legal_name(starting_name):
73     new_name = starting_name.replace('.','_')
74     new_name = new_name.replace(' ','_')
75     if new_name[0].isdigit():
76         new_name = '_' + new_name
77     return new_name
78
79 #***********************************************
80 # MAIN
81 #***********************************************
82
83 def my_callback(filename):
84         if filename.find('.x', -2) <= 0: filename += '.x' 
85         xexport = xExport(filename)
86         xexport.SelectObjs()
87
88 def my_callback_sel(filename):
89         if filename.find('.x', -2) <= 0: filename += '.x' 
90         xexport = xExport(filename)
91         xexport.exportSelMesh()
92 def event(evt, val):    
93                 if evt == Draw.ESCKEY:
94                         Draw.Exit()                
95                         return
96
97 def button_event(evt): 
98         global toggle_val,toggle1_val,toggle2_val,toggle3_val,toggle4_val,toggle5_val,toggle6_val,toggle7_val
99         global flip_z,swap_yz,flip_norm,anim,ticks,speed,no_light,Bl_norm,recalc_norm
100         arg = __script__['arg']
101         if evt == 1:
102                 toggle_val = 1 - toggle_val
103                 anim = toggle_val
104                 Draw.Redraw(1)
105         if evt == 2:
106                 toggle1_val = 1 - toggle1_val
107                 flip_norm = toggle1_val
108                 Draw.Redraw(1)
109         if evt == 3:
110                 toggle2_val = 1 - toggle2_val
111                 swap_yz = toggle2_val
112                 Draw.Redraw(1)
113         if evt == 4:
114                 toggle3_val = 1 - toggle3_val
115                 flip_z = toggle3_val
116                 Draw.Redraw(1)
117         if evt == 5:
118                 toggle4_val = 1 - toggle4_val
119                 speed = toggle4_val
120                 Draw.Redraw(1)
121         if evt == 10:
122                 toggle5_val = 1 - toggle5_val
123                 if toggle5_val==1:
124                         toggle6_val = 0
125                         toggle7_val = 0
126                 else :
127                         toggle6_val = 1
128                         toggle7_val = 1
129                 no_light = toggle7_val
130                 recalc_norm = toggle6_val
131                 Bl_norm = toggle5_val
132                 Draw.Redraw(1)
133         if evt == 11:
134                 toggle6_val = 1 - toggle6_val
135                 if toggle6_val==1:
136                         toggle5_val = 0
137                         toggle7_val = 0
138                 else :
139                         toggle5_val = 1
140                         toggle7_val = 1
141                 no_light = toggle7_val
142                 recalc_norm = toggle6_val
143                 Bl_norm = toggle5_val
144                 Draw.Redraw(1)
145         if evt == 12:
146                 toggle7_val = 1 - toggle7_val
147                 if toggle7_val==1:
148                         toggle6_val = 0
149                         toggle5_val = 0
150                 else :
151                         toggle6_val = 1
152                         toggle5_val = 1
153                 no_light = toggle7_val
154                 recalc_norm = toggle6_val
155                 Bl_norm = toggle5_val
156                 Draw.Redraw(1)
157         if evt == 6:
158                 ticks = anim_tick.val
159         if evt == 7:
160                 fname = Blender.sys.makename(ext = ".x")
161                 Blender.Window.FileSelector(my_callback, "Export DirectX", fname)
162         if evt == 8:
163                 fname = Blender.sys.makename(ext = ".x")
164                 Blender.Window.FileSelector(my_callback_sel, "Export DirectX", fname)
165         if evt == 9:
166                 Draw.Exit()
167                 
168         
169 def draw():
170                 global animsg,flipmsg,swapmsg,anim_tick
171                 global flip_z,swap_yz,flip_norm,anim,ticks,speed,recalc_norm,Bl_norm,no_light
172                 glClearColor(0.55,0.6,0.6,1)
173                 glClear(BGL.GL_COLOR_BUFFER_BIT)
174                 #external box
175                 glColor3f(0.2,0.3,0.3)
176                 rect(10,402,300,382)
177                 #--
178                 #glColor3f(0.3,0.4,0.4)
179                 #rect(11,399,298,398)
180                 #--
181                 glColor3f(0.5,0.75,0.65)
182                 rect(14,398,292,30)
183                 #--
184                 glColor3f(0.5,0.75,0.65)
185                 rect(14,366,292,160)
186                 #--
187                 glColor3f(0.5,0.75,0.65)
188                 rect(14,202,292,60)
189                 #--
190                 glColor3f(0.5,0.75,0.65)
191                 rect(14,138,292,40)
192                 #--
193                 glColor3f(0.5,0.75,0.65)
194                 rect(14,94,292,70)
195                 
196                 glColor3f(0.8,.8,0.6)
197                 glRasterPos2i(20, 380)
198                 Draw.Text("DirectX Exporter ",'large')
199                 Draw.Text("(for Blender 2.41)", 'small')
200                 #-------Aniamtion toggle---------------------------------------------
201                 Draw.Toggle("Anim", 1, 20, 330, 55, 20, toggle_val,"export animations")
202                 if toggle_val :
203                         anim = 1
204                         animsg = "animation will be exported"
205                 else:
206                         anim = 0
207                         animsg = "animation will be not exported"
208                 glRasterPos2i(100,335)
209                 Draw.Text(animsg)
210                 #---Flip normals toggle-----------------------------------------------
211                 Draw.Toggle("Flip norm", 2, 20, 300, 55, 20, toggle1_val,"invert normals")
212                 if toggle1_val :
213                         flip_norm = 1
214                         flipmsg = "flipped normals"
215                 else:
216                         flip_norm = 0
217                         flipmsg = "not flipped normals"
218                 glRasterPos2i(100,305)
219                 Draw.Text(flipmsg)
220                 #------Swap yz toggle----------------------------------------------------------------
221                 Draw.Toggle("Swap zy", 3, 20, 270, 55, 20, toggle2_val,"swap z,y axis(y up)")
222                 if toggle2_val :
223                         swap_yz = 1
224                         swapmsg = "Y-axis up"
225                 else:
226                         swap_yz = 0
227                         swapmsg = "Z-axis up"
228                 glRasterPos2i(100,275)
229                 Draw.Text(swapmsg)
230                 #------Flip z toggle----------------------------------------------------------------
231                 Draw.Toggle("Flip z", 4, 20, 240, 55, 20, toggle3_val,"flip z axis")
232                 if toggle3_val :
233                         flip_z = 1
234                         zmsg = "left handed system"
235                 else:
236                         flip_z = 0
237                         zmsg = "right handed system"
238                 glRasterPos2i(100,245)
239                 Draw.Text(zmsg)
240                 #------Speed toggle----------------------------------------------------------------
241                 Draw.Toggle("Speed", 5, 20, 210, 55, 20, toggle4_val,"Animation speed")
242                 if toggle4_val :
243                         speed = 1
244                         spedmsg = "set speed"
245                         anim_tick = Draw.Number("", 6,200, 210, 85, 20, anim_tick.val,1,100000,"ticks per second")
246                 else:
247                         speed = 0
248                         spedmsg = ""
249                 glRasterPos2i(100,215)
250                 Draw.Text(spedmsg)
251                 #------Blender Normals toggle----------------------------------------------------------------
252                 Draw.Toggle("Bl.normals", 10, 20, 105, 75, 25, toggle5_val,"export normals as in Blender")
253                 if toggle5_val :
254                         Bl_norm = 1
255                 #------Recalculute Normals toggle----------------------------------------------------------------
256                 Draw.Toggle("recalc.no", 11, 120, 105, 75, 25, toggle6_val,"export recalculated normals")
257                 if toggle6_val :
258                         recalc_norm = 1
259                 #------Recalculute Normals toggle----------------------------------------------------------------
260                 Draw.Toggle("no smooth", 12, 220, 105, 75, 25, toggle7_val,"every vertex has the face normal,no smoothing")
261                 if toggle7_val :
262                         no_light = 1
263                 #------Draw Button export----------------------------------------------------------------
264                 exp_butt = Draw.Button("Export All",7,20, 155, 75, 30, "export all the scene objects")
265                 sel_butt = Draw.Button("Export Sel",8,120, 155, 75, 30, "export the selected object")
266                 exit_butt = Draw.Button("Exit",9,220, 155, 75, 30, "exit")
267                 glRasterPos2i(20,75)
268                 Draw.Text("(C) 2006  Arben OMARI ")
269                 glRasterPos2i(20,55)
270                 Draw.Text("http://www.omariben.too.it")
271                 glRasterPos2i(20,35)
272                 Draw.Text("aromar@tin.it")
273                 
274 def rect(x,y,width,height):
275                 glBegin(GL_LINE_LOOP)
276                 glVertex2i(x,y)
277                 glVertex2i(x+width,y)
278                 glVertex2i(x+width,y-height)
279                 glVertex2i(x,y-height)
280                 glEnd()
281                 
282 def rectFill(x,y,width,height):
283                 glBegin(GL_POLYGON)
284                 glVertex2i(x,y)
285                 glVertex2i(x+width,y)
286                 glVertex2i(x+width,y-height)
287                 glVertex2i(x,y-height)
288                 glEnd()
289                 
290                 
291                 
292 Draw.Register(draw, event, button_event)
293
294
295 #***********************************************
296 #***********************************************
297 #                EXPORTER
298 #***********************************************
299 #***********************************************
300
301 class xExport:
302         def __init__(self, filename):
303                 self.file = open(filename, "w")
304
305 #*********************************************************************************************************************************************
306         #***********************************************
307         #Select Scene objects
308         #***********************************************
309         def analyzeScene(self):
310                         parent_list = []
311                         for obj in Blender.Scene.GetCurrent().objects:
312                                 if obj.type in ('Mesh', 'Armature', 'Empty'):
313                                         if obj.parent == None :
314                                                 parent_list.append(obj)
315                                                 
316                         return parent_list
317                 
318         def getChildren(self,obj):      
319                 obs = Blender.Scene.GetCurrent().objects
320                 return [ ob for ob in obs if ob.parent == obj ]
321         
322         def getArmChildren(self,obj):           
323                 for ob in Blender.Scene.GetCurrent().objects: #Object.Get():
324                         if ob.parent == obj :
325                                 return ob
326         
327         def getLocMat(self, obj):
328                 pare = obj.parent
329                 mat = obj.matrixWorld
330                 mat_id = Matrix([1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1])
331                 if pare:
332                         mat_p = pare.matrixWorld
333                         mat_c = Matrix(mat_p)
334                         mat_c.invert()
335                         mat_f = mat * mat_c
336                 else :
337                         mat_id.invert()
338                         mat_f = mat * mat_id
339                 return mat_f
340         
341         def writeObjFrames(self,obj):
342                 global space,chld_obj,ch_list
343                 mesh = obj.getData()
344                 if obj.type == "Empty" :
345                         mat = self.getLocMat(obj)
346                         mat_c = Matrix(mat)
347                         self.writeArmFrames(mat_c, make_legal_name(obj.name))
348                 if type(mesh) == Types.ArmatureType :
349                         Child_obj = self.getArmChildren(obj)
350                         chld_obj = obj
351                         ch_list.append(Child_obj)
352                         self.writeRootBone(obj, Child_obj)      
353                 if obj.type == 'Mesh' and obj not in ch_list:
354                         self.exportMesh(obj)
355                         
356                         
357         def writeChildObj(self,obj):
358                 global space,ch_list
359                 space += 1
360                 if obj :
361                         for ob in obj:
362                                 if ob not in ch_list:
363                                         self.writeObjFrames(ob)
364                                         ch_list.append(ob)
365                                         ch_ob = self.getChildren(ob)
366                                         self.writeChildObj(ch_ob)
367                                         self.closeBrackets()
368                                         self.file.write(" // End of the Object %s \n" % (ob.name))
369                                         
370                                         
371         def writeRootFrame(self):
372                 global flip_z,swap_yz,speed
373                 if speed:
374                         self.writeAnimTicks()
375                 if flip_z:
376                         mat_flip = Matrix([1, 0, 0, 0], [0, 1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1])
377                 else :
378                         mat_flip = Matrix([1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1])
379                 if swap_yz :
380                         mat_rot = RotationMatrix(-90, 4, 'x')
381                         mat_flip = mat_rot * mat_flip
382                 self.writeArmFrames(mat_flip, "RootFrame")              
383                         
384         ##################################################################      
385         def SelectObjs(self):
386                 global space,chld_obj,ch_list,flip_z,swap_yz,speed
387                 print "exporting..."
388                 self.writeHeader()
389                 self.writeRootFrame()
390                 obj_list = self.analyzeScene()
391                 space += 1
392                 ch_list = []
393                 for obj in obj_list:
394                         self.writeObjFrames(obj)
395                         ch_l = self.getChildren(obj)
396                         for ch in ch_l:
397                         
398                         
399                                 if ch and ch.type == "Armature":
400                                         ch_list.append(ch)
401                                         self.writeObjFrames(ch)
402                                 else :  
403                                         self.writeChildObj(ch_l)
404                         if obj.type != "Armature":
405                                 self.file.write("  }  // SI End of the Object %s \n" % (obj.name))      
406                                 
407                                 
408                                 
409                 self.file.write("}  // End of the Root Frame\n")                
410                 if anim :
411                         self.file.write("AnimationSet AnimationSet0 {\n")
412                         for obj in Blender.Scene.GetCurrent().objects:
413                                 if obj.type in ('Mesh', 'Empty'):
414                                         ip_list = obj.ipo
415                                         if ip_list != None :
416                                                 self.writeAnimationObj(obj)
417                                 elif obj.type == 'Armature':
418                                         act_list = obj.getAction()
419                                         if act_list != None :
420                                                 self.writeAnimation(obj)
421                                         #ip_list = obj.ipo
422                                         #if ip_list != None :
423                                         #       self.writeAnimationObj(obj)
424
425                         self.file.write("} // End of Animation Set\n")
426                 self.writeEnd()
427                 #######################################################
428                 
429                                 
430         def writeAnimTicks(self):
431                 global ticks
432                 self.file.write("AnimTicksPerSecond {\n")
433                 self.file.write("%d; \n" % (ticks))
434                 self.file.write("}\n")
435         
436         #***********************************************
437         #Export Mesh without Armature
438         #***********************************************
439         def exportMesh(self, obj):
440                 tex = []
441                 mesh = obj.getData()
442                 self.writeTextures(obj, tex)            
443                 self.writeMeshcoordArm(obj, arm_ob = None)
444                 self.writeMeshMaterialList(obj, mesh, tex)
445                 self.writeMeshNormals(obj, mesh)
446                 self.writeMeshTextureCoords(obj, mesh)
447                 self.writeMeshVertexColors(obj, mesh)
448                 self.file.write("  }  // End of the Mesh %s \n" % (obj.name))
449                 
450                                         
451         #***********************************************
452         #Export the Selected Mesh
453         #***********************************************
454         def exportSelMesh(self):
455                 print "exporting ..."
456                 self.writeHeader()
457                 self.writeRootFrame()
458                 tex = []
459                 objs = Object.GetSelected()
460                 for obj in objs:
461                         if obj.type == 'Mesh':
462                                 mesh = obj.data
463                                 self.writeTextures(obj, tex)            
464                                 self.writeMeshcoordArm(obj, arm_ob = None)
465                                 self.writeMeshMaterialList(obj, mesh, tex)
466                                 self.writeMeshNormals(obj, mesh)
467                                 self.writeMeshTextureCoords(obj, mesh)
468                                 self.writeMeshVertexColors(obj, mesh)
469                                 self.file.write(" }\n")
470                                 self.file.write("}\n")
471                                 ind = objs.index(obj)
472                                 if ind == len(objs)-1:
473                                         self.file.write("}\n")
474                                 ip_list = obj.ipo
475                                 if ip_list != None :
476                                         self.file.write("AnimationSet AnimationSet0 {\n")
477                                         self.writeAnimationObj(obj)
478                                         self.file.write("}\n")
479                         else :
480                                 print "The selected object is not a mesh"
481                 print "...finished"
482         #***********************************************
483         #Export Mesh with Armature
484         #***********************************************
485         def exportMeshArm(self,arm,arm_ob,ch_obj):
486                 tex = []
487                 mesh = ch_obj.getData()
488                 self.writeTextures(ch_obj, tex)         
489                 self.writeMeshcoordArm(ch_obj ,arm_ob)
490                 self.writeMeshMaterialList(ch_obj, mesh, tex)
491                 self.writeMeshNormals(ch_obj, mesh)
492                 self.writeMeshTextureCoords(ch_obj, mesh)
493                 self.writeSkinWeights(arm,mesh)
494                 #self.file.write("  }  // End of the Frame %s \n" % (ch_obj.name))
495                 self.file.write("  }  // End of the Object %s \n" % (ch_obj.name))
496                                 
497         #***********************************************
498         #Export Root Bone
499         #***********************************************
500         def writeRootBone(self, chld_obj,  child_obj):
501                 global space,root_bon
502                 arms = chld_obj.getData()
503                 mat_arm = self.getLocMat(chld_obj)
504                 for bon in arms.bones.values():
505                         if bon.hasParent():
506                                 pass
507                         else:
508                                 root_bon = bon
509                 space += 1
510                 mat_r = self.writeAnimCombineMatrix(root_bon,1)
511                 self.writeArmFrames(mat_r, make_legal_name(root_bon.name))
512                 
513                 bon_c = root_bon.children
514                 self.writeChildren(bon_c)
515                 self.file.write("  }  // End of the Bone %s \n" % (root_bon.name))      
516                 self.exportMeshArm(arms, chld_obj ,child_obj)
517                         
518         #***********************************************
519         #Create Children structure
520         #***********************************************
521         def writeBon(self,bon):
522                 global space
523                 mat_r = self.writeAnimCombineMatrix(bon,1)
524                 self.writeArmFrames(mat_r, make_legal_name(bon.name))
525                 
526         
527         def writeChildren(self,bon_c):
528                 global space,bone_list
529                 space += 1
530                 if bon_c:
531                         for bo in bon_c:
532                                 if bo.name not in bone_list:
533                                         self.writeBon(bo)
534                                         bone_list.append(bo.name)
535                                         bo_c = bo.children 
536                                         self.writeChildren(bo_c)
537                                         self.closeBrackets()
538                                 
539                                 
540                                         
541         def closeBrackets(self):
542                 global space
543                 space = space-1
544                 tab = "  "
545                 self.file.write("%s" % (tab * space))
546                 self.file.write("}\n")
547                 
548                 
549                         
550         #***********************************************
551         #Offset Matrix
552         #***********************************************
553         def writeMatrixOffset(self,bon):
554                 global  chld_obj
555                 Blender.Set('curframe', 1)
556                 pose = chld_obj.getPose()
557                 pos_b = pose.bones[bon.name]
558                 mat_b = pos_b.poseMatrix
559                 mat_c = Matrix(mat_b)
560                 mat_c.invert()
561                 return mat_c
562
563         
564         #***********************************************
565         #Combine Matrix
566         #***********************************************
567         def writeCombineMatrix(self,bon):
568                 global  chld_obj
569                 
570                 Blender.Set('curframe', 1)
571                 pose = chld_obj.getPose()
572                 pos_b = pose.bones[bon.name]
573                 mat_b = pos_b.poseMatrix
574                 if bon.hasParent():
575                         pare = bon.parent
576                         pos_p = pose.bones[pare.name]
577                         mat_p = pos_p.poseMatrix
578                         
579                 else:
580                         mat_p = Matrix([1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1])
581                 mat_c = Matrix(mat_p)
582                 mat_c.invert()
583                 mat_f = mat_b * mat_c
584                 
585                 return mat_f
586         #***********************************************
587         #Combine Matrix
588         #***********************************************
589         def writeAnimCombineMatrix(self,bon,fre):
590                 global  chld_obj
591                 Blender.Set('curframe', fre)
592                 pose = chld_obj.getPose()
593                 pos_b = pose.bones[bon.name]
594                 mat_b = pos_b.poseMatrix
595                 if bon.hasParent():
596                         pare = bon.parent
597                         pos_p = pose.bones[pare.name]
598                         mat_p = pos_p.poseMatrix
599                         
600                 else:
601                         mat_p = Matrix([1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1])
602                 mat_c = Matrix(mat_p)
603                 mat_c.invert()
604                 mat_f = mat_b * mat_c
605                 
606                 return mat_f
607
608
609 #*********************************************************************************************************************************************
610         #***********************************************
611         #Write SkinWeights
612         #***********************************************
613         def writeSkinWeights(self, arm, mesh):
614                 global index_list
615                 v_dict = {}
616                 Blender.Set('curframe',1)
617                 self.file.write("  XSkinMeshHeader {\n")
618                 max_infl = 0
619                 for bo in arm.bones.values() :
620                         name = bo.name
621                         try :
622                                 vertx_list = mesh.getVertsFromGroup(name,1)
623                                 for inde in vertx_list :
624                                         vert_infl = mesh.getVertexInfluences(inde[0])
625                                         ln_infl = len(vert_infl)
626                                         if ln_infl > max_infl :
627                                                 max_infl = ln_infl
628                                 
629                         except:
630                                 pass
631                 
632                 self.file.write("    %d; \n" % (max_infl))
633                 self.file.write("    %d; \n" % (max_infl * 3))
634                 self.file.write("    %d; \n" % (len(arm.bones.values())))
635                 self.file.write("  }\n")
636                 
637                 for bo in arm.bones.values() :
638                         bo_list = []
639                         weight_list = []
640                         name = bo.name 
641                         f_name = make_legal_name(name)
642                         try :
643                                 vert_list = mesh.getVertsFromGroup(name,1)
644                                 le = 0
645                                 for indx in vert_list:
646                                         ver_infl = mesh.getVertexInfluences(indx[0])
647                                         infl = 0.0
648                                         if len(ver_infl) != 0:
649                                                 sum = 0.0
650                                                 for bone_n, weight in ver_infl:
651                                                         if bone_n == name:
652                                                                 infl = weight
653                                                         sum += weight
654                                                 infl /= sum
655                                         
656                                         i = -1
657                                         for el in index_list :
658                                                 i += 1
659                                                 if el == indx[0] :
660                                                         le +=1
661                                                         bo_list.append(i)
662                                                         weight_list.append(infl)
663
664
665                                 self.file.write("  SkinWeights {\n")
666                                 self.file.write('    "%s"; \n' % (f_name))
667                                 self.file.write('     %d; \n' % (le))
668                                 count = 0
669                                 for ind in bo_list :
670                                         count += 1
671                                         if count == len(bo_list):
672                                                 self.file.write("    %d; \n" % (ind))
673                                         else :
674                                                 self.file.write("    %d, \n" % (ind))
675                                 cou = 0
676                                 for wegh in weight_list :
677                                         cou += 1
678                                         
679                                         if cou == len(weight_list):
680                                                 self.file.write("    %f; \n" % (round(wegh,6)))
681                                         else :
682                                                 self.file.write("    %f, \n" % (round(wegh,6)))
683
684                         
685                                 matx = self.writeMatrixOffset(bo)
686                                 self.writeOffsFrames(matx, name)
687                         except :
688                                 pass
689                 self.file.write("  } // End of XSkinMeshHeader\n")
690                 
691
692         #***********************************************
693         # Write Matrices
694         #***********************************************
695         def writeArmFrames(self, matx, name):
696                 global space
697                 tab = "  "
698                 self.file.write("%s" % (tab * space))
699                 self.file.write("Frame ")  
700                 self.file.write("%s {\n\n" % (name))
701                 self.file.write("%s" % (tab * space))
702                 self.file.write("  FrameTransformMatrix {\n")
703                 self.writeFrame(matx)
704         
705         #***********************************************
706         # Write Frames
707         #***********************************************
708         def writeOffsFrames(self, matx, name):
709                 space = 1
710                 self.writeFrame(matx)
711         
712          #***********************************************
713         # Write Frames
714         #***********************************************
715         def writeFrame(self, matx):
716                 tab = "  "
717                 self.file.write("%s" % (tab * space))
718                 self.file.write("    %f,%f,%f,%f,\n" %
719                                                         (round(matx[0][0],4),round(matx[0][1],4),round(matx[0][2],4),round(matx[0][3],4)))
720                 self.file.write("%s" % (tab * space))
721                 self.file.write("    %f,%f,%f,%f,\n" %
722                                                         (round(matx[1][0],4),round(matx[1][1],4),round(matx[1][2],4),round(matx[1][3],4)))
723                 self.file.write("%s" % (tab * space))   
724                 self.file.write("    %f,%f,%f,%f,\n" %
725                                                         (round(matx[2][0],4),round(matx[2][1],4),round(matx[2][2],4),round(matx[2][3],4)))
726                 self.file.write("%s" % (tab * space))
727                 self.file.write("    %f,%f,%f,%f;;\n" %
728                                                         (round(matx[3][0],4),round(matx[3][1],4),round(matx[3][2],4),round(matx[3][3],4)))
729                 self.file.write("%s" % (tab * space))
730                 self.file.write("  }\n")
731 #*********************************************************************************************************************************************
732         
733         #***********************************************
734         #HEADER
735         #***********************************************  
736         def writeHeader(self):
737                 self.file.write("xof 0303txt 0032\n\n\n")
738                 self.file.write("template VertexDuplicationIndices { \n\
739  <b8d65549-d7c9-4995-89cf-53a9a8b031e3>\n\
740  DWORD nIndices;\n\
741  DWORD nOriginalVertices;\n\
742  array DWORD indices[nIndices];\n\
743 }\n\
744 template XSkinMeshHeader {\n\
745  <3cf169ce-ff7c-44ab-93c0-f78f62d172e2>\n\
746  WORD nMaxSkinWeightsPerVertex;\n\
747  WORD nMaxSkinWeightsPerFace;\n\
748  WORD nBones;\n\
749 }\n\
750 template SkinWeights {\n\
751  <6f0d123b-bad2-4167-a0d0-80224f25fabb>\n\
752  STRING transformNodeName;\n\
753  DWORD nWeights;\n\
754  array DWORD vertexIndices[nWeights];\n\
755  array float weights[nWeights];\n\
756  Matrix4x4 matrixOffset;\n\
757 }\n\n")
758                 
759         #***********************************************
760         #CLOSE FILE
761         #***********************************************
762         def writeEnd(self):
763                 self.file.close()
764                 print "... finished"
765
766
767         #***********************************************
768         #EXPORT TEXTURES
769         #***********************************************
770         def writeTextures(self,name, tex):
771                 mesh = name.data
772                 for face in mesh.faces:
773                         if face.image and face.image.name not in tex:
774                                 tex.append(face.image.name)
775                                 
776
777
778         #***********************************************
779         #EXPORT MESH DATA with Armature
780         #***********************************************
781         def writeMeshcoordArm(self, obj ,arm_ob):
782                 global index_list,flip_z
783                 #TransformMatrix
784                 mat = self.getLocMat(obj)
785                 self.writeArmFrames(mat, make_legal_name(obj.name))
786                 mesh = NMesh.GetRawFromObject(obj.name)
787                 self.file.write("Mesh {\n")    
788                 numface=len(mesh.faces)
789                 #VERTICES NUMBER
790                 numvert = 0
791                 for face in mesh.faces:
792                         numvert = numvert + len(face.v)
793                 self.file.write("%d;\n" % (numvert))
794                 if numvert == 0:
795                         print "Mesh named",mesh.name,"has no vertices.Problems may occur using the .x file"
796                 #VERTICES COORDINATES
797                 counter = 0
798                 for face in mesh.faces:
799                         counter += 1
800                         for n in range(len(face.v)):
801                                 index_list.append(face.v[n].index)
802                                 vec_vert = Vector([(face.v[n].co[0]), face.v[n].co[1], face.v[n].co[2], 1])
803                                 if arm_ob :
804                                         f_vec_vert = vec_vert * mat
805                                 else :
806                                         f_vec_vert = vec_vert
807                                 self.file.write("%f; %f; %f;" % (round(f_vec_vert[0],4), round(f_vec_vert[1],4), round(f_vec_vert[2],4)))
808                                 if counter == numface :
809                                         if n == len(face.v)-1 :
810                                                 self.file.write(";\n")
811                                         else :
812                                                 self.file.write(",\n")
813                                 else :
814                                         self.file.write(",\n")
815                 if flip_z:
816                         a3 = 0;b3 = 2;c3 = 1
817                         a4 = 0;b4 = 3;c4 = 2;d4 = 1
818                 else:
819                         a3 = 0;b3 = 1;c3 = 2
820                         a4 = 0;b4 = 1;c4 = 2;d4 = 3
821
822                 #FACES NUMBER 
823                 self.file.write("%s;\n" % (numface))  
824                 coun,counter = 0, 0
825                 for face in mesh.faces :
826                         coun += 1
827                         separator = ','
828                         if coun == numface:
829                             separator = ';'
830                         if len(face.v) == 3:
831                                 self.file.write("3; %d, %d, %d;%c\n" % (counter + a3, counter + b3, counter + c3, separator))
832                                 counter += 3
833                         elif len(face.v) == 4:
834                                 self.file.write("4; %d, %d, %d, %d;%c\n" % (counter + a4, counter + b4, counter + c4, counter + d4, separator))
835                                 counter += 4
836                         elif len(face.v) < 3:
837                                 print "WARNING:the mesh has faces with less then 3 vertices"
838                                 print "        It my be not exported correctly."
839
840         
841         #***********************************************
842         #MESH MATERIAL LIST
843         #***********************************************
844         def writeMeshMaterialList(self, obj, mesh, tex):
845                 self.file.write("  MeshMaterialList {\n")
846                 #HOW MANY MATERIALS ARE USED
847                 count = 0
848                 for mat in mesh.getMaterials():
849                         count+=1
850                 self.file.write("    %d;\n" % (len(tex) + count))
851                 #HOW MANY FACES IT HAS
852                 numfaces=len(mesh.faces)
853                 self.file.write("    %d;\n" % (numfaces))
854                 ##MATERIALS INDEX FOR EVERY FACE
855                 counter = 0
856                 for face in mesh.faces :
857                         counter += 1
858                         mater = face.materialIndex
859                         if counter == numfaces:
860                                 if face.image and face.image.name in tex :
861                                         self.file.write("    %d;;\n" % (tex.index(face.image.name) + count))
862                                 else :
863                                         self.file.write("    %d;;\n" % (mater))
864                         else :
865                                 if face.image and face.image.name in tex :
866                                         self.file.write("    %d,\n" % (tex.index(face.image.name) + count))
867                                 else :
868                                         self.file.write("    %d,\n" % (mater))
869                         
870                 ##MATERIAL NAME
871                 for mat in mesh.getMaterials():
872                         self.file.write("  Material")
873                         self.file.write(" %s "% (make_legal_name(mat.name)))
874                         self.file.write("{\n")
875                         self.file.write("    %f; %f; %f;" % (mat.R, mat.G, mat.B))
876                         self.file.write("%s;;\n" % (mat.alpha))
877                         self.file.write("    %f;\n" % (mat.spec))
878                         self.file.write("    %f; %f; %f;;\n" % (mat.specR, mat.specG, mat.specB))
879                         self.file.write("    0.0; 0.0; 0.0;;\n")
880                         self.file.write("  }  //End of Material\n") 
881                 
882                 for mat in tex:
883                         self.file.write("  Material Mat")
884                         self.file.write("%s "% (len(tex)))
885                         self.file.write("{\n")
886                         self.file.write("    1.0; 1.0; 1.0; 1.0;;\n")
887                         self.file.write("    1.0;\n")
888                         self.file.write("    1.0; 1.0; 1.0;;\n")
889                         self.file.write("    0.0; 0.0; 0.0;;\n")
890                         self.file.write("  TextureFilename {")
891                         self.file.write('    "%s";'% (mat))
892                         self.file.write("  }\n")
893                         self.file.write("  }  // End of Material\n")
894                 self.file.write("    }  //End of MeshMaterialList\n")
895
896         #***********************************************
897         #MESH NORMALS
898         #***********************************************
899         def writeMeshNormals(self,name,mesh):
900                 global flip_norm,flip_z,no_light,recalc_norm,Bl_norm
901                 
902                 self.file.write("  MeshNormals {\n")
903                 #VERTICES NUMBER
904                 numvert = 0
905                 for face in mesh.faces:
906                         numvert = numvert + len(face.v)
907                 self.file.write("%d;\n" % (numvert))
908                 numfaces=len(mesh.faces)
909                 if flip_norm :
910                         fl = -1
911                 else :
912                         fl = 1
913                 #VERTICES NORMAL
914                 if Bl_norm:
915                         self.writeBlenderNormals(mesh,fl)
916                 if recalc_norm:
917                         self.writeRecalcNormals(mesh,fl)        
918                 if no_light:
919                         self.writeNoSmothing(mesh,fl)
920                                                 
921                 
922                 
923                 if flip_z:
924                         a3 = 0;b3 = 2;c3 = 1
925                         a4 = 0;b4 = 3;c4 = 2;d4 = 1
926                 else:
927                         a3 = 0;b3 = 1;c3 = 2
928                         a4 = 0;b4 = 1;c4 = 2;d4 = 3
929
930                 #FACES NUMBER 
931                 self.file.write("%s;\n" % (numfaces))  
932                 coun,counter = 0, 0
933                 for face in mesh.faces :
934                         coun += 1
935                         if coun == numfaces:
936                                 if len(face.v) == 3:
937                                         self.file.write("3; %d, %d, %d;;\n" % (counter + a3, counter + b3, counter + c3))
938                                         counter += 3
939                                 else :
940                                         self.file.write("4; %d, %d, %d, %d;;\n" % (counter + a4, counter + b4, counter + c4, counter + d4))
941                                         counter += 4
942                         else:
943                                 
944                                 if len(face.v) == 3:
945                                         self.file.write("3; %d, %d, %d;,\n" % (counter + a3, counter + b3, counter + c3))
946                                         counter += 3
947                                 else :
948                                         self.file.write("4; %d, %d, %d, %d;,\n" % (counter + a4, counter + b4, counter + c4, counter + d4))
949                                         counter += 4
950                 self.file.write("}  //End of MeshNormals\n")
951                 
952         def writeBlenderNormals(self,mesh,fl):
953                         numfaces=len(mesh.faces)
954                         #VERTICES NORMAL
955                         counter = 0
956                         for face in mesh.faces:
957                                 counter += 1  
958                                 for n in range(len(face.v)):
959                                         self.file.write("    %f; %f; %f;" % (
960                                                                         (round(face.v[n].no[0],6)*fl),(round(face.v[n].no[1],6)*fl),(round(face.v[n].no[2],6)*fl)))
961                                         if counter == numfaces :
962                                                 if n == len(face.v)-1 :
963                                                         self.file.write(";\n")
964                                                 else :
965                                                         self.file.write(",\n")
966                                         else :
967                                                 self.file.write(",\n")
968                                                 
969         def writeRecalcNormals(self,mesh,fl):
970                 numfaces=len(mesh.faces)
971                 normal_list = {}
972                 idx = 0
973                 for vertex in mesh.verts:
974                         v_norm = Vector([0, 0, 0])
975                         normal_list[idx] = v_norm
976                         idx += 1
977                         for face in mesh.faces:
978                                 for verts in face.v:
979                                         if verts.index == vertex.index :
980                                                         v_norm[0] += face.no[0]
981                                                         v_norm[1] += face.no[1]
982                                                         v_norm[2] += face.no[2]
983                         
984                         v_norm.normalize()
985                                                 
986                 counter = 0
987                 for face in mesh.faces:
988                                 counter += 1 
989                                 n = 0 
990                                 for vert in face.v:
991                                         n += 1
992                                         norm = normal_list[vert.index]
993                                         
994                                         self.file.write("    %f; %f; %f;" % (
995                                                                         (round(norm[0],6)*fl),(round(norm[1],6)*fl),(round(norm[2],6)*fl)))             
996                                         if counter == numfaces :
997                                                 if n == len(face.v) :
998                                                         self.file.write(";\n")
999                                                 else :
1000                                                         self.file.write(",\n")
1001                                         else :
1002                                                 self.file.write(",\n")
1003                                                 
1004         def writeNoSmothing(self,mesh,fl):
1005                 numfaces=len(mesh.faces)
1006                 counter = 0
1007                 for face in mesh.faces:
1008                                 counter += 1 
1009                                 n = 0 
1010                                 for n in range(len(face.v)):
1011                                         n += 1
1012                                         self.file.write("    %f; %f; %f;" % (
1013                                                                         (round(face.no[0],6)*fl),(round(face.no[1],6)*fl),(round(face.no[2],6)*fl)))
1014                                         
1015                                                         
1016                                         if counter == numfaces :
1017                                                 if n == len(face.v) :
1018                                                         self.file.write(";\n")
1019                                                 else :
1020                                                         self.file.write(",\n")
1021                                         else :
1022                                                 self.file.write(",\n")
1023         #***********************************************
1024         #MESH TEXTURE COORDS
1025         #***********************************************
1026         def writeMeshTextureCoords(self, name, mesh):
1027                 if mesh.hasFaceUV():
1028                         self.file.write("MeshTextureCoords {\n")
1029                         #VERTICES NUMBER
1030                         numvert = 0
1031                         for face in mesh.faces:
1032                                 numvert += len(face.v)
1033                         self.file.write("%d;\n" % (numvert))
1034                         #UV COORDS
1035                         numfaces = len(mesh.faces)
1036                         counter = -1
1037                         co = 0
1038                         for face in mesh.faces:
1039                                 counter += 1
1040                                 co += 1
1041                                 for n in range(len(face.v)):
1042                                         self.file.write("%f;%f;" % (mesh.faces[counter].uv[n][0], -mesh.faces[counter].uv[n][1]))
1043                                         if co == numfaces :
1044                                                 if n == len(face.v) - 1 :
1045                                                         self.file.write(";\n")
1046                                                 else :
1047                                                         self.file.write(",\n")
1048                                         else :
1049                                                 self.file.write(",\n")
1050
1051                         self.file.write("}  //End of MeshTextureCoords\n")
1052
1053         #***********************************************
1054         #MESH VORTEX COLORS
1055         #***********************************************
1056         def writeMeshVertexColors(self, name, mesh):
1057                 if mesh.hasVertexColours():
1058                         self.file.write("MeshVertexColors {\n")
1059                         #VERTICES NUMBER
1060                         numvert = reduce( lambda i,f: len(f)+i, mesh.faces, 0)
1061                         self.file.write("%d;\n" % (numvert))
1062                         #VERTEX COLORS
1063                         
1064                         vcounter =0
1065                         for f in mesh.faces:
1066                                 col = f.col
1067                                 for i,c in enumerate(col):
1068                                         # Note vcol alpha has no meaning
1069                                         self.file.write("%d;%f;%f;%f;%f;" % (vcounter,c.r/255.0, c.g/255.0, c.b/255.0, 1.0)) # c.a/255.0))
1070                                         vcounter+=1
1071                                         if vcounter == numvert :
1072                                                 self.file.write(";\n")
1073                                         else :
1074                                                 self.file.write(",\n")
1075
1076                         self.file.write("}  //End of MeshVertexColors\n")
1077
1078 #***********************************************#***********************************************#***********************************************
1079         #***********************************************
1080         #FRAMES
1081         #***********************************************
1082         def writeFrames(self, matx):
1083                 
1084                 self.file.write("%f,%f,%f,%f," %
1085                                                         (round(matx[0][0],4),round(matx[0][1],4),round(matx[0][2],4),round(matx[0][3],4)))
1086                 self.file.write("%f,%f,%f,%f," %
1087                                                         (round(matx[1][0],4),round(matx[1][1],4),round(matx[1][2],4),round(matx[1][3],4)))      
1088                 self.file.write("%f,%f,%f,%f," %
1089                                                         (round(matx[2][0],4),round(matx[2][1],4),round(matx[2][2],4),round(matx[2][3],4)))
1090                 self.file.write("%f,%f,%f,%f;;" %
1091                                                         (round(matx[3][0],4),round(matx[3][1],4),round(matx[3][2],4),round(matx[3][3],4)))
1092                 
1093                 
1094                 
1095         
1096         
1097         #***********************************************
1098         #WRITE ANIMATION KEYS
1099         #***********************************************
1100         def writeAnimation(self,arm_ob):
1101                 global mat_dict, root_bon
1102                 arm = arm_ob.getData()
1103                 act_list = arm_ob.getAction()
1104                 ip = act_list.getAllChannelIpos()
1105                 for bon in arm.bones.values() :
1106                         point_list = []
1107                         name = bon.name
1108                         name_f = make_legal_name(name)
1109                         try :
1110                                 ip_bon_channel = ip[bon.name]
1111                                 ip_bon_name = ip_bon_channel.getName()
1112                                 
1113                                 ip_bon = Blender.Ipo.Get(ip_bon_name)
1114                                 poi = ip_bon.getCurves()
1115                                 
1116                                 for po in poi[3].getPoints():
1117                                         a = po.getPoints()
1118                                         point_list.append(int(a[0]))
1119                                 #point_list.pop(0) 
1120                                 
1121                                 self.file.write(" Animation { \n")
1122                                 self.file.write("  { %s }\n" %(name_f))
1123                                 self.file.write("  AnimationKey { \n")
1124                                 self.file.write("   4;\n")
1125                                 self.file.write("   %d; \n" % (len(point_list)))
1126
1127                                 for fr in point_list:
1128                                         
1129                                         if name == root_bon.name :
1130                                                 
1131                                                 
1132                                                 mat_b = self.writeAnimCombineMatrix(bon,fr)
1133                                                 mat_arm = self.getLocMat(arm_ob)
1134                                                 mat = mat_b * mat_arm
1135                                         else:   
1136                                                 mat = self.writeAnimCombineMatrix(bon,fr)
1137                                                 
1138                                         self.file.write("   %d;" % (fr))
1139                                         self.file.write("16;")
1140                                 
1141                                         self.writeFrames(mat)
1142                                 
1143                                         if fr == point_list[len(point_list)-1]:
1144                                                 self.file.write(";\n")
1145                                         else:
1146                                                 self.file.write(",\n")
1147                                 self.file.write("   }\n")
1148                                 self.file.write(" }\n")
1149                                 self.file.write("\n")
1150                         except:
1151                                 pass
1152                 
1153                 
1154
1155         #***********************************************
1156         #WRITE ANIMATION KEYS
1157         #***********************************************
1158         def writeAnimationObj(self, obj):
1159                 point_list = []
1160                 ip = obj.ipo
1161                 poi = ip.getCurves()
1162                 for po in poi[0].getPoints():
1163                         a = po.getPoints()
1164                         point_list.append(int(a[0]))
1165                 
1166                 self.file.write(" Animation {\n")
1167                 self.file.write("  { ")
1168                 self.file.write("%s }\n" % (make_legal_name(obj.name)))
1169                 self.file.write("   AnimationKey { \n")
1170                 self.file.write("   4;\n")
1171                 self.file.write("   %d; \n" % (len(point_list)))
1172                 for fr in point_list:
1173                         self.file.write("   %d;" % (fr))
1174                         self.file.write("16;")
1175                         Blender.Set('curframe',fr)
1176                                 
1177                         #mat_new = self.getLocMat(obj) 
1178                         mat_new = obj.matrixLocal 
1179                         self.writeFrames(mat_new)
1180
1181                         if fr == point_list[len(point_list)-1]:
1182                                 self.file.write(";\n")
1183                         else:
1184                                 self.file.write(",\n")
1185                 self.file.write("   }\n")
1186                 self.file.write("  }\n")
1187
1188         
1189                 
1190 #***********************************************#***********************************************#***********************************************
1191
1192
1193
1194         
1195