From 0b5dd429a255bf225d9501413fa2d9ba87dff13a Mon Sep 17 00:00:00 2001 From: Campbell Barton <ideasman42@gmail.com> Date: Tue, 20 Aug 2013 12:45:48 +0000 Subject: [PATCH] fbx improve mesh support. - support multiple materials per mesh. - support multiple UV layers. - fix but where an extra dummy face would be imported. --- io_scene_fbx/import_fbx.py | 119 +++++++++++++++++++++++++++---------- 1 file changed, 89 insertions(+), 30 deletions(-) diff --git a/io_scene_fbx/import_fbx.py b/io_scene_fbx/import_fbx.py index 2804358ad..ac4f1f8b3 100644 --- a/io_scene_fbx/import_fbx.py +++ b/io_scene_fbx/import_fbx.py @@ -49,6 +49,13 @@ def elem_find_first(elem, id_search, default=None): return default +def elem_find_iter(elem, id_search): + for fbx_item in elem.elems: + if fbx_item.id == id_search: + yield fbx_item + return [] + + def elem_find_first_string(elem, id_search): fbx_item = elem_find_first(elem, id_search) if fbx_item is not None: @@ -318,7 +325,7 @@ def blen_read_geom_layerinfo(fbx_layer): def blen_read_geom_array_mapped_vert( - blen_data, + mesh, blen_data, blend_attr, fbx_layer_data, fbx_layer_index, fbx_layer_mapping, fbx_layer_ref, stride, descr, @@ -329,7 +336,7 @@ def blen_read_geom_array_mapped_vert( assert(fbx_layer_index is None) # TODO, more generic support for mapping types for i, blen_data_item in enumerate(blen_data): - blen_data_item[:] = fbx_layer_data[(i * stride): (i * stride) + stride] + setattr(blen_data_item, blend_attr, fbx_layer_data[(i * stride): (i * stride) + stride]) return True else: print("warning layer %r ref type unsupported: %r" % (descr, fbx_layer_ref)) @@ -339,8 +346,32 @@ def blen_read_geom_array_mapped_vert( return False -def blen_read_geom_array_mapped_poly( - blen_data, +def blen_read_geom_array_mapped_polygon( + mesh, blen_data, blend_attr, + fbx_layer_data, fbx_layer_index, + fbx_layer_mapping, fbx_layer_ref, + stride, descr, + ): + + if fbx_layer_mapping == b'ByPolygon': + if fbx_layer_ref == b'IndexToDirect': + if stride == 1: + for i, blen_data_item in enumerate(blen_data): + setattr(blen_data_item, blend_attr, fbx_layer_data[i]) + else: + for i, blen_data_item in enumerate(blen_data): + setattr(blen_data_item, blend_attr, fbx_layer_data[(i * stride): (i * stride) + stride]) + return True + else: + print("warning layer %r ref type unsupported: %r" % (descr, fbx_layer_ref)) + else: + print("warning layer %r mapping type unsupported: %r" % (descr, fbx_layer_mapping)) + + return False + + +def blen_read_geom_array_mapped_polyloop( + mesh, blen_data, blend_attr, fbx_layer_data, fbx_layer_index, fbx_layer_mapping, fbx_layer_ref, stride, descr, @@ -350,43 +381,71 @@ def blen_read_geom_array_mapped_poly( if fbx_layer_ref == b'IndexToDirect': assert(fbx_layer_index is not None) for i, j in enumerate(fbx_layer_index): - blen_data[i][:] = fbx_layer_data[(j * stride): (j * stride) + stride] + setattr(blen_data[i], blend_attr, fbx_layer_data[(j * stride): (j * stride) + stride]) return True else: print("warning layer %r ref type unsupported: %r" % (descr, fbx_layer_ref)) + elif fbx_layer_mapping == b'ByVertice': + if fbx_layer_ref == b'Direct': + assert(fbx_layer_index is None) + loops = mesh.loops + polygons = mesh.polygons + for p in polygons: + for i in p.loop_indices: + j = loops[i].vertex_index + setattr(blen_data[i], blend_attr, fbx_layer_data[(j * stride): (j * stride) + stride]) + else: + print("warning layer %r ref type unsupported: %r" % (descr, fbx_layer_ref)) else: print("warning layer %r mapping type unsupported: %r" % (descr, fbx_layer_mapping)) return False -def blen_read_geom_layer_uv(fbx_obj, mesh): +def blen_read_geom_layer_materials(fbx_obj, mesh): + fbx_layer = elem_find_first(fbx_obj, b'LayerElementMaterial') - for layer_id in (b'LayerElementUV',): - fbx_layer = elem_find_first(fbx_obj, layer_id) + if fbx_layer is None: + return + + (fbx_layer_name, + fbx_layer_mapping, + fbx_layer_ref, + ) = blen_read_geom_layerinfo(fbx_layer) + + layer_id = b'Materials' + fbx_layer_data = elem_prop_first(elem_find_first(fbx_layer, layer_id)) + + blen_read_geom_array_mapped_polygon( + mesh, mesh.polygons, "material_index", + fbx_layer_data, None, + fbx_layer_mapping, fbx_layer_ref, + 1, layer_id, + ) - if fbx_layer is None: - continue - # all should be valid - (fbx_layer_name, - fbx_layer_mapping, - fbx_layer_ref, - ) = blen_read_geom_layerinfo(fbx_layer) +def blen_read_geom_layer_uv(fbx_obj, mesh): + for layer_id in (b'LayerElementUV',): + for fbx_layer in elem_find_iter(fbx_obj, layer_id): + # all should be valid + (fbx_layer_name, + fbx_layer_mapping, + fbx_layer_ref, + ) = blen_read_geom_layerinfo(fbx_layer) - fbx_layer_data = elem_prop_first(elem_find_first(fbx_layer, b'UV')) - fbx_layer_index = elem_prop_first(elem_find_first(fbx_layer, b'UVIndex')) + fbx_layer_data = elem_prop_first(elem_find_first(fbx_layer, b'UV')) + fbx_layer_index = elem_prop_first(elem_find_first(fbx_layer, b'UVIndex')) - uv_tex = mesh.uv_textures.new(name=fbx_layer_name) - uv_lay = mesh.uv_layers[fbx_layer_name] - blen_data = [luv.uv for luv in uv_lay.data] + uv_tex = mesh.uv_textures.new(name=fbx_layer_name) + uv_lay = mesh.uv_layers[fbx_layer_name] + blen_data = uv_lay.data[:] - blen_read_geom_array_mapped_poly( - blen_data, - fbx_layer_data, fbx_layer_index, - fbx_layer_mapping, fbx_layer_ref, - 2, layer_id, - ) + blen_read_geom_array_mapped_polyloop( + mesh, blen_data, "uv", + fbx_layer_data, fbx_layer_index, + fbx_layer_mapping, fbx_layer_ref, + 2, layer_id, + ) def blen_read_geom_layer_normal(fbx_obj, mesh): @@ -403,10 +462,10 @@ def blen_read_geom_layer_normal(fbx_obj, mesh): layer_id = b'Normals' fbx_layer_data = elem_prop_first(elem_find_first(fbx_layer, layer_id)) - blen_data = [v.normal for v in mesh.vertices] + blen_data = mesh.vertices return blen_read_geom_array_mapped_vert( - blen_data, + mesh, blen_data, "normal", fbx_layer_data, None, fbx_layer_mapping, fbx_layer_ref, 3, layer_id, @@ -446,13 +505,12 @@ def blen_read_geom(fbx_tmpl, fbx_obj): poly_loop_prev = i + 1 index = -(index + 1) l.vertex_index = index - poly_loop_starts.append(poly_loop_prev) - poly_loop_totals.append((i - poly_loop_prev) + 1) mesh.polygons.add(len(poly_loop_starts)) mesh.polygons.foreach_set("loop_start", poly_loop_starts) mesh.polygons.foreach_set("loop_total", poly_loop_totals) + blen_read_geom_layer_materials(fbx_obj, mesh) blen_read_geom_layer_uv(fbx_obj, mesh) ok_normals = blen_read_geom_layer_normal(fbx_obj, mesh) @@ -684,6 +742,7 @@ def load(operator, context, filepath="", # eg, (b'Texture', b'KFbxFileTexture') # (b'Geometry', b'KFbxMesh') fbx_templates = {} + def _(): if fbx_defs is not None: for fbx_def in fbx_defs.elems: -- GitLab