def detect_manual_uv_wrapping(blender_shader_node):
    # Detects UV wrapping done using math nodes. This is for emulating wrap
    # modes Blender doesn't support. It looks like
    #
    #     next_socket => [Sep XYZ] => [Wrap S] => [Comb XYZ] => blender_shader_node
    #                              => [Wrap T] =>
    #
    # The [Wrap _] blocks are either math nodes (eg. PINGPONG for mirrored
    # repeat), or can be omitted.
    #
    # Returns None if not detected. Otherwise a dict containing the wrap
    # mode in each direction (or None), and next_socket.
    result = {}

    comb = previous_node(blender_shader_node.inputs['Vector'])
    if comb is None or comb.type != 'COMBXYZ': return None

    for soc in ['X', 'Y']:
        node = previous_node(comb.inputs[soc])
        if node is None: return None

        if node.type == 'SEPXYZ':
            # Passed through without change
            wrap = None
            prev_socket = previous_socket(comb.inputs[soc])
        elif node.type == 'MATH':
            # Math node applies a manual wrap
            if (node.operation == 'PINGPONG' and get_const_from_socket(
                    node.inputs[1], kind='VALUE') == 1.0):  # scale = 1
                wrap = TextureWrap.MirroredRepeat
            elif (node.operation == 'WRAP' and get_const_from_socket(
                    node.inputs[1], kind='VALUE') == 0.0 and  # min = 0
                  get_const_from_socket(node.inputs[2], kind='VALUE')
                  == 1.0):  # max = 1
                wrap = TextureWrap.Repeat
            else:
                return None

            prev_socket = previous_socket(node.inputs[0])
        else:
            return None

        if prev_socket is None: return None
        prev_node = prev_socket.node
        if prev_node.type != 'SEPXYZ': return None
        # Make sure X goes to X, etc.
        if prev_socket.name != soc: return None
        # Make sure both attach to the same SeparateXYZ node
        if soc == 'X':
            sep = prev_node
        else:
            if sep != prev_node: return None

        result['wrap_s' if soc == 'X' else 'wrap_t'] = wrap

    result['next_socket'] = sep.inputs[0]
    return result
Exemplo n.º 2
0
def __gather_occlusion_strength(primary_socket, export_settings):
    # Look for a MixRGB node that mixes with pure white in front of
    # primary_socket. The mix factor gives the occlusion strength.
    node = gltf2_blender_get.previous_node(primary_socket)
    if node and node.type == 'MIX_RGB' and node.blend_type == 'MIX':
        fac = gltf2_blender_get.get_const_from_socket(node.inputs['Fac'], kind='VALUE')
        col1 = gltf2_blender_get.get_const_from_socket(node.inputs['Color1'], kind='RGB')
        col2 = gltf2_blender_get.get_const_from_socket(node.inputs['Color2'], kind='RGB')
        if fac is not None:
            if col1 == [1, 1, 1] and col2 is None:
                return fac
            if col1 is None and col2 == [1, 1, 1]:
                return 1.0 - fac  # reversed for reversed inputs

    return None
def __gather_emissive_factor(blender_material, export_settings):
    emissive_socket = gltf2_blender_get.get_socket(blender_material,
                                                   "Emissive")
    if emissive_socket is None:
        emissive_socket = gltf2_blender_get.get_socket_old(
            blender_material, "EmissiveFactor")
    if isinstance(emissive_socket, bpy.types.NodeSocket):
        if export_settings['gltf_image_format'] != "NONE":
            factor = gltf2_blender_get.get_factor_from_socket(emissive_socket,
                                                              kind='RGB')
        else:
            factor = gltf2_blender_get.get_const_from_default_value_socket(
                emissive_socket, kind='RGB')

        if factor is None and emissive_socket.is_linked:
            # In glTF, the default emissiveFactor is all zeros, so if an emission texture is connected,
            # we have to manually set it to all ones.
            factor = [1.0, 1.0, 1.0]

        if factor is None: factor = [0.0, 0.0, 0.0]

        # Handle Emission Strength
        strength_socket = None
        if emissive_socket.node.type == 'EMISSION':
            strength_socket = emissive_socket.node.inputs['Strength']
        elif 'Emission Strength' in emissive_socket.node.inputs:
            strength_socket = emissive_socket.node.inputs['Emission Strength']
        strength = (gltf2_blender_get.get_const_from_socket(strength_socket,
                                                            kind='VALUE')
                    if strength_socket is not None else None)
        if strength is not None:
            factor = [f * strength for f in factor]

        # Clamp to range [0,1]
        factor = [min(1.0, f) for f in factor]

        if factor == [0, 0, 0]: factor = None

        return factor

    return None