Revision: 20081
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=20081
Author:   campbellbarton
Date:     2009-05-06 08:01:09 +0200 (Wed, 06 May 2009)

Log Message:
-----------
[#18328] FBX exporter not exporting multi-texture materials properly

even though the format allows materials and textures to be written separately 
the textures wont load right in maya or 3dsmax unless each texture has its own 
material.

Modified Paths:
--------------
    trunk/blender/release/scripts/export_fbx.py

Modified: trunk/blender/release/scripts/export_fbx.py
===================================================================
--- trunk/blender/release/scripts/export_fbx.py 2009-05-06 04:24:01 UTC (rev 
20080)
+++ trunk/blender/release/scripts/export_fbx.py 2009-05-06 06:01:09 UTC (rev 
20081)
@@ -93,8 +93,8 @@
                dest_dir += Blender.sys.sep
        
        image_paths = set()
-       for img in textures:
-               image_paths.add(Blender.sys.expandpath(img.filename))
+       for tex in textures:
+               image_paths.add(Blender.sys.expandpath(tex.filename))
        
        # Now copy images
        copyCount = 0
@@ -157,14 +157,29 @@
 # todo - Disallow the name 'Scene' and 'blend_root' - it will bugger things up.
 def sane_name(data, dct):
        #if not data: return None
-       name = data.name
        
+       if type(data)==tuple: # materials are paired up with images
+               data, other = data
+               use_other = True
+       else:
+               other = None
+               use_other = False
+       
+       if data:        name = data.name
+       else:           name = None
+       orig_name = name
+       
+       if other:
+               orig_name_other = other.name
+               name = '%s #%s' % (name, orig_name_other)
+       else:
+               orig_name_other = None
+       
        # dont cache, only ever call once for each data type now,
        # so as to avoid namespace collision between types - like with objects 
<-> bones
        #try:           return dct[name]
        #except:                pass
        
-       orig_name = name
        if not name:
                name = 'unnamed' # blank string, ASKING FOR TROUBLE!
        else:
@@ -173,7 +188,11 @@
        
        while name in dct.itervalues(): name = increment_string(name)
        
-       dct[orig_name] = name
+       if use_other: # even if other is None - orig_name_other will be a 
string or None
+               dct[orig_name, orig_name_other] = name
+       else:
+               dct[orig_name] = name
+               
        return name
 
 def sane_obname(data):         return sane_name(data, sane_name_mapping_ob)
@@ -1333,13 +1352,15 @@
                me = my_mesh.blenData
                
                # if there are non NULL materials on this mesh
-               if [mat for mat in my_mesh.blenMaterials if mat]:       
do_materials = True
-               else:                                                           
                                do_materials = False
+               if my_mesh.blenMaterials:       do_materials = True
+               else:                                           do_materials = 
False
                
                if my_mesh.blenTextures:        do_textures = True
-               else:                                           do_textures = 
False                     
+               else:                                           do_textures = 
False     
                
+               do_uvs = me.faceUV
                
+               
                file.write('\n\tModel: "Model::%s", "Mesh" {' % my_mesh.fbxName)
                file.write('\n\t\tVersion: 232') # newline is added in 
write_object_props
                
@@ -1516,7 +1537,7 @@
                
                # Write UV and texture layers.
                uvlayers = []
-               if me.faceUV:
+               if do_uvs:
                        uvlayers = me.getUVLayerNames()
                        uvlayer_orig = me.activeUVLayer
                        for uvindex, uvlayer in enumerate(uvlayers):
@@ -1635,32 +1656,32 @@
                                file.write('0')
                        else:
                                # Build a material mapping for this 
-                               #material_mapping_local = [0] * 16 # 
local-index : global index.
-                               material_mapping_local = [-1] * 16 # 
local-index : global index.
-                               i= 0 # 1
-                               for j, mat in enumerate(my_mesh.blenMaterials):
-                                       if mat:
-                                               material_mapping_local[j] = i
-                                               i+=1
-                                       # else leave as -1
+                               material_mapping_local = {} # local-mat & tex : 
global index.
                                
+                               for j, mat_tex_pair in 
enumerate(my_mesh.blenMaterials):
+                                       material_mapping_local[mat_tex_pair] = j
+                               
                                len_material_mapping_local = 
len(material_mapping_local)
                                
+                               mats = my_mesh.blenMaterialList
+                               
                                i=-1
                                for f in me.faces:
-                                       f_mat = f.mat
-                                       if f_mat >= len_material_mapping_local:
-                                               f_mat = 0
+                                       try:    mat = mats[f.mat]
+                                       except:mat = None
                                        
+                                       if do_uvs: tex = f.image # WARNING - 
MULTI UV LAYER IMAGES NOT SUPPORTED :/
+                                       else: tex = None
+                                       
                                        if i==-1:
                                                i=0
-                                               file.write( '%s' % 
(material_mapping_local[f_mat]))
+                                               file.write( '%s' % 
(material_mapping_local[mat, tex])) # None for mat or tex is ok
                                        else:
                                                if i==55:
                                                        file.write('\n\t\t\t\t')
                                                        i=0
                                                
-                                               file.write(',%s' % 
(material_mapping_local[f_mat]))
+                                               file.write(',%s' % 
(material_mapping_local[mat, tex]))
                                        i+=1
                        
                        file.write('\n\t\t}')
@@ -1695,7 +1716,7 @@
                                TypedIndex: 0
                        }''')
                
-               if me.faceUV:
+               if do_uvs: # same as me.faceUV
                        file.write('''
                        LayerElement:  {
                                Type: "LayerElementUV"
@@ -1777,8 +1798,8 @@
        ob_all_typegroups = [ob_meshes, ob_lights, ob_cameras, ob_arms, ob_null]
        
        groups = [] # blender groups, only add ones that have objects in the 
selections
-       materials = {}
-       textures = {}
+       materials = {} # (mat, image) keys, should be a set()
+       textures = {} # should be a set()
        
        tmp_ob_type = ob_type = None # incase no objects are exported, so as 
not to raise an error
        
@@ -1878,20 +1899,29 @@
                                        if EXP_MESH_HQ_NORMALS:
                                                BPyMesh.meshCalcNormals(me) # 
high quality normals nice for realtime engines.
                                        
-                                       for mat in mats:
-                                               # 2.44 use mat.lib too for 
uniqueness
-                                               if mat: materials[mat] = mat
-                                       
                                        texture_mapping_local = {}
+                                       material_mapping_local = {}
                                        if me.faceUV:
                                                uvlayer_orig = me.activeUVLayer
                                                for uvlayer in 
me.getUVLayerNames():
                                                        me.activeUVLayer = 
uvlayer
                                                        for f in me.faces:
-                                                               img = f.image
-                                                               textures[img] = 
texture_mapping_local[img] = img
+                                                               tex = f.image
+                                                               textures[tex] = 
texture_mapping_local[tex] = None
+                                                               
+                                                               try: mat = 
mats[f.mat]
+                                                               except: mat = 
None
+                                                               
+                                                               materials[mat, 
tex] = material_mapping_local[mat, tex] = None # should use sets, wait for 
blender 2.5
+                                                                       
                                                        
                                                        me.activeUVLayer = 
uvlayer_orig
+                                       else:
+                                               for mat in mats:
+                                                       # 2.44 use mat.lib too 
for uniqueness
+                                                       materials[mat, None] = 
material_mapping_local[mat, None] = None
+                                               else:
+                                                       materials[None, None] = 
None
                                        
                                        if EXP_ARMATURE:
                                                armob = 
BPyObject.getObjectArmature(ob)
@@ -1912,8 +1942,9 @@
                                        my_mesh = my_object_generic(ob, mtx)
                                        my_mesh.blenData =              me
                                        my_mesh.origData =              origData
-                                       my_mesh.blenMaterials = mats
-                                       my_mesh.blenTextures =  
texture_mapping_local.values()
+                                       my_mesh.blenMaterials = 
material_mapping_local.keys()
+                                       my_mesh.blenMaterialList = mats
+                                       my_mesh.blenTextures =  
texture_mapping_local.keys()
                                        
                                        # if only 1 null texture then empty the 
list
                                        if len(my_mesh.blenTextures) == 1 and 
my_mesh.blenTextures[0] == None:
@@ -2032,8 +2063,8 @@
        # Finished finding groups we use
        
        
-       materials =     [(sane_matname(mat), mat) for mat in 
materials.itervalues() if mat]
-       textures =      [(sane_texname(img), img) for img in 
textures.itervalues()  if img]
+       materials =     [(sane_matname(mat_tex_pair), mat_tex_pair) for 
mat_tex_pair in materials.iterkeys()]
+       textures =      [(sane_texname(tex), tex) for tex in 
textures.iterkeys()  if tex]
        materials.sort() # sort by name
        textures.sort()
        
@@ -2162,8 +2193,8 @@
        
        write_camera_default()
        
-       for matname, mat in materials:
-               write_material(matname, mat)
+       for matname, (mat, tex) in materials:
+               write_material(matname, mat) # We only need to have a material 
per image pair, but no need to write any image info into the material (dumb fbx 
standard)
        
        # each texture uses a video, odd
        for texname, tex in textures:
@@ -2283,7 +2314,7 @@
        Model: "Model::Camera Switcher", "CameraSwitcher" {
        }''')
        
-       for matname, mat in materials:
+       for matname, (mat, tex) in materials:
                file.write('\n\tMaterial: "Material::%s", "" {\n\t}' % matname)
 
        if textures:
@@ -2335,9 +2366,14 @@
        if materials:
                for my_mesh in ob_meshes:
                        # Connect all materials to all objects, not good form 
but ok for now.
-                       for mat in my_mesh.blenMaterials:
-                               if mat:
-                                       file.write('\n\tConnect: "OO", 
"Material::%s", "Model::%s"' % (sane_name_mapping_mat[mat.name], 
my_mesh.fbxName))
+                       for mat, tex in my_mesh.blenMaterials:
+                               if mat: mat_name = mat.name
+                               else:   mat_name = None
+                               
+                               if tex: tex_name = tex.name
+                               else:   tex_name = None
+                               
+                               file.write('\n\tConnect: "OO", "Material::%s", 
"Model::%s"' % (sane_name_mapping_mat[mat_name, tex_name], my_mesh.fbxName))
        
        if textures:
                for my_mesh in ob_meshes:


_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to