def __get_image_data(sockets_or_slots):
    # For shared ressources, such as images, we just store the portion of data that is needed in the glTF property
    # in a helper class. During generation of the glTF in the exporter these will then be combined to actual binary
    # ressources.
    def split_pixels_by_channels(
            image: bpy.types.Image) -> typing.List[typing.List[float]]:
        pixels = np.array(image.pixels)
        pixels = pixels.reshape(
            (pixels.shape[0] // image.channels, image.channels))
        channels = np.split(pixels, pixels.shape[1], axis=1)
        return channels

    if __is_socket(sockets_or_slots):
        results = [
            __get_tex_from_socket(socket) for socket in sockets_or_slots
        ]
        image = None
        for result, socket in zip(results, sockets_or_slots):
            # rudimentarily try follow the node tree to find the correct image data.
            channel = None
            for elem in result.path:
                if isinstance(elem.from_node, bpy.types.ShaderNodeSeparateRGB):
                    channel = {'R': 0, 'G': 1, 'B': 2}[elem.from_socket.name]

            if channel is not None:
                pixels = [
                    split_pixels_by_channels(result.shader_node.image)[channel]
                ]
            else:
                pixels = split_pixels_by_channels(result.shader_node.image)
                channel = 0

            file_name = os.path.splitext(result.shader_node.image.name)[0]

            image_data = gltf2_io_image_data.ImageData(
                file_name, result.shader_node.image.size[0],
                result.shader_node.image.size[1], channel, pixels)

            if image is None:
                image = image_data
            else:
                image.add_to_image(channel, image_data)

        return image
    elif __is_slot(sockets_or_slots):
        texture = __get_tex_from_slot(sockets_or_slots[0])
        pixels = split_pixels_by_channels(texture.image)

        image_data = gltf2_io_image_data.ImageData(texture.name,
                                                   texture.image.size[0],
                                                   texture.image.size[1], 0,
                                                   pixels)
        return image_data
    else:
        # Texture slots
        raise NotImplementedError()
Esempio n. 2
0
def __gather_uri(image_data, mime_type, name, export_settings):
    if export_settings[gltf2_blender_export_keys.FORMAT] == 'GLTF_SEPARATE':
        # as usual we just store the data in place instead of already resolving the references
        return gltf2_io_image_data.ImageData(
            data=image_data.encode(mime_type=mime_type),
            mime_type=mime_type,
            name=name)

    return None
Esempio n. 3
0
def __gather_uri(image_data: bytes, image_name: str, mime_type: str,
                 export_settings):
    if export_settings[gltf2_blender_export_keys.FORMAT] == 'GLTF_SEPARATE':
        return gltf2_io_image_data.ImageData(
            data=image_data,
            mime_type=mime_type,
            name=image_name,
        )
    return None
def __gather_uri(sockets_or_slots, export_settings):
    if export_settings[gltf2_blender_export_keys.FORMAT] == 'GLTF_SEPARATE':
        # as usual we just store the data in place instead of already resolving the references
        mime_type = __gather_mime_type(sockets_or_slots, export_settings)
        return gltf2_io_image_data.ImageData(
            data=__get_image_data(sockets_or_slots,
                                  export_settings).encode(mime_type=mime_type),
            mime_type=mime_type,
            name=__gather_name(sockets_or_slots, export_settings))

    return None
def __get_image_data(sockets_or_slots, export_settings):
    # For shared ressources, such as images, we just store the portion of data that is needed in the glTF property
    # in a helper class. During generation of the glTF in the exporter these will then be combined to actual binary
    # ressources.
    def split_pixels_by_channels(
            image: bpy.types.Image, export_settings
    ) -> typing.Optional[typing.List[typing.List[float]]]:
        channelcache = export_settings['gltf_channelcache']
        if image.name in channelcache:
            return channelcache[image.name]

        pixels = np.array(image.pixels)
        pixels = pixels.reshape(
            (pixels.shape[0] // image.channels, image.channels))
        channels = np.split(pixels, pixels.shape[1], axis=1)

        channelcache[image.name] = channels

        return channels

    if __is_socket(sockets_or_slots):
        results = [
            __get_tex_from_socket(socket) for socket in sockets_or_slots
        ]
        image = None
        for result, socket in zip(results, sockets_or_slots):
            if result.shader_node.image.channels == 0:
                gltf2_io_debug.print_console(
                    "WARNING",
                    "Image '{}' has no color channels and cannot be exported.".
                    format(result.shader_node.image))
                continue

            # rudimentarily try follow the node tree to find the correct image data.
            source_channel = None
            target_channel = None
            source_channels_length = None
            for elem in result.path:
                if isinstance(elem.from_node, bpy.types.ShaderNodeSeparateRGB):
                    source_channel = {
                        'R': 0,
                        'G': 1,
                        'B': 2
                    }[elem.from_socket.name]

            if source_channel is not None:
                pixels = [
                    split_pixels_by_channels(result.shader_node.image,
                                             export_settings)[source_channel]
                ]
                target_channel = source_channel
                source_channel = 0
                source_channels_length = 1
            else:
                pixels = split_pixels_by_channels(result.shader_node.image,
                                                  export_settings)
                target_channel = 0
                source_channel = 0
                source_channels_length = len(pixels)

            # Change target channel for metallic and roughness.
            if elem.to_socket.name == 'Metallic':
                target_channel = 2
                source_channels_length = 1
            elif elem.to_socket.name == 'Roughness':
                target_channel = 1
                source_channels_length = 1

            file_name = os.path.splitext(result.shader_node.image.name)[0]
            if result.shader_node.image.packed_file is None:
                file_path = result.shader_node.image.filepath
            else:
                # empty path for packed textures, because they are converted to png anyway
                file_path = ""

            image_data = gltf2_io_image_data.ImageData(
                file_name, file_path, result.shader_node.image.size[0],
                result.shader_node.image.size[1], source_channel,
                target_channel, source_channels_length, pixels)

            if image is None:
                image = image_data
            else:
                image.add_to_image(target_channel, image_data)

        return image
    elif __is_slot(sockets_or_slots):
        texture = __get_tex_from_slot(sockets_or_slots[0])
        pixels = split_pixels_by_channels(texture.image, export_settings)

        image_data = gltf2_io_image_data.ImageData(texture.name,
                                                   texture.image.filepath,
                                                   texture.image.size[0],
                                                   texture.image.size[1], 0, 0,
                                                   len(pixels), pixels)
        return image_data
    else:
        # Texture slots
        raise NotImplementedError()