Newer
Older
for (fbx_lnk,
fbx_lnk_item,
fbx_lnk_type) in connection_filter_forward(fbx_uuid, b'Model'):
# link materials
fbx_lnk_uuid = elem_uuid(fbx_lnk)
for (fbx_lnk_material,
material,
fbx_lnk_material_type) in connection_filter_reverse(fbx_lnk_uuid, b'Material'):
mesh.materials.append(material)
Bastien Montagne
committed
# We have to validate mesh polygons' mat_idx, see T41015!
# Some FBX seem to have an extra 'default' material which is not defined in FBX file.
if mesh.validate_material_indices():
print("WARNING: mesh '%s' had invalid material indices, those were reset to first material" % mesh.name)
_(); del _
def _():
Campbell Barton
committed
material_images = {}
fbx_tmpl = fbx_template_get((b'Material', b'KFbxSurfacePhong'))
# b'KFbxSurfaceLambert'
# textures that use this material
def texture_bumpfac_get(fbx_obj):
assert(fbx_obj.id == b'Material')
fbx_props = (elem_find_first(fbx_obj, b'Properties70'),
elem_find_first(fbx_tmpl, b'Properties70', fbx_elem_nil))
assert(fbx_props[0] is not None)
# (x / 7.142) is only a guess, cycles usable range is (0.0 -> 0.5)
return elem_props_get_number(fbx_props, b'BumpFactor', 2.5) / 7.142
def texture_mapping_get(fbx_obj):
assert(fbx_obj.id == b'Texture')
fbx_props = (elem_find_first(fbx_obj, b'Properties70'),
elem_find_first(fbx_tmpl, b'Properties70', fbx_elem_nil))
assert(fbx_props[0] is not None)
return (elem_props_get_vector_3d(fbx_props, b'Translation', (0.0, 0.0, 0.0)),
elem_props_get_vector_3d(fbx_props, b'Rotation', (0.0, 0.0, 0.0)),
elem_props_get_vector_3d(fbx_props, b'Scaling', (1.0, 1.0, 1.0)),
(bool(elem_props_get_enum(fbx_props, b'WrapModeU', 0)),
bool(elem_props_get_enum(fbx_props, b'WrapModeV', 0))))
Campbell Barton
committed
if not use_cycles:
# Simple function to make a new mtex and set defaults
def material_mtex_new(material, image, tex_map):
Campbell Barton
committed
tex = texture_cache.get(image)
if tex is None:
tex = bpy.data.textures.new(name=image.name, type='IMAGE')
tex.image = image
texture_cache[image] = tex
mtex = material.texture_slots.add()
mtex.texture = tex
mtex.texture_coords = 'UV'
mtex.use_map_color_diffuse = False
# No rotation here...
mtex.offset[:] = tex_map[0]
mtex.scale[:] = tex_map[2]
Campbell Barton
committed
return mtex
for fbx_uuid, fbx_item in fbx_table_nodes.items():
fbx_obj, blen_data = fbx_item
if fbx_obj.id != b'Material':
continue
material = fbx_table_nodes[fbx_uuid][1]
for (fbx_lnk,
image,
fbx_lnk_type) in connection_filter_reverse(fbx_uuid, b'Texture'):
if use_cycles:
if fbx_lnk_type.props[0] == b'OP':
lnk_type = fbx_lnk_type.props[3]
ma_wrap = cycles_material_wrap_map[material]
# tx/rot/scale
tex_map = texture_mapping_get(fbx_lnk)
if (tex_map[0] == (0.0, 0.0, 0.0) and
tex_map[1] == (0.0, 0.0, 0.0) and
tex_map[2] == (1.0, 1.0, 1.0) and
tex_map[3] == (False, False)):
use_mapping = False
else:
use_mapping = True
tex_map_kw = {
"translation": tex_map[0],
"rotation": [-i for i in tex_map[1]],
"scale": [((1.0 / i) if i != 0.0 else 1.0) for i in tex_map[2]],
"clamp": tex_map[3],
if lnk_type == b'DiffuseColor':
ma_wrap.diffuse_image_set(image)
if use_mapping:
ma_wrap.diffuse_mapping_set(**tex_map_kw)
elif lnk_type == b'SpecularColor':
ma_wrap.specular_image_set(image)
if use_mapping:
ma_wrap.specular_mapping_set(**tex_map_kw)
elif lnk_type == b'ReflectionColor':
ma_wrap.reflect_image_set(image)
if use_mapping:
ma_wrap.reflect_mapping_set(**tex_map_kw)
Campbell Barton
committed
elif lnk_type == b'TransparentColor': # alpha
ma_wrap.alpha_image_set(image)
if use_mapping:
ma_wrap.alpha_mapping_set(**tex_map_kw)
Campbell Barton
committed
if use_alpha_decals:
material_decals.add(material)
elif lnk_type == b'DiffuseFactor':
pass # TODO
elif lnk_type == b'ShininessExponent':
ma_wrap.hardness_image_set(image)
if use_mapping:
ma_wrap.hardness_mapping_set(**tex_map_kw)
elif lnk_type == b'NormalMap' or lnk_type == b'Bump': # XXX, applications abuse bump!
ma_wrap.normal_image_set(image)
ma_wrap.normal_factor_set(texture_bumpfac_get(fbx_obj))
if use_mapping:
ma_wrap.normal_mapping_set(**tex_map_kw)
"""
elif lnk_type == b'Bump':
ma_wrap.bump_image_set(image)
ma_wrap.bump_factor_set(texture_bumpfac_get(fbx_obj))
if use_mapping:
ma_wrap.bump_mapping_set(**tex_map_kw)
"""
Campbell Barton
committed
else:
print("WARNING: material link %r ignored" % lnk_type)
material_images.setdefault(material, {})[lnk_type] = image
else:
if fbx_lnk_type.props[0] == b'OP':
lnk_type = fbx_lnk_type.props[3]
# tx/rot/scale (rot is ignored here!).
tex_map = texture_mapping_get(fbx_lnk)
mtex = material_mtex_new(material, image, tex_map)
if lnk_type == b'DiffuseColor':
mtex.use_map_color_diffuse = True
mtex.blend_type = 'MULTIPLY'
elif lnk_type == b'SpecularColor':
mtex.use_map_color_spec = True
mtex.blend_type = 'MULTIPLY'
elif lnk_type == b'ReflectionColor':
mtex.use_map_raymir = True
Campbell Barton
committed
elif lnk_type == b'TransparentColor': # alpha
material.use_transparency = True
material.transparency_method = 'RAYTRACE'
material.alpha = 0.0
mtex.use_map_alpha = True
mtex.alpha_factor = 1.0
if use_alpha_decals:
material_decals.add(material)
elif lnk_type == b'DiffuseFactor':
mtex.use_map_diffuse = True
elif lnk_type == b'ShininessExponent':
mtex.use_map_hardness = True
elif lnk_type == b'NormalMap' or lnk_type == b'Bump': # XXX, applications abuse bump!
mtex.texture.use_normal_map = True # not ideal!
mtex.use_map_normal = True
mtex.normal_factor = texture_bumpfac_get(fbx_obj)
elif lnk_type == b'Bump':
mtex.use_map_normal = True
mtex.normal_factor = texture_bumpfac_get(fbx_obj)
else:
print("WARNING: material link %r ignored" % lnk_type)
Campbell Barton
committed
material_images.setdefault(material, {})[lnk_type] = image
# Check if the diffuse image has an alpha channel,
# if so, use the alpha channel.
# Note: this could be made optional since images may have alpha but be entirely opaque
for fbx_uuid, fbx_item in fbx_table_nodes.items():
fbx_obj, blen_data = fbx_item
if fbx_obj.id != b'Material':
continue
material = fbx_table_nodes[fbx_uuid][1]
image = material_images.get(material, {}).get(b'DiffuseColor')
# do we have alpha?
if image and image.depth == 32:
if use_alpha_decals:
material_decals.add(material)
Campbell Barton
committed
if use_cycles:
ma_wrap = cycles_material_wrap_map[material]
if ma_wrap.node_bsdf_alpha.mute:
ma_wrap.alpha_image_set_from_diffuse()
else:
if not any((True for mtex in material.texture_slots if mtex and mtex.use_map_alpha)):
mtex = material_mtex_new(material, image)
material.use_transparency = True
material.transparency_method = 'RAYTRACE'
material.alpha = 0.0
mtex.use_map_alpha = True
mtex.alpha_factor = 1.0
# propagate mapping from diffuse to all other channels which have none defined.
if use_cycles:
ma_wrap = cycles_material_wrap_map[material]
ma_wrap.mapping_set_from_diffuse()
_(); del _
Campbell Barton
committed
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
def _():
# Annoying workaround for cycles having no z-offset
if material_decals and use_alpha_decals:
for fbx_uuid, fbx_item in fbx_table_nodes.items():
fbx_obj, blen_data = fbx_item
if fbx_obj.id != b'Geometry':
continue
if fbx_obj.props[-1] == b'Mesh':
mesh = fbx_item[1]
if decal_offset != 0.0:
for material in mesh.materials:
if material in material_decals:
for v in mesh.vertices:
v.co += v.normal * decal_offset
break
if use_cycles:
for obj in (obj for obj in bpy.data.objects if obj.data == mesh):
obj.cycles_visibility.shadow = False
else:
for material in mesh.materials:
if material in material_decals:
# recieve but dont cast shadows
material.use_raytrace = False
_(); del _
print('Import finished in %.4f sec.' % (time.process_time() - start_time))
return {'FINISHED'}