Advertisement
Guest User

Untitled

a guest
Sep 26th, 2015
146
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 58.06 KB | None | 0 0
  1. #!BPY
  2.  
  3. """
  4. Name: 'B3D Exporter (.b3d)...'
  5. Blender: 259
  6. Group: 'Export'
  7. Tooltip: 'Export to Blitz3D file format (.b3d)'
  8. """
  9. __author__ = ["iego 'GaNDaLDF' Parisi, MTLZ (is06), Joerg Henrichs, Marianne Gagnon"]
  10. __url__ = ["www.gandaldf.com"]
  11. __version__ = "3.0"
  12. __bpydoc__ = """\
  13. """
  14.  
  15. # BLITZ3D EXPORTER 3.0
  16. # Copyright (C) 2009 by Diego "GaNDaLDF" Parisi  -  www.gandaldf.com
  17. # Lightmap issue fixed by Capricorn 76 Pty. Ltd. - www.capricorn76.com
  18. # Blender 2.63 compatiblity based on work by MTLZ, www.is06.com
  19. # With changes by Marianne Gagnon and Joerg Henrichs, supertuxkart.sf.net (Copyright (C) 2011-2012)
  20. #
  21. # LICENSE:
  22. # This program is free software; you can redistribute it and/or modify
  23. # it under the terms of the GNU General Public License as published by
  24. # the Free Software Foundation; either version 2 of the License, or
  25. # (at your option) any later version.
  26. #
  27. # This program is distributed in the hope that it will be useful,
  28. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  29. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  30. # GNU General Public License for more details.
  31. #
  32. # You should have received a copy of the GNU General Public License
  33. # along with this program; if not, write to the Free Software
  34. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  35.  
  36. bl_info = {
  37.     "name": "B3D (BLITZ3D) Model Exporter",
  38.     "description": "Exports a blender scene or object to the B3D (BLITZ3D) format",
  39.     "author": "Diego 'GaNDaLDF' Parisi, MTLZ (is06), Joerg Henrichs, Marianne Gagnon",
  40.     "version": (3,1),
  41.     "blender": (2, 5, 9),
  42.     "api": 31236,
  43.     "location": "File > Export",
  44.     "warning": '', # used for warning icon and text in addons panel
  45.     "wiki_url": "http://supertuxkart.sourceforge.net/Get_involved",
  46.     "tracker_url": "https://sourceforge.net/apps/trac/supertuxkart/",
  47.     "category": "Import-Export"}
  48.  
  49.  
  50. import bpy
  51. import sys,os,os.path,struct,math,string
  52. import mathutils
  53. import math
  54.  
  55. if not hasattr(sys,"argv"): sys.argv = ["???"]
  56.  
  57.  
  58. #Global Stacks
  59. b3d_parameters = {}
  60. texture_flags  = []
  61. texs_stack     = {}
  62. brus_stack     = []
  63. vertex_groups  = []
  64. bone_stack     = {}
  65. keys_stack     = []
  66.  
  67. texture_count = 0
  68.  
  69. # bone_stack indices constants
  70. BONE_PARENT_MATRIX = 0
  71. BONE_PARENT = 1
  72. BONE_ITSELF = 2
  73.  
  74. # texture stack indices constants
  75. TEXTURE_ID = 0
  76. TEXTURE_FLAGS = 1
  77.  
  78. per_face_vertices = {}
  79.  
  80. the_scene = None
  81.  
  82. #Transformation Matrix
  83. TRANS_MATRIX = mathutils.Matrix([[1,0,0,0],[0,0,1,0],[0,1,0,0],[0,0,0,1]])
  84. BONE_TRANS_MATRIX = mathutils.Matrix([[-1,0,0,0],[0,0,-1,0],[0,-1,0,0],[0,0,0,1]])
  85.  
  86. DEBUG = False
  87. PROGRESS = True
  88. PROGRESS_VERBOSE = False
  89.  
  90. tesselated_objects = {}
  91.  
  92. #Support Functions
  93. def write_int(value):
  94.     return struct.pack("<i",value)
  95.  
  96. def write_float(value):
  97.     return struct.pack("<f",value)
  98.  
  99. def write_float_couple(value1, value2):
  100.     return struct.pack("<ff", value1, value2)
  101.  
  102. def write_float_triplet(value1, value2, value3):
  103.     return struct.pack("<fff", value1, value2, value3)
  104.  
  105. def write_float_quad(value1, value2, value3, value4):
  106.     return struct.pack("<ffff", value1, value2, value3, value4)
  107.    
  108. def write_string(value):
  109.     binary_format = "<%ds"%(len(value)+1)
  110.     return struct.pack(binary_format, str.encode(value))
  111.  
  112. def write_chunk(name,value):
  113.     dummy = bytearray()
  114.     return dummy + name + write_int(len(value)) + value
  115.  
  116. trimmed_paths = {}
  117.  
  118. def getArmatureAnimationEnd(armature):
  119.     end_frame = 1
  120.     if armature.animation_data.action:
  121.         ipo = armature.animation_data.action.fcurves
  122.         for curve in ipo:
  123.             if "pose" in curve.data_path:
  124.                 end_frame = max(end_frame, curve.keyframe_points[-1].co[0])
  125.    
  126.     for nla_track in armature.animation_data.nla_tracks:
  127.         if len(nla_track.strips) > 0:
  128.             end_frame = max(end_frame, nla_track.strips[-1].frame_end)
  129.        
  130.     return end_frame
  131.  
  132. # ==== Write B3D File ====
  133. # (main exporter function)
  134. def write_b3d_file(filename, objects=[]):
  135.     global texture_flags, texs_stack, trimmed_paths, tesselated_objects
  136.     global brus_stack, vertex_groups, bone_stack, keys_stack
  137.  
  138.     #Global Stacks
  139.     texture_flags = []
  140.     texs_stack = {}
  141.     brus_stack = []
  142.     vertex_groups = []
  143.     bone_stack = []
  144.     keys_stack = []
  145.     trimmed_paths = {}
  146.     file_buf = bytearray()
  147.     temp_buf = bytearray()
  148.     tesselated_objects = {}
  149.  
  150.     import time
  151.     start = time.time()
  152.  
  153.     temp_buf += write_int(1) #Version
  154.     temp_buf += write_texs(objects) #TEXS
  155.     temp_buf += write_brus(objects) #BRUS
  156.     temp_buf += write_node(objects) #NODE
  157.  
  158.     if len(temp_buf) > 0:
  159.         file_buf += write_chunk(b"BB3D",temp_buf)
  160.         temp_buf = ""
  161.  
  162.     file = open(filename,'wb')
  163.     file.write(file_buf)
  164.     file.close()
  165.    
  166.     # free memory
  167.     trimmed_paths = {}
  168.    
  169.     end = time.time()
  170.    
  171.     print("Exported in", (end - start))
  172.  
  173.  
  174. def tesselate_if_needed(objdata):
  175.     if objdata not in tesselated_objects:
  176.         objdata.calc_tessface()
  177.         tesselated_objects[objdata] = True
  178.     return objdata
  179.  
  180. def getUVTextures(obj_data):
  181.     # BMesh in blender 2.63 broke this
  182.     if bpy.app.version[1] >= 63:
  183.         return tesselate_if_needed(obj_data).tessface_uv_textures
  184.     else:
  185.         return obj_data.uv_textures
  186.  
  187. def getFaces(obj_data):
  188.     # BMesh in blender 2.63 broke this
  189.     if bpy.app.version[1] >= 63:
  190.         return tesselate_if_needed(obj_data).tessfaces
  191.     else:
  192.         return obj_data.faces
  193.  
  194. def getVertexColors(obj_data):
  195.     # BMesh in blender 2.63 broke this
  196.     if bpy.app.version[1] >= 63:
  197.         return tesselate_if_needed(obj_data).tessface_vertex_colors
  198.     else:
  199.         return obj_data.vertex_colors
  200.  
  201. # ==== Write TEXS Chunk ====
  202. def write_texs(objects=[]):
  203.     global b3d_parameters
  204.     global trimmed_paths
  205.     global texture_count
  206.     texs_buf = bytearray()
  207.     temp_buf = bytearray()
  208.     layer_max = 0
  209.     obj_count = 0
  210.     set_wrote = 0
  211.  
  212.     if objects:
  213.         exp_obj = objects
  214.     else:
  215.         if b3d_parameters.get("export-selected"):
  216.             exp_obj = [ob for ob in bpy.data.objects if ob.select]
  217.         else:
  218.             exp_obj = bpy.data.objects
  219.  
  220.     if PROGRESS: print(len(exp_obj),"TEXS")
  221.  
  222.     if PROGRESS_VERBOSE: progress = 0
  223.  
  224.     for obj in exp_obj:
  225.        
  226.         if PROGRESS_VERBOSE:
  227.             progress = progress + 1
  228.             if (progress % 10 == 0): print("TEXS",progress,"/",len(exp_obj))
  229.        
  230.         if obj.type == "MESH":
  231.             set_count = 0
  232.             set_wrote = 0
  233.             #data = obj.getData(mesh = True)
  234.             data = obj.data
  235.            
  236.             # FIXME?
  237.             #orig_uvlayer = data.activeUVLayer
  238.            
  239.             layer_set = [[],[],[],[],[],[],[],[]]
  240.            
  241.             # 8 UV layers are supported
  242.             texture_flags.append([None,None,None,None,None,None,None,None])
  243.  
  244.             #if len(data.getUVLayerNames()) <= 8:
  245.             uv_textures = getUVTextures(data)
  246.             if len(uv_textures) <= 8:
  247.                 if len(uv_textures) > layer_max:
  248.                     layer_max = len(uv_textures)
  249.             else:
  250.                 layer_max = 8
  251.  
  252.             for face in getFaces(data):
  253.                 for iuvlayer,uvlayer in enumerate(uv_textures):
  254.                     if iuvlayer < 8:
  255.                        
  256.                         # FIXME?
  257.                         #data.activeUVLayer = uvlayer
  258.                        
  259.                         #layer_set[iuvlayer].append(face.uv)
  260.                         new_data = None
  261.                         try:
  262.                             new_data = uvlayer.data[face.index].uv
  263.                         except:
  264.                             pass
  265.                        
  266.                         layer_set[iuvlayer].append( new_data )
  267.  
  268.             for i in range(len(uv_textures)):
  269.                 if set_wrote:
  270.                     set_count += 1
  271.                     set_wrote = 0
  272.  
  273.                 for iuvlayer in range(i,len(uv_textures)):
  274.                     if layer_set[i] == layer_set[iuvlayer]:
  275.                         if texture_flags[obj_count][iuvlayer] is None:
  276.                             if set_count == 0:
  277.                                 tex_flag = 1
  278.                             elif set_count == 1:
  279.                                 tex_flag = 65536
  280.                             elif set_count > 1:
  281.                                 tex_flag = 1
  282.                             if b3d_parameters.get("mipmap"):
  283.                                 enable_mipmaps=8
  284.                             else:
  285.                                 enable_mipmaps=0
  286.                             texture_flags[obj_count][iuvlayer] = tex_flag | enable_mipmaps
  287.                             set_wrote = 1
  288.  
  289.             for face in getFaces(data):
  290.                 for iuvlayer,uvlayer in enumerate(uv_textures):
  291.                     if iuvlayer < 8:
  292.                        
  293.                         if not (iuvlayer < len(uv_textures)):
  294.                             continue
  295.                        
  296.                         # FIXME?
  297.                         #data.activeUVLayer = uvlayer
  298.                        
  299.                         #if DEBUG: print("<uv face=", face.index, ">")
  300.                        
  301.                         img = getUVTextures(data)[iuvlayer].data[face.index].image
  302.                        
  303.                         if img:
  304.                            
  305.                             if img.filepath in trimmed_paths:
  306.                                 img_name = trimmed_paths[img.filepath]
  307.                             else:
  308.                                 img_name = bpy.path.basename(img.filepath)
  309.                                 trimmed_paths[img.filepath] = img_name
  310.  
  311.                             if not img_name in texs_stack:
  312.                                 texs_stack[img_name] = [len(texs_stack), texture_flags[obj_count][iuvlayer]]
  313.                                 temp_buf += write_string(img_name) #Texture File Name
  314.                                 temp_buf += write_int(texture_flags[obj_count][iuvlayer]) #Flags
  315.                                 temp_buf += write_int(2)   #Blend
  316.                                 temp_buf += write_float(0) #X_Pos
  317.                                 temp_buf += write_float(0) #Y_Pos
  318.                                 temp_buf += write_float(1) #X_Scale
  319.                                 temp_buf += write_float(1) #Y_Scale
  320.                                 temp_buf += write_float(0) #Rotation
  321.                             #else:
  322.                             #    if DEBUG: print("    <image id=(previous)","name=","'"+img_name+"'","/>")
  323.                            
  324.                         #if DEBUG: print("</uv>")
  325.  
  326.             obj_count += 1
  327.  
  328.             #FIXME?
  329.             #if orig_uvlayer:
  330.             #    data.activeUVLayer = orig_uvlayer
  331.  
  332.     texture_count = layer_max
  333.  
  334.     if len(temp_buf) > 0:
  335.         texs_buf += write_chunk(b"TEXS",temp_buf)
  336.         temp_buf = ""
  337.  
  338.     return texs_buf
  339.  
  340. # ==== Write BRUS Chunk ====
  341. def write_brus(objects=[]):
  342.     global b3d_parameters
  343.     global trimmed_paths
  344.     global texture_count
  345.     brus_buf = bytearray()
  346.     temp_buf = bytearray()
  347.     mat_count = 0
  348.     obj_count = 0
  349.  
  350.     if DEBUG: print("<!-- BRUS chunk -->")
  351.  
  352.     if objects:
  353.         exp_obj = objects
  354.     else:
  355.         if  b3d_parameters.get("export-selected"):
  356.             exp_obj = [ob for ob in bpy.data.objects if ob.select]
  357.         else:
  358.             exp_obj = bpy.data.objects
  359.  
  360.     if PROGRESS: print(len(exp_obj),"BRUS")
  361.     if PROGRESS_VERBOSE: progress = 0
  362.  
  363.     for obj in exp_obj:
  364.        
  365.         if PROGRESS_VERBOSE:
  366.             progress += 1
  367.             if (progress % 10 == 0): print("BRUS",progress,"/",len(exp_obj))
  368.            
  369.         if obj.type == "MESH":
  370.             data = obj.data
  371.            
  372.             uv_textures = getUVTextures(data)
  373.            
  374.             if len(uv_textures) <= 0:
  375.                 continue
  376.  
  377.             if DEBUG: print("<obj name=",obj.name,">")
  378.  
  379.             img_found = 0
  380.            
  381.             for face in getFaces(data):
  382.                
  383.                 face_stack = []
  384.                
  385.                 for iuvlayer,uvlayer in enumerate(uv_textures):
  386.                     if iuvlayer < 8:
  387.                        
  388.                         img_id = -1
  389.                        
  390.                         if face.index >= len(uv_textures[iuvlayer].data):
  391.                             continue
  392.                        
  393.                         img = uv_textures[iuvlayer].data[face.index].image
  394.                        
  395.                         if not img:
  396.                             continue
  397.                        
  398.                         img_found = 1
  399.                        
  400.                         if img.filepath in trimmed_paths:
  401.                             img_name = trimmed_paths[img.filepath]
  402.                         else:
  403.                             img_name = os.path.basename(img.filepath)
  404.                             trimmed_paths[img.filepath] = img_name
  405.                        
  406.                         if DEBUG: print("    <!-- Building FACE 'stack' -->")
  407.                        
  408.                         if img_name in texs_stack:
  409.                             img_id = texs_stack[img_name][TEXTURE_ID]
  410.                        
  411.                         face_stack.insert(iuvlayer,img_id)
  412.                         if DEBUG: print("    <uv face=",face.index,"layer=", iuvlayer, " imgid=", img_id, "/>")
  413.  
  414.                 for i in range(len(face_stack),texture_count):
  415.                     face_stack.append(-1)
  416.  
  417.  
  418.                 if DEBUG: print("    <!-- Writing chunk -->")
  419.                
  420.                 if not img_found:
  421.                     if data.materials:
  422.                         if data.materials[face.material_index]:
  423.                             mat_data = data.materials[face.material_index]
  424.                             mat_colr = mat_data.diffuse_color[0]
  425.                             mat_colg = mat_data.diffuse_color[1]
  426.                             mat_colb = mat_data.diffuse_color[2]
  427.                             mat_alpha = mat_data.alpha
  428.                             mat_name = mat_data.name
  429.  
  430.                             if not mat_name in brus_stack:
  431.                                 brus_stack.append(mat_name)
  432.                                 temp_buf += write_string(mat_name) #Brush Name
  433.                                 temp_buf += write_float(mat_colr)  #Red
  434.                                 temp_buf += write_float(mat_colg)  #Green
  435.                                 temp_buf += write_float(mat_colb)  #Blue
  436.                                 temp_buf += write_float(mat_alpha) #Alpha
  437.                                 temp_buf += write_float(0)         #Shininess
  438.                                 temp_buf += write_int(1)           #Blend
  439.                                 if b3d_parameters.get("vertex-colors") and len(getVertexColors(data)):
  440.                                     temp_buf += write_int(2) #Fx
  441.                                 else:
  442.                                     temp_buf += write_int(0) #Fx
  443.  
  444.                                 for i in face_stack:
  445.                                     temp_buf += write_int(i) #Texture ID
  446.                     else:
  447.                         if b3d_parameters.get("vertex-colors") and len(getVertexColors(data)) > 0:
  448.                             if not face_stack in brus_stack:
  449.                                 brus_stack.append(face_stack)
  450.                                 mat_count += 1
  451.                                 temp_buf += write_string("Brush.%.3i"%mat_count) #Brush Name
  452.                                 temp_buf += write_float(1) #Red
  453.                                 temp_buf += write_float(1) #Green
  454.                                 temp_buf += write_float(1) #Blue
  455.                                 temp_buf += write_float(1) #Alpha
  456.                                 temp_buf += write_float(0) #Shininess
  457.                                 temp_buf += write_int(1)   #Blend
  458.                                 temp_buf += write_int(2)   #Fx
  459.  
  460.                                 for i in face_stack:
  461.                                     temp_buf += write_int(i) #Texture ID
  462.                 else: # img_found
  463.                
  464.                     if not face_stack in brus_stack:
  465.                         brus_stack.append(face_stack)
  466.                         mat_count += 1
  467.                         temp_buf += write_string("Brush.%.3i"%mat_count) #Brush Name
  468.                         temp_buf += write_float(1) #Red
  469.                         temp_buf += write_float(1) #Green
  470.                         temp_buf += write_float(1) #Blue
  471.                         temp_buf += write_float(1) #Alpha
  472.                         temp_buf += write_float(0) #Shininess
  473.                         temp_buf += write_int(1)   #Blend
  474.                        
  475.                         if DEBUG: print("    <brush id=",len(brus_stack),">")
  476.                        
  477.                         if b3d_parameters.get("vertex-colors") and len(getVertexColors(data)) > 0:
  478.                             temp_buf += write_int(2) #Fx
  479.                         else:
  480.                             temp_buf += write_int(0) #Fx
  481.  
  482.                         for i in face_stack:
  483.                             temp_buf += write_int(i) #Texture ID
  484.                             if DEBUG: print("        <texture id=",i,">")
  485.                        
  486.                         if DEBUG: print("    </brush>")
  487.                
  488.                 if DEBUG: print("")
  489.  
  490.             if DEBUG: print("</obj>")
  491.             obj_count += 1
  492.  
  493.             #FIXME?
  494.             #if orig_uvlayer:
  495.             #    data.activeUVLayer = orig_uvlayer
  496.  
  497.     if len(temp_buf) > 0:
  498.         brus_buf += write_chunk(b"BRUS",write_int(texture_count) + temp_buf) #N Texs
  499.         temp_buf = ""
  500.    
  501.     return brus_buf
  502.  
  503. # ==== Write NODE Chunk ====
  504. def write_node(objects=[]):
  505.     global bone_stack
  506.     global keys_stack
  507.     global b3d_parameters
  508.     global the_scene
  509.    
  510.     root_buf = []
  511.     node_buf = []
  512.     main_buf = bytearray()
  513.     temp_buf = []
  514.     obj_count = 0
  515.     amb_light = 0
  516.  
  517.     num_mesh = 0
  518.     num_ligs = 0
  519.     num_cams = 0
  520.     num_lorc = 0
  521.     #exp_scn = Blender.Scene.GetCurrent()
  522.     #exp_scn = the_scene
  523.     #exp_con = exp_scn.getRenderingContext()
  524.  
  525.     #first_frame = Blender.Draw.Create(exp_con.startFrame())
  526.     #last_frame = Blender.Draw.Create(exp_con.endFrame())
  527.     #num_frames = last_frame.val - first_frame.val
  528.     first_frame = the_scene.frame_start
  529.  
  530.     if DEBUG: print("<node first_frame=", first_frame, ">")
  531.  
  532.     if objects:
  533.         exp_obj = objects
  534.     else:
  535.         if b3d_parameters.get("export-selected"):
  536.             exp_obj = [ob for ob in bpy.data.objects if ob.select]
  537.         else:
  538.             exp_obj = bpy.data.objects
  539.  
  540.     for obj in exp_obj:
  541.         if obj.type == "MESH":
  542.             num_mesh += 1
  543.         if obj.type == "CAMERA":
  544.             num_cams += 1
  545.         if obj.type == "LAMP":
  546.             num_ligs += 1
  547.  
  548.     if b3d_parameters.get("cameras"):
  549.         num_lorc += num_cams
  550.  
  551.     if b3d_parameters.get("lights"):
  552.         num_lorc += 1
  553.         num_lorc += num_ligs
  554.  
  555.     if num_mesh + num_lorc > 1:
  556.         exp_root = 1
  557.     else:
  558.         exp_root = 0
  559.  
  560.     if exp_root:
  561.         root_buf.append(write_string("ROOT")) #Node Name
  562.  
  563.         root_buf.append(write_float_triplet(0, 0, 0)) #Position X,Y,Z
  564.         root_buf.append(write_float_triplet(1, 1, 1)) #Scale X, Y, Z
  565.         root_buf.append(write_float_quad(1, 0, 0, 0)) #Rotation W, X, Y, Z
  566.  
  567.     if PROGRESS: progress = 0
  568.  
  569.     for obj in exp_obj:
  570.        
  571.         if PROGRESS:
  572.             progress += 1
  573.             print("NODE:",progress,"/",len(exp_obj))
  574.        
  575.         if obj.type == "MESH":
  576.            
  577.             if DEBUG: print("    <mesh name=",obj.name,">")
  578.            
  579.             bone_stack = {}
  580.             keys_stack = []
  581.  
  582.             anim_data = None
  583.            
  584.             # check if this object has an armature modifier
  585.             for curr_mod in obj.modifiers:
  586.                 if curr_mod.type == 'ARMATURE':
  587.                     arm = curr_mod.object
  588.                     if arm is not None:
  589.                         anim_data = arm.animation_data
  590.  
  591.             # check if this object has an armature parent (second way to do armature animations in blender)
  592.             if anim_data is None:
  593.                 if obj.parent:
  594.                     if obj.parent.type == "ARMATURE":
  595.                         arm = obj.parent
  596.                         if arm.animation_data:
  597.                             anim_data = arm.animation_data
  598.  
  599.             if anim_data:
  600.                 matrix = mathutils.Matrix()
  601.  
  602.                 temp_buf.append(write_string(obj.name)) #Node Name
  603.                
  604.                 position = matrix.to_translation()
  605.                 temp_buf.append(write_float_triplet(position[0], position[1], position[2])) #Position X, Y, Z
  606.  
  607.                 scale = matrix.to_scale()
  608.                 temp_buf.append(write_float_triplet(scale[0], scale[2], scale[1])) #Scale X, Y, Z
  609.  
  610.                 if DEBUG: print("        <arm name=", obj.name, " loc=", -position[0], position[1], position[2], " scale=", scale[0], scale[1], scale[2], "/>")
  611.                
  612.                 quat = matrix.to_quaternion()
  613.                 quat.normalize()
  614.  
  615.                 temp_buf.append(write_float_quad(quat.w, quat.x, quat.z, quat.y))
  616.             else:
  617.                 if b3d_parameters.get("local-space"):
  618.                     matrix = TRANS_MATRIX.copy()
  619.                     scale_matrix = mathutils.Matrix()
  620.                 else:
  621.                     matrix = obj.matrix_world*TRANS_MATRIX
  622.                     scale_matrix = obj.matrix_world.copy()
  623.                
  624.                
  625.                 if bpy.app.version[1] >= 62:
  626.                     # blender 2.62 broke the API : Column-major access was changed to row-major access
  627.                     tmp = mathutils.Vector([matrix[0][1], matrix[1][1], matrix[2][1], matrix[3][1]])
  628.                     matrix[0][1] = matrix[0][2]
  629.                     matrix[1][1] = matrix[1][2]
  630.                     matrix[2][1] = matrix[2][2]
  631.                     matrix[3][1] = matrix[3][2]
  632.                    
  633.                     matrix[0][2] = tmp[0]
  634.                     matrix[1][2] = tmp[1]
  635.                     matrix[2][2] = tmp[2]
  636.                     matrix[3][2] = tmp[3]
  637.                 else:
  638.                     tmp = mathutils.Vector(matrix[1])
  639.                     matrix[1] = matrix[2]
  640.                     matrix[2] = tmp
  641.  
  642.                 temp_buf.append(write_string(obj.name)) #Node Name
  643.  
  644.                 #print("Matrix : ", matrix)
  645.                 position = matrix.to_translation()
  646.  
  647.                 temp_buf.append(write_float_triplet(position[0], position[2], position[1]))
  648.  
  649.                 scale = scale_matrix.to_scale()
  650.                 temp_buf.append(write_float_triplet(scale[0], scale[2], scale[1]))
  651.  
  652.                 quat = matrix.to_quaternion()
  653.                 quat.normalize()
  654.  
  655.                 temp_buf.append(write_float_quad(quat.w, quat.x, quat.z, quat.y))
  656.                  
  657.                 if DEBUG:
  658.                     print("        <position>",position[0],position[2],position[1],"</position>")
  659.                     print("        <scale>",scale[0],scale[1],scale[2],"</scale>")
  660.                     print("        <rotation>", quat.w, quat.x, quat.y, quat.z, "</rotation>")
  661.            
  662.             if anim_data:
  663.                 the_scene.frame_set(1,subframe=0.0)
  664.                
  665.                 arm_matrix = arm.matrix_world
  666.                
  667.                 if b3d_parameters.get("local-space"):
  668.                     arm_matrix = mathutils.Matrix()
  669.                
  670.                 def read_armature(arm_matrix,bone,parent = None):
  671.                     if (parent and not bone.parent.name == parent.name):
  672.                         return
  673.  
  674.                     matrix = mathutils.Matrix(bone.matrix)
  675.                    
  676.                     if parent:
  677.  
  678.                         #print("==== "+bone.name+" ====")
  679.                         a = (bone.matrix_local)
  680.                        
  681.                         #print("A : [%.2f %.2f %.2f %.2f]" % (a[0][0], a[0][1], a[0][2], a[0][3]))
  682.                         #print("    [%.2f %.2f %.2f %.2f]" % (a[1][0], a[1][1], a[1][2], a[1][3]))
  683.                         #print("    [%.2f %.2f %.2f %.2f]" % (a[2][0], a[2][1], a[2][2], a[2][3]))
  684.                         #print("    [%.2f %.2f %.2f %.2f]" % (a[3][0], a[3][1], a[3][2], a[3][3]))
  685.                        
  686.                         b = (parent.matrix_local.inverted().to_4x4())
  687.                        
  688.                         #print("B : [%.2f %.2f %.2f %.2f]" % (b[0][0], b[0][1], b[0][2], b[0][3]))
  689.                         #print("    [%.2f %.2f %.2f %.2f]" % (b[1][0], b[1][1], b[1][2], b[1][3]))
  690.                         #print("    [%.2f %.2f %.2f %.2f]" % (b[2][0], b[2][1], b[2][2], b[2][3]))
  691.                         #print("    [%.2f %.2f %.2f %.2f]" % (b[3][0], b[3][1], b[3][2], b[3][3]))
  692.                        
  693.                         par_matrix = b * a
  694.                        
  695.                         transform = mathutils.Matrix([[1,0,0,0],[0,0,-1,0],[0,-1,0,0],[0,0,0,1]])
  696.                         par_matrix = transform*par_matrix*transform
  697.                        
  698.                         # FIXME: that's ugly, find a clean way to change the matrix.....
  699.                         if bpy.app.version[1] >= 62:
  700.                             # blender 2.62 broke the API : Column-major access was changed to row-major access
  701.                             # TODO: test me
  702.                             par_matrix[1][3] = -par_matrix[1][3]
  703.                             par_matrix[2][3] = -par_matrix[2][3]
  704.                         else:
  705.                             par_matrix[3][1] = -par_matrix[3][1]
  706.                             par_matrix[3][2] = -par_matrix[3][2]
  707.                        
  708.                         #c = par_matrix
  709.                         #print("With parent")
  710.                         #print("C : [%.3f %.3f %.3f %.3f]" % (c[0][0], c[0][1], c[0][2], c[0][3]))
  711.                         #print("    [%.3f %.3f %.3f %.3f]" % (c[1][0], c[1][1], c[1][2], c[1][3]))
  712.                         #print("    [%.3f %.3f %.3f %.3f]" % (c[2][0], c[2][1], c[2][2], c[2][3]))
  713.                         #print("    [%.3f %.3f %.3f %.3f]" % (c[3][0], c[3][1], c[3][2], c[3][3]))
  714.                        
  715.                     else:
  716.                        
  717.                         #print("==== "+bone.name+" ====")
  718.                         #print("Without parent")
  719.  
  720.                         m = arm_matrix*bone.matrix_local
  721.                        
  722.                         #c = arm.matrix_world
  723.                         #print("A : [%.3f %.3f %.3f %.3f]" % (c[0][0], c[0][1], c[0][2], c[0][3]))
  724.                         #print("    [%.3f %.3f %.3f %.3f]" % (c[1][0], c[1][1], c[1][2], c[1][3]))
  725.                         #print("    [%.3f %.3f %.3f %.3f]" % (c[2][0], c[2][1], c[2][2], c[2][3]))
  726.                         #print("    [%.3f %.3f %.3f %.3f]" % (c[3][0], c[3][1], c[3][2], c[3][3]))
  727.                        
  728.                         #c = bone.matrix_local
  729.                         #print("B : [%.3f %.3f %.3f %.3f]" % (c[0][0], c[0][1], c[0][2], c[0][3]))
  730.                         #print("    [%.3f %.3f %.3f %.3f]" % (c[1][0], c[1][1], c[1][2], c[1][3]))
  731.                         #print("    [%.3f %.3f %.3f %.3f]" % (c[2][0], c[2][1], c[2][2], c[2][3]))
  732.                         #print("    [%.3f %.3f %.3f %.3f]" % (c[3][0], c[3][1], c[3][2], c[3][3]))
  733.                        
  734.                         par_matrix = m*mathutils.Matrix([[-1,0,0,0],[0,0,1,0],[0,1,0,0],[0,0,0,1]])
  735.                                                
  736.                         #c = par_matrix
  737.                         #print("C : [%.3f %.3f %.3f %.3f]" % (c[0][0], c[0][1], c[0][2], c[0][3]))
  738.                         #print("    [%.3f %.3f %.3f %.3f]" % (c[1][0], c[1][1], c[1][2], c[1][3]))
  739.                         #print("    [%.3f %.3f %.3f %.3f]" % (c[2][0], c[2][1], c[2][2], c[2][3]))
  740.                         #print("    [%.3f %.3f %.3f %.3f]" % (c[3][0], c[3][1], c[3][2], c[3][3]))
  741.                        
  742.  
  743.                     bone_stack[bone.name] = [par_matrix,parent,bone]
  744.  
  745.                     if bone.children:
  746.                         for child in bone.children: read_armature(arm_matrix,child,bone)
  747.  
  748.                 for bone in arm.data.bones.values():
  749.                     if not bone.parent:
  750.                         read_armature(arm_matrix,bone)
  751.  
  752.                 frame_count = first_frame
  753.                
  754.                 last_frame = int(getArmatureAnimationEnd(arm))
  755.                 num_frames = last_frame - first_frame
  756.  
  757.                 while frame_count <= last_frame:
  758.  
  759.                     the_scene.frame_set(int(frame_count), subframe=0.0)
  760.                    
  761.                     if DEBUG: print("        <frame id=", int(frame_count), ">")
  762.                     arm_pose = arm.pose
  763.                     arm_matrix = arm.matrix_world
  764.                    
  765.                     transform = mathutils.Matrix([[-1,0,0,0],[0,0,1,0],[0,1,0,0],[0,0,0,1]])
  766.                     arm_matrix = transform*arm_matrix
  767.  
  768.                     for bone_name in arm.data.bones.keys():
  769.                         #bone_matrix = mathutils.Matrix(arm_pose.bones[bone_name].poseMatrix)
  770.                         bone_matrix = mathutils.Matrix(arm_pose.bones[bone_name].matrix)
  771.                        
  772.                         #print("(outer loop) bone_matrix for",bone_name,"=", bone_matrix)
  773.                        
  774.                         #print(bone_name,":",bone_matrix)
  775.                        
  776.                         #bone_matrix = bpy.data.scenes[0].objects[0].pose.bones['Bone'].matrix
  777.                        
  778.                         for ibone in bone_stack:
  779.                            
  780.                             bone = bone_stack[ibone]
  781.                            
  782.                             if bone[BONE_ITSELF].name == bone_name:
  783.                                
  784.                                 if DEBUG: print("            <bone id=",ibone,"name=",bone_name,">")
  785.                                
  786.                                 # == 2.4 exporter ==
  787.                                 #if bone_stack[ibone][1]:
  788.                                 #    par_matrix = Blender.Mathutils.Matrix(arm_pose.bones[bone_stack[ibone][1].name].poseMatrix)
  789.                                 #    bone_matrix *= par_matrix.invert()
  790.                                 #else:
  791.                                 #    if b3d_parameters.get("local-space"):
  792.                                 #        bone_matrix *= TRANS_MATRIX
  793.                                 #    else:
  794.                                 #        bone_matrix *= arm_matrix
  795.                                 #bone_loc = bone_matrix.translationPart()
  796.                                 #bone_rot = bone_matrix.rotationPart().toQuat()
  797.                                 #bone_rot.normalize()
  798.                                 #bone_sca = bone_matrix.scalePart()
  799.                                 #keys_stack.append([frame_count - first_frame.val+1,bone_name,bone_loc,bone_sca,bone_rot])
  800.                                
  801.                                 # if has parent
  802.                                 if bone[BONE_PARENT]:
  803.                                     par_matrix = mathutils.Matrix(arm_pose.bones[bone[BONE_PARENT].name].matrix)
  804.                                     bone_matrix = par_matrix.inverted()*bone_matrix
  805.                                 else:
  806.                                     if b3d_parameters.get("local-space"):
  807.                                         bone_matrix = bone_matrix*mathutils.Matrix([[-1,0,0,0],[0,0,1,0],[0,1,0,0],[0,0,0,1]])
  808.                                     else:
  809.                                        
  810.                                         #if frame_count == 1:
  811.                                         #    print("====",bone_name,"====")
  812.                                         #    print("arm_matrix = ", arm_matrix)
  813.                                         #    print("bone_matrix = ", bone_matrix)
  814.                                        
  815.                                         bone_matrix = arm_matrix*bone_matrix
  816.                                        
  817.                                         #if frame_count == 1:
  818.                                         #    print("arm_matrix*bone_matrix", bone_matrix)
  819.                                        
  820.                                
  821.                                 #print("bone_matrix =", bone_matrix)
  822.                                
  823.                                 bone_sca = bone_matrix.to_scale()
  824.                                 bone_loc = bone_matrix.to_translation()
  825.                                
  826.                                 # FIXME: silly tweaks to resemble the Blender 2.4 exporter output
  827.                                 if b3d_parameters.get("local-space"):
  828.                                    
  829.                                     bone_rot = bone_matrix.to_quaternion()
  830.                                     bone_rot.normalize()
  831.                                    
  832.                                    
  833.                                     if not bone[BONE_PARENT]:
  834.                                         tmp = bone_rot.z
  835.                                         bone_rot.z = bone_rot.y
  836.                                         bone_rot.y = tmp
  837.                                        
  838.                                         bone_rot.x = -bone_rot.x
  839.                                     else:
  840.                                         tmp = bone_loc.z
  841.                                         bone_loc.z = bone_loc.y
  842.                                         bone_loc.y = tmp
  843.  
  844.                                 else:
  845.                                     bone_rot = bone_matrix.to_quaternion()
  846.                                     bone_rot.normalize()
  847.  
  848.                                 keys_stack.append([frame_count - first_frame+1, bone_name, bone_loc, bone_sca, bone_rot])
  849.                                 if DEBUG: print("                <loc>", bone_loc, "</loc>")
  850.                                 if DEBUG: print("                <rot>", bone_rot, "</rot>")
  851.                                 if DEBUG: print("                <scale>", bone_sca, "</scale>")
  852.                                 if DEBUG: print("            </bone>")
  853.  
  854.                     frame_count += 1
  855.  
  856.                     if DEBUG: print("        </frame>")
  857.  
  858.                 #Blender.Set("curframe",0)
  859.                 #Blender.Window.Redraw()
  860.  
  861.             temp_buf.append(write_node_mesh(obj,obj_count,anim_data,exp_root)) #NODE MESH
  862.            
  863.             if anim_data:
  864.                 temp_buf.append(write_node_anim(num_frames)) #NODE ANIM
  865.  
  866.                 for ibone in bone_stack:
  867.                     if not bone_stack[ibone][BONE_PARENT]:
  868.                         temp_buf.append(write_node_node(ibone)) #NODE NODE
  869.  
  870.             obj_count += 1
  871.  
  872.             if len(temp_buf) > 0:
  873.                 node_buf.append(write_chunk(b"NODE",b"".join(temp_buf)))
  874.                 temp_buf = []
  875.            
  876.             if DEBUG: print("    </mesh>")
  877.  
  878.         if b3d_parameters.get("cameras"):
  879.             if obj.type == "CAMERA":
  880.                 data = obj.data
  881.                 matrix = obj.getMatrix("worldspace")
  882.                 matrix *= TRANS_MATRIX
  883.  
  884.                 if data.type == "ORTHO":
  885.                     cam_type = 2
  886.                     cam_zoom = round(data.scale,4)
  887.                 else:
  888.                     cam_type = 1
  889.                     cam_zoom = round(data.lens,4)
  890.  
  891.                 cam_near = round(data.clipStart,4)
  892.                 cam_far = round(data.clipEnd,4)
  893.  
  894.                 node_name = ("CAMS"+"\n%s"%obj.name+"\n%s"%cam_type+\
  895.                              "\n%s"%cam_zoom+"\n%s"%cam_near+"\n%s"%cam_far)
  896.                 temp_buf.append(write_string(node_name)) #Node Name
  897.  
  898.                 position = matrix.translation_part()
  899.                 temp_buf.append(write_float_triplet(-position[0], position[1], position[2]))
  900.  
  901.                 scale = matrix.scale_part()
  902.                 temp_buf.append(write_float_triplet(scale[0], scale[1], scale[2]))
  903.  
  904.                 matrix *= mathutils.Matrix.Rotation(180,4,'Y')
  905.                 quat = matrix.to_quat()
  906.                 quat.normalize()
  907.  
  908.                 temp_buf.append(write_float_quad(quat.w, quat.x, quat.y, -quat.z))
  909.  
  910.                 if len(temp_buf) > 0:
  911.                     node_buf.append(write_chunk(b"NODE",b"".join(temp_buf)))
  912.                     temp_buf = []
  913.  
  914.         if b3d_parameters.get("lights"):
  915.             if amb_light == 0:
  916.                 data = Blender.World.GetCurrent()
  917.  
  918.                 amb_light = 1
  919.                 amb_color = (int(data.amb[2]*255) |(int(data.amb[1]*255) << 8) | (int(data.amb[0]*255) << 16))
  920.  
  921.                 node_name = (b"AMBI"+"\n%s"%amb_color)
  922.                 temp_buf.append(write_string(node_name)) #Node Name
  923.  
  924.                 temp_buf.append(write_float_triplet(0, 0, 0)) #Position X, Y, Z
  925.                 temp_buf.append(write_float_triplet(1, 1, 1)) #Scale X, Y, Z
  926.                 temp_buf.append(write_float_quad(1, 0, 0, 0)) #Rotation W, X, Y, Z
  927.  
  928.                 if len(temp_buf) > 0:
  929.                     node_buf.append(write_chunk(b"NODE",b"".join(temp_buf)))
  930.                     temp_buf = []
  931.  
  932.             if obj.type == "LAMP":
  933.                 data = obj.getData()
  934.                 matrix = obj.getMatrix("worldspace")
  935.                 matrix *= TRANS_MATRIX
  936.  
  937.                 if data.type == 0:
  938.                     lig_type = 2
  939.                 elif data.type == 2:
  940.                     lig_type = 3
  941.                 else:
  942.                     lig_type = 1
  943.  
  944.                 lig_angle = round(data.spotSize,4)
  945.                 lig_color = (int(data.b*255) |(int(data.g*255) << 8) | (int(data.r*255) << 16))
  946.                 lig_range = round(data.dist,4)
  947.  
  948.                 node_name = ("LIGS"+"\n%s"%obj.name+"\n%s"%lig_type+\
  949.                              "\n%s"%lig_angle+"\n%s"%lig_color+"\n%s"%lig_range)
  950.                 temp_buf.append(write_string(node_name)) #Node Name
  951.  
  952.                 position = matrix.translation_part()
  953.                 temp_buf.append(write_float_triplet(-position[0], position[1], position[2]))
  954.                 if DEBUG: print("        <position>",-position[0],position[1],position[2],"</position>")
  955.  
  956.                 scale = matrix.scale_part()
  957.                 temp_buf.append(write_float_triplet(scale[0], scale[1], scale[2]))
  958.                
  959.                 if DEBUG: print("        <scale>",scale[0],scale[1],scale[2],"</scale>")
  960.  
  961.                 matrix *= mathutils.Matrix.Rotation(180,4,'Y')
  962.                 quat = matrix.toQuat()
  963.                 quat.normalize()
  964.  
  965.                 temp_buf.append(write_float_quad(quat.w, quat.x, quat.y, -quat.z))
  966.                 if DEBUG: print("        <rotation>", quat.w, quat.x, quat.y, quat.z, "</rotation>")
  967.  
  968.                 if len(temp_buf) > 0:
  969.                     node_buf.append(write_chunk(b"NODE","b".join(temp_buf)))
  970.                     temp_buf = []
  971.    
  972.     if len(node_buf) > 0:
  973.         if exp_root:
  974.             main_buf += write_chunk(b"NODE",b"".join(root_buf) + b"".join(node_buf))
  975.         else:
  976.             main_buf += b"".join(node_buf)
  977.  
  978.         node_buf = []
  979.         root_buf = []
  980.  
  981.     if DEBUG: print("</node>")
  982.  
  983.     return main_buf
  984.  
  985. # ==== Write NODE MESH Chunk ====
  986. def write_node_mesh(obj,obj_count,arm_action,exp_root):
  987.     global vertex_groups
  988.     vertex_groups = []
  989.     mesh_buf = bytearray()
  990.     temp_buf = bytearray()
  991.  
  992.     if arm_action:
  993.         data = obj.data
  994.     else:
  995.         data = obj.to_mesh(the_scene, True, 'PREVIEW')
  996.    
  997.     temp_buf += write_int(-1) #Brush ID
  998.     temp_buf += write_node_mesh_vrts(obj, data, obj_count, arm_action, exp_root) #NODE MESH VRTS
  999.     temp_buf += write_node_mesh_tris(obj, data, obj_count, arm_action, exp_root) #NODE MESH TRIS
  1000.  
  1001.     if len(temp_buf) > 0:
  1002.         mesh_buf += write_chunk(b"MESH",temp_buf)
  1003.         temp_buf = ""
  1004.  
  1005.     return mesh_buf
  1006.  
  1007. def build_vertex_groups(data):
  1008.     for f in getFaces(data):
  1009.         for v in f.vertices:
  1010.             vertex_groups.append({})
  1011.  
  1012.  
  1013. # ==== Write NODE MESH VRTS Chunk ====
  1014. def write_node_mesh_vrts(obj, data, obj_count, arm_action, exp_root):
  1015.     vrts_buf = bytearray()
  1016.     temp_buf = []
  1017.     obj_flags = 0
  1018.    
  1019.     #global time_in_a
  1020.     #global time_in_b
  1021.     #global time_in_b1
  1022.     #global time_in_b2
  1023.     #global time_in_b3
  1024.     #global time_in_b4
  1025.  
  1026.     #data = obj.getData(mesh = True)
  1027.     global the_scene
  1028.    
  1029.     # FIXME: port to 2.5 API?
  1030.     #orig_uvlayer = data.activeUVLayer
  1031.  
  1032.     if b3d_parameters.get("vertex-normals"):
  1033.         obj_flags += 1
  1034.  
  1035.     #if b3d_parameters.get("vertex-colors") and data.getColorLayerNames():
  1036.     if b3d_parameters.get("vertex-colors") and len(getVertexColors(data)) > 0:
  1037.         obj_flags += 2
  1038.  
  1039.     temp_buf.append(write_int(obj_flags)) #Flags
  1040.     #temp_buf += write_int(len(data.getUVLayerNames())) #UV Set
  1041.     temp_buf.append(write_int(len(getUVTextures(data)))) #UV Set
  1042.     temp_buf.append(write_int(2)) #UV Set Size
  1043.  
  1044.     # ---- Prepare the mesh "stack"
  1045.     build_vertex_groups(data)
  1046.    
  1047.     # ---- Fill the mesh "stack"
  1048.     if DEBUG: print("")
  1049.     if DEBUG: print("        <!-- Building vertex_groups -->\n")
  1050.  
  1051.     ivert = -1
  1052.  
  1053.  
  1054.     #if PROGRESS_VERBOSE:
  1055.     #    progress = 0
  1056.     #    print("    vertex_groups, face:",0,"/",len(getFaces(data)))
  1057.    
  1058.     the_scene.frame_set(1,subframe=0.0)
  1059.    
  1060.     if b3d_parameters.get("local-space"):
  1061.         mesh_matrix = mathutils.Matrix()
  1062.     else:
  1063.         mesh_matrix = obj.matrix_world.copy()
  1064.    
  1065.     #import time
  1066.        
  1067.     uv_layers_count = len(getUVTextures(data))
  1068.     for face in getFaces(data):
  1069.        
  1070.         if DEBUG: print("        <!-- Face",face.index,"-->")
  1071.        
  1072.         #if PROGRESS_VERBOSE:
  1073.         #    progress += 1
  1074.         #    if (progress % 50 == 0): print("    vertex_groups, face:",progress,"/",len(data.faces))
  1075.        
  1076.         per_face_vertices[face.index] = []
  1077.        
  1078.         for vertex_id,vert in enumerate(face.vertices):
  1079.            
  1080.             ivert += 1
  1081.                        
  1082.             per_face_vertices[face.index].append(ivert)
  1083.            
  1084.             #a = time.time()
  1085.                            
  1086.             if arm_action:
  1087.                 v = mesh_matrix * data.vertices[vert].co
  1088.                 vert_matrix = mathutils.Matrix.Translation(v)
  1089.             else:
  1090.                 vert_matrix = mathutils.Matrix.Translation(data.vertices[vert].co)
  1091.  
  1092.             vert_matrix *= TRANS_MATRIX
  1093.             vcoord = vert_matrix.to_translation()
  1094.  
  1095.             temp_buf.append(write_float_triplet(vcoord.x, vcoord.z, vcoord.y))
  1096.  
  1097.             #b = time.time()
  1098.             #time_in_a += b - a
  1099.            
  1100.             if b3d_parameters.get("vertex-normals"):
  1101.                 norm_matrix = mathutils.Matrix.Translation(data.vertices[vert].normal)
  1102.  
  1103.                 if arm_action:
  1104.                     norm_matrix *= mesh_matrix
  1105.  
  1106.                 norm_matrix *= TRANS_MATRIX
  1107.                 normal_vector = norm_matrix.to_translation()
  1108.                
  1109.                 temp_buf.append(write_float_triplet(normal_vector.x,  #NX
  1110.                                                     normal_vector.z,  #NY
  1111.                                                     normal_vector.y)) #NZ
  1112.  
  1113.             #c = time.time()
  1114.             #time_in_b += c - b
  1115.  
  1116.             if b3d_parameters.get("vertex-colors") and len(getVertexColors(data)) > 0:
  1117.                 vertex_colors = getVertexColors(data)
  1118.                 if vertex_id == 0:
  1119.                     vcolor = vertex_colors[0].data[face.index].color1
  1120.                 elif vertex_id == 1:
  1121.                     vcolor = vertex_colors[0].data[face.index].color2
  1122.                 elif vertex_id == 2:
  1123.                     vcolor = vertex_colors[0].data[face.index].color3
  1124.                 elif vertex_id == 3:
  1125.                     vcolor = vertex_colors[0].data[face.index].color4
  1126.                
  1127.                 temp_buf.append(write_float_quad(vcolor.r, #R
  1128.                                                  vcolor.g, #G
  1129.                                                  vcolor.b, #B
  1130.                                                  1.0))     #A (FIXME?)
  1131.            
  1132.             #d = time.time()
  1133.             #time_in_b1 += d - c
  1134.            
  1135.             for vg in obj.vertex_groups:
  1136.                 w = 0.0
  1137.                 try:
  1138.                     w = vg.weight(vert)
  1139.                 except:
  1140.                     pass
  1141.                 vertex_groups[ivert][vg.name] = w
  1142.            
  1143.             #e = time.time()
  1144.             #time_in_b2 += e - d
  1145.            
  1146.             # ==== !!bottleneck here!! (40% of the function)
  1147.             if vertex_id == 0:
  1148.                 for iuvlayer in range(uv_layers_count):
  1149.                     uv = getUVTextures(data)[iuvlayer].data[face.index].uv1
  1150.                     temp_buf.append(write_float_couple(uv[0], 1-uv[1]) ) # U, V
  1151.             elif vertex_id == 1:
  1152.                 for iuvlayer in range(uv_layers_count):
  1153.                     uv = getUVTextures(data)[iuvlayer].data[face.index].uv2
  1154.                     temp_buf.append(write_float_couple(uv[0], 1-uv[1]) ) # U, V
  1155.             elif vertex_id == 2:
  1156.                 for iuvlayer in range(uv_layers_count):
  1157.                     uv = getUVTextures(data)[iuvlayer].data[face.index].uv3
  1158.                     temp_buf.append(write_float_couple(uv[0], 1-uv[1]) ) # U, V
  1159.             elif vertex_id == 3:
  1160.                 for iuvlayer in range(uv_layers_count):
  1161.                     uv = getUVTextures(data)[iuvlayer].data[face.index].uv4
  1162.                     temp_buf.append(write_float_couple(uv[0], 1-uv[1]) ) # U, V
  1163.  
  1164.             #f = time.time()
  1165.             #time_in_b3 += f - e
  1166.             # =====================
  1167.  
  1168.    
  1169.     if DEBUG: print("")
  1170.    
  1171.     #c = time.time()
  1172.     #time_in_b += c - b
  1173.     #print("time_in_a = ",time_in_a)
  1174.     #print("time_in_b = ",time_in_b)
  1175.     #print("time_in_b1 = ", time_in_b1)
  1176.     #print("time_in_b2 = ", time_in_b2)
  1177.     #print("time_in_b3 = ", time_in_b3)
  1178.     #print("time_in_b4 = ", time_in_b4)
  1179.  
  1180.     if len(temp_buf) > 0:
  1181.         vrts_buf += write_chunk(b"VRTS",b"".join(temp_buf))
  1182.         temp_buf = []
  1183.  
  1184.     return vrts_buf
  1185.  
  1186. # ==== Write NODE MESH TRIS Chunk ====
  1187. def write_node_mesh_tris(obj, data, obj_count,arm_action,exp_root):
  1188.  
  1189.     global texture_count
  1190.  
  1191.     #FIXME?
  1192.     #orig_uvlayer = data.activeUVLayer
  1193.  
  1194.     # An dictoriary that maps all brush-ids to a list of faces
  1195.     # using this brush. This helps to sort the triangles by
  1196.     # brush, creating less mesh buffer in irrlicht.
  1197.     dBrushId2Face = {}
  1198.    
  1199.     if DEBUG: print("")
  1200.    
  1201.     for face in getFaces(data):
  1202.         img_found = 0
  1203.         face_stack = []
  1204.        
  1205.         uv_textures = getUVTextures(data)
  1206.         uv_layer_count = len(uv_textures)
  1207.         for iuvlayer,uvlayer in enumerate(uv_textures):
  1208.             if iuvlayer < 8:
  1209.                
  1210.                 if iuvlayer >= uv_layer_count:
  1211.                     continue
  1212.                
  1213.                 img_id = -1
  1214.                
  1215.                 img = uv_textures[iuvlayer].data[face.index].image
  1216.                 if img:
  1217.                    
  1218.                     if img.filepath in trimmed_paths:
  1219.                         img_name = trimmed_paths[img.filepath]
  1220.                     else:
  1221.                         img_name = os.path.basename(img.filepath)
  1222.                         trimmed_paths[img.filepath] = img_name
  1223.                    
  1224.                     img_found = 1
  1225.                     if img_name in texs_stack:
  1226.                         img_id = texs_stack[img_name][TEXTURE_ID]
  1227.  
  1228.                 face_stack.insert(iuvlayer,img_id)
  1229.  
  1230.         for i in range(len(face_stack),texture_count):
  1231.             face_stack.append(-1)
  1232.  
  1233.         if img_found == 0:
  1234.             brus_id = -1
  1235.             if data.materials and data.materials[face.material_index]:
  1236.                 mat_name = data.materials[face.material_index].name
  1237.                 for i in range(len(brus_stack)):
  1238.                     if brus_stack[i] == mat_name:
  1239.                         brus_id = i
  1240.                         break
  1241.             else:
  1242.                 for i in range(len(brus_stack)):
  1243.                     if brus_stack[i] == face_stack:
  1244.                         brus_id = i
  1245.                         break
  1246.         else:
  1247.             brus_id = -1
  1248.             for i in range(len(brus_stack)):
  1249.                 if brus_stack[i] == face_stack:
  1250.                     brus_id = i
  1251.                     break
  1252.             if brus_id == -1:
  1253.                 print("Cannot find in brus stack : ", face_stack)
  1254.  
  1255.         if brus_id in dBrushId2Face:
  1256.             dBrushId2Face[brus_id].append(face)
  1257.         else:
  1258.             dBrushId2Face[brus_id] = [face]
  1259.        
  1260.         if DEBUG: print("        <!-- Face",face.index,"in brush",brus_id,"-->")
  1261.    
  1262.     tris_buf = bytearray()
  1263.    
  1264.     if DEBUG: print("")
  1265.     if DEBUG: print("        <!-- TRIS chunk -->")
  1266.    
  1267.     if PROGRESS_VERBOSE: progress = 0
  1268.                
  1269.     for brus_id in dBrushId2Face.keys():
  1270.        
  1271.         if PROGRESS_VERBOSE:
  1272.             progress += 1
  1273.             print("BRUS:",progress,"/",len(dBrushId2Face.keys()))
  1274.        
  1275.         temp_buf = [write_int(brus_id)] #Brush ID
  1276.        
  1277.         if DEBUG: print("        <brush id=", brus_id, ">")
  1278.        
  1279.         if PROGRESS_VERBOSE: progress2 = 0
  1280.                
  1281.         for face in dBrushId2Face[brus_id]:
  1282.            
  1283.             if PROGRESS_VERBOSE:
  1284.                 progress2 += 1
  1285.                 if (progress2 % 50 == 0): print("    TRIS:",progress2,"/",len(dBrushId2Face[brus_id]))
  1286.  
  1287.             vertices = per_face_vertices[face.index]
  1288.  
  1289.             temp_buf.append(write_int(vertices[2])) #A
  1290.             temp_buf.append(write_int(vertices[1])) #B
  1291.             temp_buf.append(write_int(vertices[0])) #C
  1292.  
  1293.             if DEBUG: print("            <face id=", vertices[2], vertices[1], vertices[0],"/> <!-- face",face.index,"-->")
  1294.  
  1295.             if len(face.vertices) == 4:
  1296.                 temp_buf.append(write_int(vertices[3])) #A
  1297.                 temp_buf.append(write_int(vertices[2])) #B
  1298.                 temp_buf.append(write_int(vertices[0])) #C
  1299.                 if DEBUG: print("            <face id=", vertices[3], vertices[2], vertices[0],"/> <!-- face",face.index,"-->")
  1300.  
  1301.         if DEBUG: print("        </brush>")
  1302.         tris_buf += write_chunk(b"TRIS", b"".join(temp_buf))
  1303.  
  1304.     return tris_buf
  1305.  
  1306. # ==== Write NODE ANIM Chunk ====
  1307. def write_node_anim(num_frames):
  1308.     anim_buf = bytearray()
  1309.     temp_buf = bytearray()
  1310.  
  1311.     temp_buf += write_int(0) #Flags
  1312.     temp_buf += write_int(num_frames) #Frames
  1313.     temp_buf += write_float(60) #FPS
  1314.  
  1315.     if len(temp_buf) > 0:
  1316.         anim_buf += write_chunk(b"ANIM",temp_buf)
  1317.         temp_buf = ""
  1318.  
  1319.     return anim_buf
  1320.  
  1321. # ==== Write NODE NODE Chunk ====
  1322. def write_node_node(ibone):
  1323.     node_buf = bytearray()
  1324.     temp_buf = []
  1325.  
  1326.     bone = bone_stack[ibone]
  1327.  
  1328.     matrix = bone[BONE_PARENT_MATRIX]
  1329.     temp_buf.append(write_string(bone[BONE_ITSELF].name)) #Node Name
  1330.    
  1331.  
  1332.  
  1333.     # FIXME: we should use the same matrix format everywhere to not require this
  1334.    
  1335.     position = matrix.to_translation()
  1336.     if bone[BONE_PARENT]:
  1337.         temp_buf.append(write_float_triplet(-position[0], position[2], position[1]))
  1338.     else:
  1339.         temp_buf.append(write_float_triplet(position[0], position[2], position[1]))
  1340.    
  1341.    
  1342.     scale = matrix.to_scale()
  1343.     temp_buf.append(write_float_triplet(scale[0], scale[2], scale[1]))
  1344.  
  1345.     quat = matrix.to_quaternion()
  1346.     quat.normalize()
  1347.  
  1348.     temp_buf.append(write_float_quad(quat.w, quat.x, quat.z, quat.y))
  1349.  
  1350.     temp_buf.append(write_node_bone(ibone))
  1351.     temp_buf.append(write_node_keys(ibone))
  1352.  
  1353.     for iibone in bone_stack:
  1354.         if bone_stack[iibone][BONE_PARENT] == bone_stack[ibone][BONE_ITSELF]:
  1355.             temp_buf.append(write_node_node(iibone))
  1356.  
  1357.     if len(temp_buf) > 0:
  1358.         node_buf += write_chunk(b"NODE", b"".join(temp_buf))
  1359.         temp_buf = []
  1360.  
  1361.     return node_buf
  1362.  
  1363. # ==== Write NODE BONE Chunk ====
  1364. def write_node_bone(ibone):
  1365.     bone_buf = bytearray()
  1366.     temp_buf = []
  1367.  
  1368.     my_name = bone_stack[ibone][BONE_ITSELF].name
  1369.  
  1370.     for ivert in range(len(vertex_groups)):
  1371.         if my_name in vertex_groups[ivert]:
  1372.             vert_influ = vertex_groups[ivert][my_name]
  1373.             #if DEBUG: print("        <bone name=",bone_stack[ibone][BONE_ITSELF].name,"face_vertex_id=", ivert + iuv,
  1374.             #                " weigth=", vert_influ[1] , "/>")
  1375.             temp_buf.append(write_int(ivert)) # Face Vertex ID
  1376.             temp_buf.append(write_float(vert_influ)) #Weight
  1377.  
  1378.     bone_buf += write_chunk(b"BONE", b"".join(temp_buf))
  1379.     temp_buf = []
  1380.  
  1381.     return bone_buf
  1382.  
  1383. # ==== Write NODE KEYS Chunk ====
  1384. def write_node_keys(ibone):
  1385.     keys_buf = bytearray()
  1386.     temp_buf = []
  1387.  
  1388.     temp_buf.append(write_int(7)) #Flags
  1389.  
  1390.     my_name = bone_stack[ibone][BONE_ITSELF].name
  1391.  
  1392.     for ikeys in range(len(keys_stack)):
  1393.         if keys_stack[ikeys][1] == my_name:
  1394.             temp_buf.append(write_int(keys_stack[ikeys][0])) #Frame
  1395.  
  1396.             position = keys_stack[ikeys][2]
  1397.             # FIXME: we should use the same matrix format everywhere and not require this
  1398.             if b3d_parameters.get("local-space"):
  1399.                 if bone_stack[ibone][BONE_PARENT]:
  1400.                     temp_buf.append(write_float_triplet(-position[0], position[2], position[1]))
  1401.                 else:
  1402.                     temp_buf.append(write_float_triplet(position[0], position[2], position[1]))
  1403.             else:
  1404.                 temp_buf.append(write_float_triplet(-position[0], position[1], position[2]))
  1405.  
  1406.             scale = keys_stack[ikeys][3]
  1407.             temp_buf.append(write_float_triplet(scale[0], scale[1], scale[2]))
  1408.  
  1409.             quat = keys_stack[ikeys][4]
  1410.             quat.normalize()
  1411.  
  1412.             temp_buf.append(write_float_quad(quat.w, -quat.x, quat.y, quat.z))
  1413.             #break
  1414.  
  1415.     keys_buf += write_chunk(b"KEYS",b"".join(temp_buf))
  1416.     temp_buf = []
  1417.  
  1418.     return keys_buf
  1419.  
  1420.  
  1421. # ==== CONFIRM OPERATOR ====
  1422. class B3D_Confirm_Operator(bpy.types.Operator):
  1423.     bl_idname = ("screen.b3d_confirm")
  1424.     bl_label = ("File Exists, Overwrite?")
  1425.    
  1426.     def invoke(self, context, event):
  1427.         wm = context.window_manager
  1428.         return wm.invoke_props_dialog(self)
  1429.    
  1430.     def execute(self, context):
  1431.         write_b3d_file(B3D_Confirm_Operator.filepath)
  1432.         return {'FINISHED'}
  1433.  
  1434.  
  1435. #class ObjectListItem(bpy.types.PropertyGroup):
  1436. #    id = bpy.props.IntProperty(name="ID")
  1437. #
  1438. #bpy.utils.register_class(ObjectListItem)
  1439.    
  1440. # ==== EXPORT OPERATOR ====
  1441.  
  1442. class B3D_Export_Operator(bpy.types.Operator):
  1443.     bl_idname = ("screen.b3d_export")
  1444.     bl_label = ("B3D Export")
  1445.     filepath = bpy.props.StringProperty(subtype="FILE_PATH")
  1446.  
  1447.     selected = bpy.props.BoolProperty(name="Export Selected Only", default=False)
  1448.     vnormals = bpy.props.BoolProperty(name="Export Vertex Normals", default=True)
  1449.     vcolors  = bpy.props.BoolProperty(name="Export Vertex Colors", default=True)
  1450.     cameras  = bpy.props.BoolProperty(name="Export Cameras", default=False)
  1451.     lights   = bpy.props.BoolProperty(name="Export Lights", default=False)
  1452.     mipmap   = bpy.props.BoolProperty(name="Mipmap", default=False)
  1453.     localsp  = bpy.props.BoolProperty(name="Use Local Space Coords", default=False)
  1454.  
  1455.     overwrite_without_asking  = bpy.props.BoolProperty(name="Overwrite without asking", default=False)
  1456.    
  1457.     #skip_dialog = False
  1458.    
  1459.     #objects = bpy.props.CollectionProperty(type=ObjectListItem, options={'HIDDEN'})
  1460.    
  1461.     def invoke(self, context, event):
  1462.         blend_filepath = context.blend_data.filepath
  1463.         if not blend_filepath:
  1464.             blend_filepath = "Untitled.b3d"
  1465.         else:
  1466.             blend_filepath = os.path.splitext(blend_filepath)[0] + ".b3d"
  1467.         self.filepath = blend_filepath
  1468.        
  1469.         context.window_manager.fileselect_add(self)
  1470.         return {'RUNNING_MODAL'}
  1471.    
  1472.     def execute(self, context):
  1473.        
  1474.         global b3d_parameters
  1475.         global the_scene
  1476.         b3d_parameters["export-selected"] = self.selected
  1477.         b3d_parameters["vertex-normals" ] = self.vnormals
  1478.         b3d_parameters["vertex-colors"  ] = self.vcolors
  1479.         b3d_parameters["cameras"        ] = self.cameras
  1480.         b3d_parameters["lights"         ] = self.lights
  1481.         b3d_parameters["mipmap"         ] = self.mipmap
  1482.         b3d_parameters["local-space"    ] = self.localsp
  1483.        
  1484.         the_scene = context.scene
  1485.        
  1486.         if self.filepath == "":
  1487.             return {'FINISHED'}
  1488.  
  1489.         if not self.filepath.endswith(".b3d"):
  1490.             self.filepath += ".b3d"
  1491.  
  1492.         print("EXPORT", self.filepath," vcolor = ", self.vcolors)
  1493.            
  1494.         obj_list = []
  1495.         try:
  1496.             # FIXME: silly and ugly hack, the list of objects to export is passed through
  1497.             #        a custom scene property
  1498.             obj_list = context.scene.obj_list
  1499.         except:
  1500.             pass
  1501.        
  1502.         if len(obj_list) > 0:
  1503.          
  1504.             #objlist = []
  1505.             #for a in self.objects:
  1506.             #    objlist.append(bpy.data.objects[a.id])
  1507.             #
  1508.             #write_b3d_file(self.filepath, obj_list)
  1509.            
  1510.             write_b3d_file(self.filepath, obj_list)
  1511.         else:
  1512.             if os.path.exists(self.filepath) and not self.overwrite_without_asking:
  1513.                 #self.report({'ERROR'}, "File Exists")
  1514.                 B3D_Confirm_Operator.filepath = self.filepath
  1515.                 bpy.ops.screen.b3d_confirm('INVOKE_DEFAULT')
  1516.                 return {'FINISHED'}
  1517.             else:
  1518.                 write_b3d_file(self.filepath)
  1519.         return {'FINISHED'}
  1520.  
  1521.  
  1522. # Add to a menu
  1523. def menu_func_export(self, context):
  1524.     global the_scene
  1525.     the_scene = context.scene
  1526.     self.layout.operator(B3D_Export_Operator.bl_idname, text="B3D (.b3d)")
  1527.  
  1528. def register():
  1529.     bpy.types.INFO_MT_file_export.append(menu_func_export)
  1530.     bpy.utils.register_module(__name__)
  1531.  
  1532. def unregister():
  1533.     bpy.types.INFO_MT_file_export.remove(menu_func_export)
  1534.  
  1535. if __name__ == "__main__":
  1536.     register()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement