Skip to content
Snippets Groups Projects
Commit 0b5dd429 authored by Campbell Barton's avatar Campbell Barton
Browse files

fbx improve mesh support.

- support multiple materials per mesh.
- support multiple UV layers.
- fix but where an extra dummy face would be imported.
parent 23d5d287
No related branches found
No related tags found
No related merge requests found
...@@ -49,6 +49,13 @@ def elem_find_first(elem, id_search, default=None): ...@@ -49,6 +49,13 @@ def elem_find_first(elem, id_search, default=None):
return default 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): def elem_find_first_string(elem, id_search):
fbx_item = elem_find_first(elem, id_search) fbx_item = elem_find_first(elem, id_search)
if fbx_item is not None: if fbx_item is not None:
...@@ -318,7 +325,7 @@ def blen_read_geom_layerinfo(fbx_layer): ...@@ -318,7 +325,7 @@ def blen_read_geom_layerinfo(fbx_layer):
def blen_read_geom_array_mapped_vert( def blen_read_geom_array_mapped_vert(
blen_data, mesh, blen_data, blend_attr,
fbx_layer_data, fbx_layer_index, fbx_layer_data, fbx_layer_index,
fbx_layer_mapping, fbx_layer_ref, fbx_layer_mapping, fbx_layer_ref,
stride, descr, stride, descr,
...@@ -329,7 +336,7 @@ def blen_read_geom_array_mapped_vert( ...@@ -329,7 +336,7 @@ def blen_read_geom_array_mapped_vert(
assert(fbx_layer_index is None) assert(fbx_layer_index is None)
# TODO, more generic support for mapping types # TODO, more generic support for mapping types
for i, blen_data_item in enumerate(blen_data): 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 return True
else: else:
print("warning layer %r ref type unsupported: %r" % (descr, fbx_layer_ref)) print("warning layer %r ref type unsupported: %r" % (descr, fbx_layer_ref))
...@@ -339,8 +346,32 @@ def blen_read_geom_array_mapped_vert( ...@@ -339,8 +346,32 @@ def blen_read_geom_array_mapped_vert(
return False return False
def blen_read_geom_array_mapped_poly( def blen_read_geom_array_mapped_polygon(
blen_data, 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_data, fbx_layer_index,
fbx_layer_mapping, fbx_layer_ref, fbx_layer_mapping, fbx_layer_ref,
stride, descr, stride, descr,
...@@ -350,43 +381,71 @@ def blen_read_geom_array_mapped_poly( ...@@ -350,43 +381,71 @@ def blen_read_geom_array_mapped_poly(
if fbx_layer_ref == b'IndexToDirect': if fbx_layer_ref == b'IndexToDirect':
assert(fbx_layer_index is not None) assert(fbx_layer_index is not None)
for i, j in enumerate(fbx_layer_index): 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 return True
else: else:
print("warning layer %r ref type unsupported: %r" % (descr, fbx_layer_ref)) 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: else:
print("warning layer %r mapping type unsupported: %r" % (descr, fbx_layer_mapping)) print("warning layer %r mapping type unsupported: %r" % (descr, fbx_layer_mapping))
return False 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',): if fbx_layer is None:
fbx_layer = elem_find_first(fbx_obj, layer_id) 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 def blen_read_geom_layer_uv(fbx_obj, mesh):
(fbx_layer_name, for layer_id in (b'LayerElementUV',):
fbx_layer_mapping, for fbx_layer in elem_find_iter(fbx_obj, layer_id):
fbx_layer_ref, # all should be valid
) = blen_read_geom_layerinfo(fbx_layer) (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_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_index = elem_prop_first(elem_find_first(fbx_layer, b'UVIndex'))
uv_tex = mesh.uv_textures.new(name=fbx_layer_name) uv_tex = mesh.uv_textures.new(name=fbx_layer_name)
uv_lay = mesh.uv_layers[fbx_layer_name] uv_lay = mesh.uv_layers[fbx_layer_name]
blen_data = [luv.uv for luv in uv_lay.data] blen_data = uv_lay.data[:]
blen_read_geom_array_mapped_poly( blen_read_geom_array_mapped_polyloop(
blen_data, mesh, blen_data, "uv",
fbx_layer_data, fbx_layer_index, fbx_layer_data, fbx_layer_index,
fbx_layer_mapping, fbx_layer_ref, fbx_layer_mapping, fbx_layer_ref,
2, layer_id, 2, layer_id,
) )
def blen_read_geom_layer_normal(fbx_obj, mesh): def blen_read_geom_layer_normal(fbx_obj, mesh):
...@@ -403,10 +462,10 @@ 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' layer_id = b'Normals'
fbx_layer_data = elem_prop_first(elem_find_first(fbx_layer, layer_id)) 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( return blen_read_geom_array_mapped_vert(
blen_data, mesh, blen_data, "normal",
fbx_layer_data, None, fbx_layer_data, None,
fbx_layer_mapping, fbx_layer_ref, fbx_layer_mapping, fbx_layer_ref,
3, layer_id, 3, layer_id,
...@@ -446,13 +505,12 @@ def blen_read_geom(fbx_tmpl, fbx_obj): ...@@ -446,13 +505,12 @@ def blen_read_geom(fbx_tmpl, fbx_obj):
poly_loop_prev = i + 1 poly_loop_prev = i + 1
index = -(index + 1) index = -(index + 1)
l.vertex_index = index 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.add(len(poly_loop_starts))
mesh.polygons.foreach_set("loop_start", poly_loop_starts) mesh.polygons.foreach_set("loop_start", poly_loop_starts)
mesh.polygons.foreach_set("loop_total", poly_loop_totals) 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) blen_read_geom_layer_uv(fbx_obj, mesh)
ok_normals = blen_read_geom_layer_normal(fbx_obj, mesh) ok_normals = blen_read_geom_layer_normal(fbx_obj, mesh)
...@@ -684,6 +742,7 @@ def load(operator, context, filepath="", ...@@ -684,6 +742,7 @@ def load(operator, context, filepath="",
# eg, (b'Texture', b'KFbxFileTexture') # eg, (b'Texture', b'KFbxFileTexture')
# (b'Geometry', b'KFbxMesh') # (b'Geometry', b'KFbxMesh')
fbx_templates = {} fbx_templates = {}
def _(): def _():
if fbx_defs is not None: if fbx_defs is not None:
for fbx_def in fbx_defs.elems: for fbx_def in fbx_defs.elems:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment