Adding blender exporter
[lodematron.git] / sexpr_exporter.py
blob1b552f50938bf3d05eab11732e620d4848bf9a7c
1 #!BPY
3 """
4 # Name: 'sexpr (.sexpr)...'
5 # Blender: 246
6 # Group: 'Export'
7 # Tooltip: 'Export to S-Expressions for reading by Scheme/Lisp Faimily.'
8 """
9 __author__ = "William Robinson and John Connors"
10 __url__ = ("blender", "blenderartists.org", "http://badbyteblues.blogspot.com/")
11 __version__ = "1.0"
13 __bpydoc__ = """\
14 This script exports a Blender mesh with armature as an s-expression in a lispy
15 format.
16 """
17 # sexpr_exporter.py version 1.0
18 # Copyright (C) 2007,2008 William Robinson and John Connors
20 # This program is free software; you can redistribute it and/or modify
21 # it under the terms of the GNU General Public License as published by
22 # the Free Software Foundation; either version 2 of the License, or
23 # (at your option) any later version.
25 # This program is distributed in the hope that it will be useful,
26 # but WITHOUT ANY WARRANTY; without even the implied warranty of
27 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 # GNU General Public License for more details.
31 import Blender
32 from Blender import Types, Object, NMesh, Material,Armature,Mesh
33 from Blender.Mathutils import *
34 from Blender import Draw, BGL
35 from Blender.BGL import *
36 import math
38 global mat_flip,index_list,space,bone_list,mat_dict
39 global anim,flip_norm,swap_zy,flip_z,speed,ticks,no_light,recalc_norm,Bl_norm
40 bone_list =[]
41 index_list = []
42 mat_dict = {}
43 space = 0;flip_z = 1;anim=0;swap_yz=0;flip_norm=0;speed=0;ticks= 25
44 Bl_norm = 1;recalc_norm = 0;no_light = 0
46 toggle_val = 0
47 toggle1_val = 0
48 toggle2_val = 0
49 toggle3_val = 1
50 toggle4_val = 0
51 toggle5_val = 1
52 toggle6_val = 0
53 toggle7_val = 0
54 anim_tick = Draw.Create(25)
56 #***********************************************
57 # Only allow letters, digits, and # underscore in Names.
58 #***********************************************
59 def make_legal_name(starting_name):
60 new_name = starting_name.replace('.','_')
61 new_name = new_name.replace(' ','_')
62 if new_name[0].isdigit():
63 new_name = '_' + new_name
64 new_name = '"' + new_name + '"'
65 return new_name
67 #***********************************************
68 # MAIN
69 #***********************************************
71 def my_callback(filename):
72 if filename.find('.sexpr', -6) <= 0: filename += '.sexpr'
73 xexport = xExport(filename)
74 xexport.SelectObjs()
76 def my_callback_sel(filename):
77 if filename.find('.sexpr', -6) <= 0: filename += '.sexpr'
78 xexport = xExport(filename)
79 xexport.exportSelMesh()
80 def event(evt, val):
81 if evt == Draw.ESCKEY:
82 Draw.Exit()
83 return
85 def button_event(evt):
86 global toggle_val,toggle1_val,toggle2_val,toggle3_val,toggle4_val,toggle5_val,toggle6_val,toggle7_val
87 global flip_z,swap_yz,flip_norm,anim,ticks,speed,no_light,Bl_norm,recalc_norm
88 arg = __script__['arg']
89 if evt == 1:
90 toggle_val = 1 - toggle_val
91 anim = toggle_val
92 Draw.Redraw(1)
93 if evt == 2:
94 toggle1_val = 1 - toggle1_val
95 flip_norm = toggle1_val
96 Draw.Redraw(1)
97 if evt == 3:
98 toggle2_val = 1 - toggle2_val
99 swap_yz = toggle2_val
100 Draw.Redraw(1)
101 if evt == 4:
102 toggle3_val = 1 - toggle3_val
103 flip_z = toggle3_val
104 Draw.Redraw(1)
105 if evt == 5:
106 toggle4_val = 1 - toggle4_val
107 speed = toggle4_val
108 Draw.Redraw(1)
109 if evt == 10:
110 toggle5_val = 1 - toggle5_val
111 if toggle5_val==1:
112 toggle6_val = 0
113 toggle7_val = 0
114 else :
115 toggle6_val = 1
116 toggle7_val = 1
117 no_light = toggle7_val
118 recalc_norm = toggle6_val
119 Bl_norm = toggle5_val
120 Draw.Redraw(1)
121 if evt == 11:
122 toggle6_val = 1 - toggle6_val
123 if toggle6_val==1:
124 toggle5_val = 0
125 toggle7_val = 0
126 else :
127 toggle5_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 == 12:
134 toggle7_val = 1 - toggle7_val
135 if toggle7_val==1:
136 toggle6_val = 0
137 toggle5_val = 0
138 else :
139 toggle6_val = 1
140 toggle5_val = 1
141 no_light = toggle7_val
142 recalc_norm = toggle6_val
143 Bl_norm = toggle5_val
144 Draw.Redraw(1)
145 if evt == 6:
146 ticks = anim_tick.val
147 if evt == 7:
148 fname = Blender.sys.makename(ext = ".sexpr")
149 Blender.Window.FileSelector(my_callback, "Export Sexpr", fname)
150 if evt == 8:
151 fname = Blender.sys.makename(ext = ".sexpr")
152 Blender.Window.FileSelector(my_callback_sel, "Export Sexpr", fname)
153 if evt == 9:
154 Draw.Exit()
157 def draw():
158 global animsg,flipmsg,swapmsg,anim_tick
159 global flip_z,swap_yz,flip_norm,anim,ticks,speed,recalc_norm,Bl_norm,no_light
160 glClearColor(0.55,0.6,0.6,1)
161 glClear(BGL.GL_COLOR_BUFFER_BIT)
162 #external box
163 glColor3f(0.2,0.3,0.3)
164 rect(10,402,300,382)
166 #glColor3f(0.3,0.4,0.4)
167 #rect(11,399,298,398)
169 glColor3f(0.5,0.75,0.65)
170 rect(14,398,292,30)
172 glColor3f(0.5,0.75,0.65)
173 rect(14,366,292,160)
175 glColor3f(0.5,0.75,0.65)
176 rect(14,202,292,60)
178 glColor3f(0.5,0.75,0.65)
179 rect(14,138,292,40)
181 glColor3f(0.5,0.75,0.65)
182 rect(14,94,292,70)
184 glColor3f(0.8,.8,0.6)
185 glRasterPos2i(20, 380)
186 Draw.Text("Sexpr Exporter ",'large')
187 Draw.Text("(for Blender 2.41)", 'small')
188 #-------Aniamtion toggle---------------------------------------------
189 Draw.Toggle("Anim", 1, 20, 330, 55, 20, toggle_val,"export animations")
190 if toggle_val :
191 anim = 1
192 animsg = "animation will be exported"
193 else:
194 anim = 0
195 animsg = "animation will be not exported"
196 glRasterPos2i(100,335)
197 Draw.Text(animsg)
198 #---Flip normals toggle-----------------------------------------------
199 Draw.Toggle("Flip norm", 2, 20, 300, 55, 20, toggle1_val,"invert normals")
200 if toggle1_val :
201 flip_norm = 1
202 flipmsg = "flipped normals"
203 else:
204 flip_norm = 0
205 flipmsg = "not flipped normals"
206 glRasterPos2i(100,305)
207 Draw.Text(flipmsg)
208 #------Swap yz toggle----------------------------------------------------------------
209 Draw.Toggle("Swap zy", 3, 20, 270, 55, 20, toggle2_val,"swap z,y axis(y up)")
210 if toggle2_val :
211 swap_yz = 1
212 swapmsg = "Y-axis up"
213 else:
214 swap_yz = 0
215 swapmsg = "Z-axis up"
216 glRasterPos2i(100,275)
217 Draw.Text(swapmsg)
218 #------Flip z toggle----------------------------------------------------------------
219 Draw.Toggle("Flip z", 4, 20, 240, 55, 20, toggle3_val,"flip z axis")
220 if toggle3_val :
221 flip_z = 1
222 zmsg = "left handed system"
223 else:
224 flip_z = 0
225 zmsg = "right handed system"
226 glRasterPos2i(100,245)
227 Draw.Text(zmsg)
228 #------Speed toggle----------------------------------------------------------------
229 Draw.Toggle("Speed", 5, 20, 210, 55, 20, toggle4_val,"Animation speed")
230 if toggle4_val :
231 speed = 1
232 spedmsg = "set speed"
233 anim_tick = Draw.Number("", 6,200, 210, 85, 20, anim_tick.val,1,100000,"ticks per second")
234 else:
235 speed = 0
236 spedmsg = ""
237 glRasterPos2i(100,215)
238 Draw.Text(spedmsg)
239 #------Blender Normals toggle----------------------------------------------------------------
240 Draw.Toggle("Bl.normals", 10, 20, 105, 75, 25, toggle5_val,"export normals as in Blender")
241 if toggle5_val :
242 Bl_norm = 1
243 #------Recalculute Normals toggle----------------------------------------------------------------
244 Draw.Toggle("recalc.no", 11, 120, 105, 75, 25, toggle6_val,"export recalculated normals")
245 if toggle6_val :
246 recalc_norm = 1
247 #------Recalculute Normals toggle----------------------------------------------------------------
248 Draw.Toggle("no smooth", 12, 220, 105, 75, 25, toggle7_val,"every vertex has the face normal,no smoothing")
249 if toggle7_val :
250 no_light = 1
251 #------Draw Button export----------------------------------------------------------------
252 exp_butt = Draw.Button("Export All",7,20, 155, 75, 30, "export all the scene objects")
253 sel_butt = Draw.Button("Export Sel",8,120, 155, 75, 30, "export the selected object")
254 exit_butt = Draw.Button("Exit",9,220, 155, 75, 30, "exit")
255 glRasterPos2i(20,75)
256 Draw.Text("(C) 2008 John Connors ")
257 glRasterPos2i(20,55)
258 Draw.Text("http://badbyteblues.blogspot.com")
259 glRasterPos2i(20,35)
260 Draw.Text("johnc@yagc.ndo.co.uk")
262 def rect(x,y,width,height):
263 glBegin(GL_LINE_LOOP)
264 glVertex2i(x,y)
265 glVertex2i(x+width,y)
266 glVertex2i(x+width,y-height)
267 glVertex2i(x,y-height)
268 glEnd()
270 def rectFill(x,y,width,height):
271 glBegin(GL_POLYGON)
272 glVertex2i(x,y)
273 glVertex2i(x+width,y)
274 glVertex2i(x+width,y-height)
275 glVertex2i(x,y-height)
276 glEnd()
280 Draw.Register(draw, event, button_event)
283 #***********************************************
284 #***********************************************
285 # EXPORTER
286 #***********************************************
287 #***********************************************
289 class xExport:
290 def __init__(self, filename):
291 self.file = open(filename, "w")
293 #*********************************************************************************************************************************************
294 #***********************************************
295 #Select Scene objects
296 #***********************************************
297 def analyzeScene(self):
298 parent_list = []
299 for obj in Blender.Scene.GetCurrent().objects:
300 if obj.type in ('Mesh', 'Armature', 'Empty'):
301 if obj.parent == None :
302 parent_list.append(obj)
304 return parent_list
306 def getChildren(self,obj):
307 obs = Blender.Scene.GetCurrent().objects
308 return [ ob for ob in obs if ob.parent == obj ]
310 def getArmChildren(self,obj):
311 for ob in Blender.Scene.GetCurrent().objects: #Object.Get():
312 if ob.parent == obj :
313 return ob
315 def getLocMat(self, obj):
316 pare = obj.parent
317 mat = obj.matrixWorld
318 mat_id = Matrix([1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1])
319 if pare:
320 mat_p = pare.matrixWorld
321 mat_c = Matrix(mat_p)
322 mat_c.invert()
323 mat_f = mat * mat_c
324 else :
325 mat_id.invert()
326 mat_f = mat * mat_id
327 return mat_f
329 def writeObjFrames(self,obj):
330 global space,chld_obj,ch_list
331 mesh = obj.getData()
332 if obj.type == "Empty" :
333 mat = self.getLocMat(obj)
334 mat_c = Matrix(mat)
335 self.writeArmFrames(mat_c, make_legal_name(obj.name))
336 if type(mesh) == Types.ArmatureType :
337 Child_obj = self.getArmChildren(obj)
338 chld_obj = obj
339 ch_list.append(Child_obj)
340 self.writeRootBone(obj, Child_obj)
341 if obj.type == 'Mesh' and obj not in ch_list:
342 self.exportMesh(obj)
345 def writeChildObj(self,obj):
346 global space,ch_list
347 space += 1
348 if obj :
349 for ob in obj:
350 if ob not in ch_list:
351 self.writeObjFrames(ob)
352 ch_list.append(ob)
353 ch_ob = self.getChildren(ob)
354 self.writeChildObj(ch_ob)
355 self.closeBrackets()
356 self.file.write(" ; End of the Object %s \n" % (ob.name))
359 def writeRootFrame(self):
360 global flip_z,swap_yz,speed
361 if speed:
362 self.writeAnimTicks()
363 if flip_z:
364 mat_flip = Matrix([1, 0, 0, 0], [0, 1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1])
365 else :
366 mat_flip = Matrix([1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1])
367 if swap_yz :
368 mat_rot = RotationMatrix(-90, 4, 'x')
369 mat_flip = mat_rot * mat_flip
370 self.writeArmFrames(mat_flip, ":RootFrame")
372 ##################################################################
373 def SelectObjs(self):
374 global space,chld_obj,ch_list,flip_z,swap_yz,speed
375 print "exporting..."
376 self.writeHeader()
377 self.writeRootFrame()
378 obj_list = self.analyzeScene()
379 space += 1
380 ch_list = []
381 for obj in obj_list:
382 self.writeObjFrames(obj)
383 ch_l = self.getChildren(obj)
384 for ch in ch_l:
387 if ch and ch.type == "Armature":
388 ch_list.append(ch)
389 self.writeObjFrames(ch)
390 else :
391 self.writeChildObj(ch_l)
392 if obj.type != "Armature":
393 self.file.write(" ) ; SI End of the Object %s \n" % (obj.name))
397 self.file.write(") ; End of the Root Frame\n")
398 if anim :
399 self.file.write("(:AnimationSet :AnimationSet0 \n")
400 for obj in Blender.Scene.GetCurrent().objects:
401 if obj.type in ('Mesh', 'Empty'):
402 ip_list = obj.ipo
403 if ip_list != None :
404 self.writeAnimationObj(obj)
405 elif obj.type == 'Armature':
406 act_list = obj.getAction()
407 if act_list != None :
408 self.writeAnimation(obj)
409 #ip_list = obj.ipo
410 #if ip_list != None :
411 # self.writeAnimationObj(obj)
413 self.file.write(") ; End of Animation Set\n")
414 self.writeEnd()
415 #######################################################
418 def writeAnimTicks(self):
419 global ticks
420 self.file.write("(:AnimTicksPerSecond \n")
421 self.file.write("%d \n" % (ticks))
422 self.file.write(")\n")
424 #***********************************************
425 #Export Mesh without Armature
426 #***********************************************
427 def exportMesh(self, obj):
428 tex = []
429 mesh = obj.getData()
430 self.writeTextures(obj, tex)
431 self.writeMeshcoordArm(obj, arm_ob = None)
432 self.writeMeshMaterialList(obj, mesh, tex)
433 self.writeMeshNormals(obj, mesh)
434 self.writeMeshTextureCoords(obj, mesh)
435 self.file.write(") ; End of the Mesh %s \n" % (obj.name))
438 #***********************************************
439 #Export the Selected Mesh
440 #***********************************************
441 def exportSelMesh(self):
442 print "exporting ..."
443 self.writeHeader()
444 self.writeRootFrame()
445 tex = []
446 objs = Object.GetSelected()
447 for obj in objs:
448 if obj.type == 'Mesh':
449 mesh = obj.data
450 self.writeTextures(obj, tex)
451 self.writeMeshcoordArm(obj, arm_ob = None)
452 self.writeMeshMaterialList(obj, mesh, tex)
453 self.writeMeshNormals(obj, mesh)
454 self.writeMeshTextureCoords(obj, mesh)
455 self.file.write(")\n")
456 self.file.write(")\n")
457 ind = objs.index(obj)
458 if ind == len(objs)-1:
459 self.file.write(")\n")
460 ip_list = obj.ipo
461 if ip_list != None :
462 self.file.write("(:AnimationSet :AnimationSet0 \n")
463 self.writeAnimationObj(obj)
464 self.file.write(")\n")
465 else :
466 print "The selected object is not a mesh"
467 print "...finished"
468 #***********************************************
469 #Export Mesh with Armature
470 #***********************************************
471 def exportMeshArm(self,arm,arm_ob,ch_obj):
472 tex = []
473 mesh = ch_obj.getData()
474 self.writeTextures(ch_obj, tex)
475 self.writeMeshcoordArm(ch_obj ,arm_ob)
476 self.writeMeshMaterialList(ch_obj, mesh, tex)
477 self.writeMeshNormals(ch_obj, mesh)
478 self.writeMeshTextureCoords(ch_obj, mesh)
479 self.writeSkinWeights(arm,mesh)
480 #self.file.write(" ) ; End of the Frame %s \n" % (ch_obj.name))
481 self.file.write(") ; End of the Object %s \n" % (ch_obj.name))
483 #***********************************************
484 #Export Root Bone
485 #***********************************************
486 def writeRootBone(self, chld_obj, child_obj):
487 global space,root_bon
488 arms = chld_obj.getData()
489 mat_arm = self.getLocMat(chld_obj)
490 for bon in arms.bones.values():
491 if bon.hasParent():
492 pass
493 else:
494 root_bon = bon
495 space += 1
496 mat_r = self.writeAnimCombineMatrix(root_bon,1)
497 self.writeArmFrames(mat_r, make_legal_name(root_bon.name))
499 bon_c = root_bon.children
500 self.writeChildren(bon_c)
501 self.file.write(") ; End of the Bone %s \n" % (root_bon.name))
502 self.exportMeshArm(arms, chld_obj ,child_obj)
504 #***********************************************
505 #Create Children structure
506 #***********************************************
507 def writeBon(self,bon):
508 global space
509 mat_r = self.writeAnimCombineMatrix(bon,1)
510 self.writeArmFrames(mat_r, make_legal_name(bon.name))
513 def writeChildren(self,bon_c):
514 global space,bone_list
515 space += 1
516 if bon_c:
517 for bo in bon_c:
518 if bo.name not in bone_list:
519 self.writeBon(bo)
520 bone_list.append(bo.name)
521 bo_c = bo.children
522 self.writeChildren(bo_c)
523 self.closeBrackets()
527 def closeBrackets(self):
528 global space
529 space = space-1
530 tab = " "
531 self.file.write(")\n")
535 #***********************************************
536 #Offset Matrix
537 #***********************************************
538 def writeMatrixOffset(self,bon):
539 global chld_obj
540 Blender.Set('curframe', 1)
541 pose = chld_obj.getPose()
542 pos_b = pose.bones[bon.name]
543 mat_b = pos_b.poseMatrix
544 mat_c = Matrix(mat_b)
545 mat_c.invert()
546 return mat_c
549 #***********************************************
550 #Combine Matrix
551 #***********************************************
552 def writeCombineMatrix(self,bon):
553 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 if bon.hasParent():
560 pare = bon.parent
561 pos_p = pose.bones[pare.name]
562 mat_p = pos_p.poseMatrix
563 else:
564 mat_p = Matrix([1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1])
565 mat_c = Matrix(mat_p)
566 mat_c.invert()
567 mat_f = mat_b * mat_c
569 return mat_f
570 #***********************************************
571 #Combine Matrix
572 #***********************************************
573 def writeAnimCombineMatrix(self,bon,fre):
574 global chld_obj
575 Blender.Set('curframe', fre)
576 pose = chld_obj.getPose()
577 pos_b = pose.bones[bon.name]
578 mat_b = pos_b.poseMatrix
579 if bon.hasParent():
580 pare = bon.parent
581 pos_p = pose.bones[pare.name]
582 mat_p = pos_p.poseMatrix
584 else:
585 mat_p = Matrix([1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1])
586 mat_c = Matrix(mat_p)
587 mat_c.invert()
588 mat_f = mat_b * mat_c
590 return mat_f
593 #*********************************************************************************************************************************************
594 #***********************************************
595 #Write SkinWeights
596 #***********************************************
597 def writeSkinWeights(self, arm, mesh):
598 global index_list
599 v_dict = {}
600 Blender.Set('curframe',1)
601 self.file.write("(:XSkinMeshHeader \n")
602 max_infl = 0
603 for bo in arm.bones.values() :
604 name = bo.name
605 try :
606 vertx_list = mesh.getVertsFromGroup(name,1)
607 for inde in vertx_list :
608 vert_infl = mesh.getVertexInfluences(inde[0])
609 ln_infl = len(vert_infl)
610 if ln_infl > max_infl :
611 max_infl = ln_infl
613 except:
614 pass
616 self.file.write("%d \n" % (max_infl))
617 self.file.write("%d \n" % (max_infl * 3))
618 self.file.write("%d \n" % (len(arm.bones.values())))
619 self.file.write(")\n")
621 for bo in arm.bones.values() :
622 bo_list = []
623 weight_list = []
624 name = bo.name
625 f_name = make_legal_name(name)
626 try :
627 vert_list = mesh.getVertsFromGroup(name,1)
628 le = 0
629 for indx in vert_list:
630 ver_infl = mesh.getVertexInfluences(indx[0])
631 infl = 0.0
632 if len(ver_infl) != 0:
633 sum = 0.0
634 for bone_n, weight in ver_infl:
635 if bone_n == name:
636 infl = weight
637 sum += weight
638 infl /= sum
640 i = -1
641 for el in index_list :
642 i += 1
643 if el == indx[0] :
644 le +=1
645 bo_list.append(i)
646 weight_list.append(infl)
649 self.file.write("(:SkinWeights \n")
650 self.file.write('"%s"\n' % (f_name))
651 self.file.write('%d\n' % (le))
652 count = 0
653 for ind in bo_list :
654 count += 1
655 if count == len(bo_list):
656 self.file.write("%d\n" % (ind))
657 else :
658 self.file.write("%d\n" % (ind))
659 cou = 0
660 for wegh in weight_list :
661 cou += 1
663 if cou == len(weight_list):
664 self.file.write("%f\n" % (round(wegh,6)))
665 else :
666 self.file.write("%f\n" % (round(wegh,6)))
669 matx = self.writeMatrixOffset(bo)
670 self.writeOffsFrames(matx, name)
671 except :
672 pass
673 self.file.write(") ; End of XSkinMeshHeader\n")
676 #***********************************************
677 # Write Matrices
678 #***********************************************
679 def writeArmFrames(self, matx, name):
680 self.file.write("(:Frame ")
681 self.file.write("%s \n\n" % (name))
682 self.file.write("(:FrameTransformMatrix \n\n")
683 self.writeFrame(matx)
685 #***********************************************
686 # Write Frames
687 #***********************************************
688 def writeOffsFrames(self, matx, name):
689 space = 1
690 self.writeFrame(matx)
692 #***********************************************
693 # Write Frames
694 #***********************************************
695 def writeFrame(self, matx):
696 self.file.write("%f %f %f %f \n" %
697 (round(matx[0][0],4),round(matx[0][1],4),round(matx[0][2],4),round(matx[0][3],4)))
698 self.file.write("%f %f %f %f\n" %
699 (round(matx[1][0],4),round(matx[1][1],4),round(matx[1][2],4),round(matx[1][3],4)))
700 self.file.write("%f %f %f %f \n" %
701 (round(matx[2][0],4),round(matx[2][1],4),round(matx[2][2],4),round(matx[2][3],4)))
702 self.file.write("%f %f %f %f\n" %
703 (round(matx[3][0],4),round(matx[3][1],4),round(matx[3][2],4),round(matx[3][3],4)))
704 self.file.write(")\n")
705 #*********************************************************************************************************************************************
707 #***********************************************
708 #HEADER
709 #***********************************************
710 def writeHeader(self):
711 pass
713 #***********************************************
714 #CLOSE FILE
715 #***********************************************
716 def writeEnd(self):
717 self.file.close()
718 print "... finished"
721 #***********************************************
722 #EXPORT TEXTURES
723 #***********************************************
724 def writeTextures(self,name, tex):
725 mesh = name.data
726 for face in mesh.faces:
727 if face.image and face.image.name not in tex:
728 tex.append(face.image.name)
732 #***********************************************
733 #EXPORT MESH DATA with Armature
734 #***********************************************
735 def writeMeshcoordArm(self, obj ,arm_ob):
736 global index_list,flip_z
737 #TransformMatrix
738 mat = self.getLocMat(obj)
739 self.writeArmFrames(mat, make_legal_name(obj.name))
740 mesh = NMesh.GetRawFromObject(obj.name)
741 self.file.write("(:Mesh \n")
742 numface=len(mesh.faces)
743 #VERTICES NUMBER
744 numvert = 0
745 for face in mesh.faces:
746 numvert = numvert + len(face.v)
747 self.file.write("%d ;; nvertices\n" % (numvert))
748 if numvert == 0:
749 print "Mesh named",mesh.name,"has no vertices.Problems may occur using the .sexpr file"
750 #VERTICES COORDINATES
751 counter = 0
752 for face in mesh.faces:
753 counter += 1
754 for n in range(len(face.v)):
755 index_list.append(face.v[n].index)
756 vec_vert = Vector([(face.v[n].co[0]), face.v[n].co[1], face.v[n].co[2], 1])
757 if arm_ob :
758 f_vec_vert = vec_vert * mat
759 else :
760 f_vec_vert = vec_vert
761 self.file.write("%f %f %f" % (round(f_vec_vert[0],4), round(f_vec_vert[1],4), round(f_vec_vert[2],4)))
762 if counter == numface :
763 if n == len(face.v)-1 :
764 self.file.write("\n")
765 else :
766 self.file.write("\n")
767 else :
768 self.file.write("\n")
769 if flip_z:
770 a3 = 0;b3 = 2;c3 = 1
771 a4 = 0;b4 = 3;c4 = 2;d4 = 1
772 else:
773 a3 = 0;b3 = 1;c3 = 2
774 a4 = 0;b4 = 1;c4 = 2;d4 = 3
776 #FACES NUMBER
777 self.file.write("%s ;; numfaces\n" % (numface))
778 coun,counter = 0, 0
779 for face in mesh.faces :
780 coun += 1
781 separator = ','
782 if coun == numface:
783 separator = ';'
784 if len(face.v) == 3:
785 self.file.write("3 %d %d %d\n" % (counter + a3, counter + b3, counter + c3))
786 counter += 3
787 elif len(face.v) == 4:
788 self.file.write("4 %d %d %d %d\n" % (counter + a4, counter + b4, counter + c4, counter + d4))
789 counter += 4
790 elif len(face.v) < 3:
791 print "WARNING:the mesh has faces with less then 3 vertices"
792 print " It my be not exported correctly."
795 #***********************************************
796 #MESH MATERIAL LIST
797 #***********************************************
798 def writeMeshMaterialList(self, obj, mesh, tex):
799 self.file.write("(:MeshMaterialList \n")
800 #HOW MANY MATERIALS ARE USED
801 count = 0
802 for mat in mesh.getMaterials():
803 count+=1
804 self.file.write("%d ; nMaterials\n" % (len(tex) + count))
805 #HOW MANY FACES IT HAS
806 numfaces=len(mesh.faces)
807 self.file.write("%d ;; nFaces\n" % (numfaces))
808 ##MATERIALS INDEX FOR EVERY FACE
809 counter = 0
810 for face in mesh.faces :
811 counter += 1
812 mater = face.materialIndex
813 if counter == numfaces:
814 if face.image and face.image.name in tex :
815 self.file.write(" %d\n" % (tex.index(face.image.name) + count))
816 else :
817 self.file.write(" %d\n" % (mater))
818 else :
819 if face.image and face.image.name in tex :
820 self.file.write(" %d\n" % (tex.index(face.image.name) + count))
821 else :
822 self.file.write(" %d\n" % (mater))
824 ##MATERIAL NAME
825 for mat in mesh.getMaterials():
826 self.file.write("(:Material")
827 self.file.write(" %s \n"% (make_legal_name(mat.name)))
828 self.file.write(" %f %f %f " % (mat.R, mat.G, mat.B))
829 self.file.write("%s \n" % (mat.alpha))
830 self.file.write(" %f \n" % (mat.spec))
831 self.file.write(" %f %f %f \n" % (mat.specR, mat.specG, mat.specB))
832 self.file.write(" 0.0 0.0 0.0 \n")
833 self.file.write(") ;End of Material\n")
835 for mat in tex:
836 self.file.write("(:Material Mat")
837 self.file.write("%s \n"% (len(tex)))
838 self.file.write(" 1.0 1.0 1.0 1.0 \n")
839 self.file.write(" 1.0 \n")
840 self.file.write(" 1.0 1.0 1.0 \n")
841 self.file.write(" 0.0 0.0 0.0 \n")
842 self.file.write("(:TextureFilename ")
843 self.file.write(' "%s" '% (mat))
844 self.file.write(")\n")
845 self.file.write(") ; End of Material\n")
846 self.file.write(") ;End of MeshMaterialList\n")
848 #***********************************************
849 #MESH NORMALS
850 #***********************************************
851 def writeMeshNormals(self,name,mesh):
852 global flip_norm,flip_z,no_light,recalc_norm,Bl_norm
854 self.file.write("(:MeshNormals \n")
855 #VERTICES NUMBER
856 numvert = 0
857 for face in mesh.faces:
858 numvert = numvert + len(face.v)
859 self.file.write("%d ;; nNormals\n" % (numvert))
860 numfaces=len(mesh.faces)
861 if flip_norm :
862 fl = -1
863 else :
864 fl = 1
865 #VERTICES NORMAL
866 if Bl_norm:
867 self.writeBlenderNormals(mesh,fl)
868 if recalc_norm:
869 self.writeRecalcNormals(mesh,fl)
870 if no_light:
871 self.writeNoSmothing(mesh,fl)
875 if flip_z:
876 a3 = 0;b3 = 2;c3 = 1
877 a4 = 0;b4 = 3;c4 = 2;d4 = 1
878 else:
879 a3 = 0;b3 = 1;c3 = 2
880 a4 = 0;b4 = 1;c4 = 2;d4 = 3
882 #FACES NUMBER
883 self.file.write("%s \n" % (numfaces))
884 coun,counter = 0, 0
885 for face in mesh.faces :
886 coun += 1
887 if coun == numfaces:
888 if len(face.v) == 3:
889 self.file.write("3 %d %d %d\n" % (counter + a3, counter + b3, counter + c3))
890 counter += 3
891 else :
892 self.file.write("4 %d %d %d %d\n" % (counter + a4, counter + b4, counter + c4, counter + d4))
893 counter += 4
894 else:
896 if len(face.v) == 3:
897 self.file.write("3 %d %d %d\n" % (counter + a3, counter + b3, counter + c3))
898 counter += 3
899 else :
900 self.file.write("4 %d %d %d %d\n" % (counter + a4, counter + b4, counter + c4, counter + d4))
901 counter += 4
902 self.file.write(") ; End of MeshNormals\n")
904 def writeBlenderNormals(self,mesh,fl):
905 numfaces=len(mesh.faces)
906 #VERTICES NORMAL
907 counter = 0
908 for face in mesh.faces:
909 counter += 1
910 for n in range(len(face.v)):
911 self.file.write(" %f %f %f" % (
912 (round(face.v[n].no[0],6)*fl),(round(face.v[n].no[1],6)*fl),(round(face.v[n].no[2],6)*fl)))
913 if counter == numfaces :
914 if n == len(face.v)-1 :
915 self.file.write("\n")
916 else :
917 self.file.write("\n")
918 else :
919 self.file.write("\n")
922 def writeRecalcNormals(self,mesh,fl):
923 numfaces=len(mesh.faces)
924 normal_list = {}
925 idx = 0
926 for vertex in mesh.verts:
927 v_norm = Vector([0, 0, 0])
928 normal_list[idx] = v_norm
929 idx += 1
930 for face in mesh.faces:
931 for verts in face.v:
932 if verts.index == vertex.index :
933 v_norm[0] += face.no[0]
934 v_norm[1] += face.no[1]
935 v_norm[2] += face.no[2]
936 v_norm.normalize()
937 counter = 0
938 for face in mesh.faces:
939 counter += 1
940 n = 0
941 for vert in face.v:
942 n += 1
943 norm = normal_list[vert.index]
944 self.file.write("%f %f %f" % ((round(norm[0],6)*fl),(round(norm[1],6)*fl),(round(norm[2],6)*fl)))
945 self.file.write("\n")
947 def writeNoSmothing(self,mesh,fl):
948 numfaces=len(mesh.faces)
949 counter = 0
950 for face in mesh.faces:
951 counter += 1
952 n = 0
953 for n in range(len(face.v)):
954 self.file.write(" %f %f %f" % ((round(face.no[0],6)*fl),(round(face.no[1],6)*fl),(round(face.no[2],6)*fl)))
955 self.file.write("\n")
957 #***********************************************
958 #MESH TEXTURE COORDS
959 #***********************************************
960 def writeMeshTextureCoords(self, name, mesh):
961 if mesh.hasFaceUV():
962 self.file.write("(:MeshTextureCoords \n")
963 #VERTICES NUMBER
964 numvert = 0
965 for face in mesh.faces:
966 numvert += len(face.v)
967 self.file.write("%d\n ;; nUVS" % (numvert))
968 #UV COORDS
969 numfaces = len(mesh.faces)
970 counter = -1
971 co = 0
972 for face in mesh.faces:
973 counter += 1
974 co += 1
975 for n in range(len(face.v)):
976 self.file.write("%f %f" % (mesh.faces[counter].uv[n][0], -mesh.faces[counter].uv[n][1]))
977 if co == numfaces :
978 if n == len(face.v) - 1 :
979 self.file.write("\n")
980 else :
981 self.file.write("\n")
982 else :
983 self.file.write("\n")
984 self.file.write(") ; End of MeshTextureCoords\n")
986 #***********************************************#***********************************************#***********************************************
987 #***********************************************
988 #FRAMES
989 #***********************************************
990 def writeFrames(self, matx):
992 self.file.write("%f %f %f %f " %
993 (round(matx[0][0],4),round(matx[0][1],4),round(matx[0][2],4),round(matx[0][3],4)))
994 self.file.write("%f %f %f %f " %
995 (round(matx[1][0],4),round(matx[1][1],4),round(matx[1][2],4),round(matx[1][3],4)))
996 self.file.write("%f %f %f %f " %
997 (round(matx[2][0],4),round(matx[2][1],4),round(matx[2][2],4),round(matx[2][3],4)))
998 self.file.write("%f %f %f %f " %
999 (round(matx[3][0],4),round(matx[3][1],4),round(matx[3][2],4),round(matx[3][3],4)))
1005 #***********************************************
1006 #WRITE ANIMATION KEYS
1007 #***********************************************
1008 def writeAnimation(self,arm_ob):
1009 global mat_dict, root_bon
1010 arm = arm_ob.getData()
1011 act_list = arm_ob.getAction()
1012 ip = act_list.getAllChannelIpos()
1013 for bon in arm.bones.values() :
1014 point_list = []
1015 name = bon.name
1016 name_f = make_legal_name(name)
1017 try :
1018 ip_bon_channel = ip[bon.name]
1019 ip_bon_name = ip_bon_channel.getName()
1021 ip_bon = Blender.Ipo.Get(ip_bon_name)
1022 poi = ip_bon.getCurves()
1024 for po in poi[3].getPoints():
1025 a = po.getPoints()
1026 point_list.append(int(a[0]))
1027 #point_list.pop(0)
1029 self.file.write("(:Animation \n")
1030 self.file.write("( %s )\n" %(name_f))
1031 self.file.write("(:AnimationKey \n")
1032 self.file.write("4 ")
1033 self.file.write("%d\n" % (len(point_list)))
1035 for fr in point_list:
1037 if name == root_bon.name :
1040 mat_b = self.writeAnimCombineMatrix(bon,fr)
1041 mat_arm = self.getLocMat(arm_ob)
1042 mat = mat_b * mat_arm
1043 else:
1044 mat = self.writeAnimCombineMatrix(bon,fr)
1046 self.file.write("%d " % (fr))
1047 self.file.write("16 ")
1049 self.writeFrames(mat)
1051 if fr == point_list[len(point_list)-1]:
1052 self.file.write("\n")
1053 else:
1054 self.file.write("\n")
1055 self.file.write(")\n")
1056 self.file.write(")\n")
1057 except:
1058 pass
1062 #***********************************************
1063 #WRITE ANIMATION KEYS
1064 #***********************************************
1065 def writeAnimationObj(self, obj):
1066 point_list = []
1067 ip = obj.ipo
1068 poi = ip.getCurves()
1069 for po in poi[0].getPoints():
1070 a = po.getPoints()
1071 point_list.append(int(a[0]))
1073 self.file.write("(:Animation \n")
1074 self.file.write("( ")
1075 self.file.write("%s )\n" % (make_legal_name(obj.name)))
1076 self.file.write("(:AnimationKey \n")
1077 self.file.write("4 ")
1078 self.file.write("%d \n" % (len(point_list)))
1079 for fr in point_list:
1080 self.file.write(" %d " % (fr))
1081 self.file.write(" 16 ")
1082 Blender.Set('curframe',fr)
1084 #mat_new = self.getLocMat(obj)
1085 mat_new = obj.matrixLocal
1086 self.writeFrames(mat_new)
1087 self.file.write("\n")
1089 self.file.write(")\n")
1090 self.file.write(")\n")
1094 #***********************************************#***********************************************#***********************************************