diff --git a/io_scene_3ds/export_3ds.py b/io_scene_3ds/export_3ds.py index 156c1dcba..34243e9dd 100644 --- a/io_scene_3ds/export_3ds.py +++ b/io_scene_3ds/export_3ds.py @@ -1566,21 +1566,42 @@ def save(operator, context, filepath="", scale_factor=1.0, apply_unit=False, use object_info.add_subchunk(ambient_chunk) if world.use_nodes: ntree = world.node_tree.links - background_color = _3ds_chunk(RGB) + background_color_chunk = _3ds_chunk(RGB) background_chunk = _3ds_chunk(SOLIDBACKGND) background_flag = _3ds_chunk(USE_SOLIDBGND) - amcol, bgcol, bgtex, nworld = 'EMISSION', 'BACKGROUND', 'TEX_ENVIRONMENT', 'OUTPUT_WORLD' - bg_color = next((lk.from_node.inputs[0].default_value[:3] for lk in ntree if lk.to_node.type == bgcol), world.color) - bg_image = next((lk.from_node.image.name for lk in ntree if lk.from_node.type == bgtex and lk.to_node.type in {amcol, bgcol}), False) - background_color.add_variable("color", _3ds_float_color(bg_color)) - background_chunk.add_subchunk(background_color) - object_info.add_subchunk(background_chunk) + bgshader = 'ADD_SHADER', 'MIX_SHADER', 'OUTPUT_WORLD' + bgtexture = 'TEX_IMAGE', 'TEX_ENVIRONMENT' + acol, bcol = 'EMISSION', 'BACKGROUND' + bg_color = next((lk.from_node.inputs[0].default_value[:3] for lk in ntree if lk.from_node.type == bcol and lk.to_node.type in bgshader), world.color) + bg_image = next((lk.from_node.image.name for lk in ntree if lk.from_node.type in bgtexture and lk.to_node.type in {acol, bcol}), False) + background_color_chunk.add_variable("color", _3ds_float_color(bg_color)) + background_chunk.add_subchunk(background_color_chunk) if bg_image: background_image = _3ds_chunk(BITMAP) background_flag = _3ds_chunk(USE_BITMAP) background_image.add_variable("image", _3ds_string(sane_name(bg_image))) object_info.add_subchunk(background_image) + object_info.add_subchunk(background_chunk) object_info.add_subchunk(background_flag) + fogshader = next((lk.from_socket.node for lk in ntree if lk.from_socket.identifier and lk.to_socket.identifier == 'Volume'), False) + if fogshader: + fogflag = 0 + if world.mist_settings.falloff == 'QUADRATIC': + fogflag |= 0x1 + if world.mist_settings.falloff == 'INVERSE_QUADRATIC': + fogflag |= 0x2 + fog_chunk = _3ds_chunk(LAYER_FOG) + fog_color_chunk = _3ds_chunk(RGB) + use_fog_flag = _3ds_chunk(USE_LAYER_FOG) + fog_color_chunk.add_variable("color", _3ds_float_color(fogshader.inputs[0].default_value[:3])) + fog_chunk.add_variable("lowZ", _3ds_float(world.mist_settings.start)) + fog_chunk.add_variable("highZ", _3ds_float(world.mist_settings.depth)) + fog_chunk.add_variable("density", _3ds_float(fogshader.inputs[1].default_value)) + fog_chunk.add_variable("flags", _3ds_uint(fogflag)) + fog_chunk.add_subchunk(fog_color_chunk) + object_info.add_subchunk(fog_chunk) + if layer.use_pass_mist: + object_info.add_subchunk(use_fog_flag) if write_keyframe and world.animation_data: kfdata.add_subchunk(make_ambient_node(world)) diff --git a/io_scene_3ds/import_3ds.py b/io_scene_3ds/import_3ds.py index 9b431bcdb..bba5e4703 100644 --- a/io_scene_3ds/import_3ds.py +++ b/io_scene_3ds/import_3ds.py @@ -701,15 +701,15 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI realname, ext = os.path.splitext(filename) contextWorld = bpy.data.worlds.new("Background: " + realname) context.scene.world = contextWorld + contextWorld.use_nodes = True + read_chunk(file, temp_chunk) + if temp_chunk.ID == COLOR_F: + contextWorld.node_tree.nodes['Background'].inputs[0].default_value[:3] = read_float_array(temp_chunk) + elif temp_chunk.ID == LIN_COLOR_F: + contextWorld.node_tree.nodes['Background'].inputs[0].default_value[:3] = read_float_array(temp_chunk) else: - contextWorld.use_nodes = True - read_chunk(file, temp_chunk) - if temp_chunk.ID == COLOR_F: - contextWorld.node_tree.nodes['Background'].inputs[0].default_value[:3] = read_float_array(temp_chunk) - elif temp_chunk.ID == LIN_COLOR_F: - contextWorld.node_tree.nodes['Background'].inputs[0].default_value[:3] = read_float_array(temp_chunk) - else: skip_to_end(file, temp_chunk) - new_chunk.bytes_read += temp_chunk.bytes_read + skip_to_end(file, temp_chunk) + new_chunk.bytes_read += temp_chunk.bytes_read # If bitmap chunk elif CreateWorld and new_chunk.ID == BITMAP: @@ -719,45 +719,50 @@ def process_next_chunk(context, file, previous_chunk, imported_objects, CONSTRAI realname, ext = os.path.splitext(filename) contextWorld = bpy.data.worlds.new("Bitmap: " + realname) context.scene.world = contextWorld - else: - contextWorld.use_nodes = True - links = contextWorld.node_tree.links - nodes = contextWorld.node_tree.nodes - bitmapnode = nodes.new(type='ShaderNodeTexEnvironment') - bitmapnode.label = bitmap_name - bitmapnode.location = (-300, 300) - bitmapnode.image = load_image(bitmap_name, dirname, place_holder=False, recursive=image_search, check_existing=True) - links.new(bitmapnode.outputs['Color'], nodes['Background'].inputs[0]) - new_chunk.bytes_read += read_str_len + contextWorld.use_nodes = True + links = contextWorld.node_tree.links + nodes = contextWorld.node_tree.nodes + bitmapnode = nodes.new(type='ShaderNodeTexEnvironment') + bitmapnode.label = bitmap_name + bitmapnode.location = (-300, 300) + bitmapnode.image = load_image(bitmap_name, dirname, place_holder=False, recursive=image_search, check_existing=True) + links.new(bitmapnode.outputs['Color'], nodes['Background'].inputs[0]) + new_chunk.bytes_read += read_str_len # If fog chunk elif CreateWorld and new_chunk.ID == LAYER_FOG: + """Fog options flags are bit 20 (0x100000) for background fogging, + bit 0 (0x1) for bottom falloff, and bit 1 (0x2) for top falloff.""" if contextWorld is None: path, filename = os.path.split(file.name) realname, ext = os.path.splitext(filename) contextWorld = bpy.data.worlds.new("LayerFog: " + realname) context.scene.world = contextWorld + contextWorld.use_nodes = True + links = contextWorld.node_tree.links + nodes = contextWorld.node_tree.nodes + layerfog = nodes.new(type='ShaderNodeVolumeScatter') + layerfog.label = "Layer Fog" + layerfog.location = (300, 100) + links.new(layerfog.outputs['Volume'], nodes['World Output'].inputs['Volume']) + context.view_layer.use_pass_mist = False + contextWorld.mist_settings.use_mist = True + contextWorld.mist_settings.start = read_float(new_chunk) + contextWorld.mist_settings.depth = read_float(new_chunk) + layerfog.inputs[1].default_value = read_float(new_chunk) + layerfog_flag = read_long(new_chunk) + if layerfog_flag & 0x1: + contextWorld.mist_settings.falloff = 'QUADRATIC' + if layerfog_flag & 0x2: + contextWorld.mist_settings.falloff = 'INVERSE_QUADRATIC' + read_chunk(file, temp_chunk) + if temp_chunk.ID == COLOR_F: + layerfog.inputs[0].default_value[:3] = read_float_array(temp_chunk) + elif temp_chunk.ID == LIN_COLOR_F: + layerfog.inputs[0].default_value[:3] = read_float_array(temp_chunk) else: - contextWorld.use_nodes = True - links = contextWorld.node_tree.links - nodes = contextWorld.node_tree.nodes - context.view_layer.use_pass_mist = False - layerfog = nodes.new(type='ShaderNodeVolumeScatter') - layerfog.label = "Layer Fog" - layerfog.location = (300, 100) - links.new(layerfog.outputs['Volume'], nodes['World Output'].inputs['Volume']) - contextWorld.mist_settings.start = read_float(new_chunk) - contextWorld.mist_settings.depth = read_float(new_chunk) - layerfog.inputs[1].default_value = read_float(new_chunk) - layerfogflag = read_long(new_chunk) - read_chunk(file, temp_chunk) - if temp_chunk.ID == COLOR_F: - layerfog.inputs[0].default_value[:3] = read_float_array(temp_chunk) - elif temp_chunk.ID == LIN_COLOR_F: - layerfog.inputs[0].default_value[:3] = read_float_array(temp_chunk) - else: - skip_to_end(file, temp_chunk) - new_chunk.bytes_read += temp_chunk.bytes_read + skip_to_end(file, temp_chunk) + new_chunk.bytes_read += temp_chunk.bytes_read elif CreateWorld and new_chunk.ID == USE_LAYER_FOG: context.view_layer.use_pass_mist = True