Esempio n. 1
0
def get_texture(texture_path, texture_type, report_invalid=False):
    """Creates and setup Texture and Image data on active Material.

    :param texture_path: Texture path
    :type texture_path: str
    :param texture_type: Texture type keyword
    :type texture_type: str
    :param report_invalid: flag indicating if invalid texture should be reported in 3d view
    :type report_invalid: bool
    """

    # CREATE TEXTURE/IMAGE ID NAME
    teximag_id_name = _path.get_filename(texture_path, with_ext=False)

    # CREATE ABSOLUTE FILEPATH
    abs_texture_filepath = _path.get_abs_path(texture_path)

    # return None on non-existing texture file path
    if not abs_texture_filepath or not os.path.isfile(abs_texture_filepath):
        return None

    if abs_texture_filepath.endswith(".tobj"):
        abs_texture_filepath = _path.get_texture_path_from_tobj(abs_texture_filepath)

        # if not existing or none supported file
        if abs_texture_filepath is None or abs_texture_filepath[-4:] not in (".tga", ".png", ".dds"):

            if report_invalid:
                lprint("", report_warnings=-1, report_errors=-1)

            # take care of none existing paths referenced in tobj texture names
            if abs_texture_filepath:

                lprint("W Texture can't be displayed as TOBJ file: %r is referencing non texture file:\n\t   %r",
                       (texture_path, _path.readable_norm(abs_texture_filepath)))

            else:

                lprint("W Texture can't be displayed as TOBJ file: %r is referencing non existing texture file.",
                       (texture_path,))

            if report_invalid:
                lprint("", report_warnings=1, report_errors=1)

            return None

    texture = None
    if abs_texture_filepath and os.path.isfile(abs_texture_filepath):

        # find existing texture with this image
        if teximag_id_name in bpy.data.textures:

            # reuse existing image texture if possible
            postfix = 0
            postfixed_tex = teximag_id_name
            while postfixed_tex in bpy.data.textures:

                img_exists = bpy.data.textures[postfixed_tex].image is not None
                if img_exists and _path.repair_path(bpy.data.textures[postfixed_tex].image.filepath) == _path.repair_path(abs_texture_filepath):
                    texture = bpy.data.textures[postfixed_tex]
                    break

                postfix += 1
                postfixed_tex = teximag_id_name + "." + str(postfix).zfill(3)

        # if texture wasn't found create new one
        if not texture:

            texture = bpy.data.textures.new(teximag_id_name, 'IMAGE')
            image = None

            # reuse existing image if possible
            postfix = 0
            postfixed_img = teximag_id_name
            while postfixed_img in bpy.data.images:

                if _path.repair_path(bpy.data.images[postfixed_img].filepath) == _path.repair_path(abs_texture_filepath):
                    image = bpy.data.images[postfixed_img]
                    break

                postfix += 1
                postfixed_img = teximag_id_name + "." + str(postfix).zfill(3)

            # if image wasn't found load it
            if not image:
                image = bpy.data.images.load(abs_texture_filepath)
                image.name = teximag_id_name

                # try to get relative path to the Blender file and set it to the image
                if bpy.data.filepath != '':  # empty file path means blender file is not saved
                    try:
                        rel_path = _path.relative_path(os.path.dirname(bpy.data.filepath), abs_texture_filepath)
                    except ValueError:  # catch different mount paths: "path is on mount 'C:', start on mount 'E:'"
                        rel_path = None

                    if rel_path:
                        image.filepath = rel_path

            # finally link image to texture
            texture.image = image
            image.use_alpha = True

        # set proper color space depending on texture type
        if texture_type == "nmap":
            # For TGA normal maps texture use Non-Color color space as it should be,
            # but for 16-bits PNG normal maps texture sRGB has to be used
            # otherwise Blender completely messes up normals calculation
            if texture.image.filepath.endswith(".tga"):
                texture.image.colorspace_settings.name = "Non-Color"
            else:
                texture.image.colorspace_settings.name = "sRGB"
        else:
            texture.image.colorspace_settings.name = "sRGB"

        # set usage of normal map if texture type is correct
        texture.use_normal_map = (texture_type == "nmap")

    if texture is None and texture_path.endswith(".tobj"):
        if report_invalid:
            lprint("", report_warnings=-1, report_errors=-1)

        lprint("W Texture can't be displayed as TOBJ file: %r is referencing non existing texture file:\n\t   %r",
               (texture_path, _path.readable_norm(abs_texture_filepath)))

        if report_invalid:
            lprint("", report_warnings=1, report_errors=1)

    return texture
Esempio n. 2
0
def get_texture(texture_path, texture_type, report_invalid=False):
    """Creates and setup Texture and Image data on active Material.

    :param texture_path: Texture path
    :type texture_path: str
    :param texture_type: Texture type keyword
    :type texture_type: str
    :param report_invalid: flag indicating if invalid texture should be reported in 3d view
    :type report_invalid: bool
    """

    # CREATE TEXTURE/IMAGE ID NAME
    teximag_id_name = _path.get_filename(texture_path, with_ext=False)

    # CREATE ABSOLUTE FILEPATH
    abs_texture_filepath = _path.get_abs_path(texture_path)

    # return None on non-existing texture file path
    if not abs_texture_filepath or not os.path.isfile(abs_texture_filepath):
        return None

    if abs_texture_filepath.endswith(".tobj"):
        abs_texture_filepath = _path.get_texture_path_from_tobj(
            abs_texture_filepath)

        # if not existing or none supported file
        if abs_texture_filepath is None or abs_texture_filepath[-4:] not in (
                ".tga", ".png", ".dds"):

            if report_invalid:
                lprint("", report_warnings=-1, report_errors=-1)

            # take care of none existing paths referenced in tobj texture names
            if abs_texture_filepath:

                lprint(
                    "W Texture can't be displayed as TOBJ file: %r is referencing non texture file:\n\t   %r",
                    (texture_path, _path.readable_norm(abs_texture_filepath)))

            else:

                lprint(
                    "W Texture can't be displayed as TOBJ file: %r is referencing non existing texture file.",
                    (texture_path, ))

            if report_invalid:
                lprint("", report_warnings=1, report_errors=1)

            return None

    texture = None
    if abs_texture_filepath and os.path.isfile(abs_texture_filepath):

        # find existing texture with this image
        if teximag_id_name in bpy.data.textures:

            # reuse existing image texture if possible
            postfix = 0
            postfixed_tex = teximag_id_name
            while postfixed_tex in bpy.data.textures:

                img_exists = bpy.data.textures[postfixed_tex].image is not None
                if img_exists and _path.repair_path(
                        bpy.data.textures[postfixed_tex].image.filepath
                ) == _path.repair_path(abs_texture_filepath):
                    texture = bpy.data.textures[postfixed_tex]
                    break

                postfix += 1
                postfixed_tex = teximag_id_name + "." + str(postfix).zfill(3)

        # if texture wasn't found create new one
        if not texture:

            texture = bpy.data.textures.new(teximag_id_name, 'IMAGE')
            image = None

            # reuse existing image if possible
            postfix = 0
            postfixed_img = teximag_id_name
            while postfixed_img in bpy.data.images:

                if _path.repair_path(
                        bpy.data.images[postfixed_img].filepath
                ) == _path.repair_path(abs_texture_filepath):
                    image = bpy.data.images[postfixed_img]
                    break

                postfix += 1
                postfixed_img = teximag_id_name + "." + str(postfix).zfill(3)

            # if image wasn't found load it
            if not image:
                image = bpy.data.images.load(abs_texture_filepath)
                image.name = teximag_id_name

                # try to get relative path to the Blender file and set it to the image
                if bpy.data.filepath != '':  # empty file path means blender file is not saved
                    try:
                        rel_path = _path.relative_path(
                            os.path.dirname(bpy.data.filepath),
                            abs_texture_filepath)
                    except ValueError:  # catch different mount paths: "path is on mount 'C:', start on mount 'E:'"
                        rel_path = None

                    if rel_path:
                        image.filepath = rel_path

            # finally link image to texture
            texture.image = image
            image.use_alpha = True

        # set proper color space depending on texture type
        if texture_type == "nmap":
            # For TGA normal maps texture use Non-Color color space as it should be,
            # but for 16-bits PNG normal maps texture sRGB has to be used
            # otherwise Blender completely messes up normals calculation
            if texture.image.filepath.endswith(".tga"):
                texture.image.colorspace_settings.name = "Non-Color"
            else:
                texture.image.colorspace_settings.name = "sRGB"
        else:
            texture.image.colorspace_settings.name = "sRGB"

        # set usage of normal map if texture type is correct
        texture.use_normal_map = (texture_type == "nmap")

    if texture is None and texture_path.endswith(".tobj"):
        if report_invalid:
            lprint("", report_warnings=-1, report_errors=-1)

        lprint(
            "W Texture can't be displayed as TOBJ file: %r is referencing non existing texture file:\n\t   %r",
            (texture_path, _path.readable_norm(abs_texture_filepath)))

        if report_invalid:
            lprint("", report_warnings=1, report_errors=1)

    return texture
Esempio n. 3
0
def get_texture_image(texture_path, texture_type, report_invalid=False):
    """Creates and returns image for given texture path and type.

    :param texture_path: Texture path
    :type texture_path: str
    :param texture_type: Texture type keyword
    :type texture_type: str
    :param report_invalid: flag indicating if invalid texture should be reported in 3d view
    :type report_invalid: bool
    :return: loaded image datablock to be used in SCS material
    :rtype: bpy.types.Image
    """

    # get reflection image texture
    if texture_path.endswith(".tobj") and texture_type == "reflection":
        return get_reflection_image(texture_path, report_invalid=report_invalid)

    # CREATE TEXTURE/IMAGE ID NAME
    teximag_id_name = _path.get_filename(texture_path, with_ext=False)

    # CREATE ABSOLUTE FILEPATH
    abs_texture_filepath = _path.get_abs_path(texture_path)

    # return None on non-existing texture file path
    if not abs_texture_filepath or not os.path.isfile(abs_texture_filepath):
        return None

    if abs_texture_filepath.endswith(".tobj"):
        abs_texture_filepath = _path.get_texture_path_from_tobj(abs_texture_filepath)

        # if not existing or none supported file
        if abs_texture_filepath is None or abs_texture_filepath[-4:] not in (".tga", ".png", ".dds"):

            if report_invalid:
                lprint("", report_warnings=-1, report_errors=-1)

            # take care of none existing paths referenced in tobj texture names
            if abs_texture_filepath:

                lprint("W Texture can't be displayed as TOBJ file: %r is referencing non texture file:\n\t   %r",
                       (texture_path, _path.readable_norm(abs_texture_filepath)))

            else:

                lprint("W Texture can't be displayed as TOBJ file: %r is referencing non existing texture file.",
                       (texture_path,))

            if report_invalid:
                lprint("", report_warnings=1, report_errors=1)

            return None

    image = None
    if abs_texture_filepath and os.path.isfile(abs_texture_filepath):

        # reuse existing image texture if possible
        postfix = 0
        postfixed_tex = teximag_id_name
        while postfixed_tex in bpy.data.images:

            img_exists = postfixed_tex in bpy.data.images
            if img_exists and _path.repair_path(bpy.data.images[postfixed_tex].filepath) == _path.repair_path(abs_texture_filepath):
                image = bpy.data.images[postfixed_tex]
                break

            postfix += 1
            postfixed_tex = teximag_id_name + "." + str(postfix).zfill(3)

        # if image wasn't found create new one
        if not image:

            image = None

            # reuse existing image if possible
            postfix = 0
            postfixed_img = teximag_id_name
            while postfixed_img in bpy.data.images:

                if _path.repair_path(bpy.data.images[postfixed_img].filepath) == _path.repair_path(abs_texture_filepath):
                    image = bpy.data.images[postfixed_img]
                    break

                postfix += 1
                postfixed_img = teximag_id_name + "." + str(postfix).zfill(3)

            # if image wasn't found load it
            if not image:
                image = bpy.data.images.load(abs_texture_filepath)
                image.name = teximag_id_name
                image.alpha_mode = 'CHANNEL_PACKED'

                # try to get relative path to the Blender file and set it to the image
                if bpy.data.filepath != '':  # empty file path means blender file is not saved
                    try:
                        rel_path = _path.relative_path(os.path.dirname(bpy.data.filepath), abs_texture_filepath)
                    except ValueError:  # catch different mount paths: "path is on mount 'C:', start on mount 'E:'"
                        rel_path = None

                    if rel_path:
                        image.filepath = rel_path

    if image is None and texture_path.endswith(".tobj"):
        if report_invalid:
            lprint("", report_warnings=-1, report_errors=-1)

        lprint("W Texture can't be displayed as TOBJ file: %r is referencing non existing texture file:\n\t   %r",
               (texture_path, _path.readable_norm(abs_texture_filepath)))

        if report_invalid:
            lprint("", report_warnings=1, report_errors=1)

    return image
Esempio n. 4
0
def get_texture(texture_path, texture_type):
    """Creates and setup Texture and Image data on active Material.

    :param texture_path: Texture path
    :type texture_path: str
    :param texture_type: Texture type keyword
    :type texture_type: str
    """
    # print(' texture_path: %s' % str(texture_path))

    # CREATE TEXTURE/IMAGE ID NAME
    teximag_id_name = _path.get_filename(texture_path, with_ext=False)

    # CREATE ABSOLUTE FILEPATH
    abs_texture_filepath = _path.get_abs_path(texture_path)

    texture = None
    if abs_texture_filepath and os.path.isfile(abs_texture_filepath):

        # find existing texture with this image
        if teximag_id_name in bpy.data.textures:

            # reuse existing image texture if possible
            postfix = 0
            postfixed_tex = teximag_id_name
            while postfixed_tex in bpy.data.textures:

                if _path.repair_path(bpy.data.textures[postfixed_tex].image.filepath) == _path.repair_path(abs_texture_filepath):
                    texture = bpy.data.textures[postfixed_tex]
                    break

                postfix += 1
                postfixed_tex = teximag_id_name + "." + str(postfix).zfill(3)

        # if texture wasn't found create new one
        if not texture:

            texture = bpy.data.textures.new(teximag_id_name, 'IMAGE')
            image = None

            # reuse existing image if possible
            postfix = 0
            postfixed_img = teximag_id_name
            while postfixed_img in bpy.data.images:

                if _path.repair_path(bpy.data.images[postfixed_img].filepath) == _path.repair_path(abs_texture_filepath):
                    image = bpy.data.images[postfixed_img]
                    break

                postfix += 1
                postfixed_img = teximag_id_name + "." + str(postfix).zfill(3)

            # if image wasn't found load it
            if not image:
                image = bpy.data.images.load(abs_texture_filepath)
                image.name = teximag_id_name

                # try to get relative path to the Blender file and set it to the image
                if bpy.data.filepath != '':  # empty file path means blender file is not saved
                    try:
                        rel_path = _path.relative_path(os.path.dirname(bpy.data.filepath), abs_texture_filepath)
                    except ValueError:  # catch different mount paths: "path is on mount 'C:', start on mount 'E:'"
                        rel_path = None

                    if rel_path:
                        image.filepath = rel_path

            # finally link image to texture
            texture.image = image
            image.use_alpha = True

        # normal map related settings
        if texture_type == "nmap":
            texture.image.colorspace_settings.name = "Raw"
            texture.use_normal_map = True
        else:
            texture.image.colorspace_settings.name = "sRGB"
            texture.use_normal_map = False

    return texture
Esempio n. 5
0
def get_reflection_image(texture_path, report_invalid=False):
    """Gets reflection image for given texture path.

    1. gets all textures names and check existance
    2. create image objects for all planes
    3. setup scene, create planes, create camera projector and assign images
    4. render & save image
    5. cleanup & scene restoring
    6. load temp image and pack it
    7. set filepath to TOBJ

    :param texture_path: Texture path
    :type texture_path: str
    :param report_invalid: flag indicating if invalid texture should be reported in 3d view
    :type report_invalid: bool
    :return: loaded image datablock to be used in SCS material
    :rtype: bpy.types.Image
    """

    # CREATE TEXTURE/IMAGE ID NAME
    teximag_id_name = _path.get_filename(texture_path, with_ext=False) + "_cubemap"

    # CREATE ABSOLUTE FILEPATH
    abs_tobj_filepath = _path.get_abs_path(texture_path)

    # return None on non-existing TOBJ
    if not abs_tobj_filepath or not os.path.isfile(abs_tobj_filepath):
        return None

    # check existance of this cubemap
    if teximag_id_name in bpy.data.images:

        if _path.get_abs_path(bpy.data.images[teximag_id_name].filepath) == abs_tobj_filepath:
            return bpy.data.images[teximag_id_name]

        bpy.data.images.remove(bpy.data.images[teximag_id_name])

    # 1. get all textures file paths and check their existance

    abs_texture_filepaths = _path.get_texture_paths_from_tobj(abs_tobj_filepath)

    # should be a cubemap with six images
    if not abs_texture_filepaths or len(abs_texture_filepaths) != 6:
        return None

    # all six images have to exist
    for abs_texture_filepath in abs_texture_filepaths:

        if abs_texture_filepath[-4:] not in (".tga", ".png", ".dds"):  # none supported file

            if report_invalid:
                lprint("", report_warnings=-1, report_errors=-1)

            lprint("W Texture can't be displayed as TOBJ file: %r is referencing non texture file:\n\t   %r",
                   (texture_path, _path.readable_norm(abs_texture_filepath)))

            if report_invalid:
                lprint("", report_warnings=1, report_errors=1)

            return None

        elif not os.path.isfile(abs_texture_filepath):  # none existing file

            if report_invalid:
                lprint("", report_warnings=-1, report_errors=-1)

            # take care of none existing paths referenced in tobj texture names
            lprint("W Texture can't be displayed as TOBJ file: %r is referencing non existing texture file:\n\t   %r",
                   (texture_path, _path.readable_norm(abs_texture_filepath)))

            if report_invalid:
                lprint("", report_warnings=1, report_errors=1)

            return None

    # 2. create image objects for all planes

    images = []
    for abs_texture_filepath in abs_texture_filepaths:
        images.append(bpy.data.images.load(abs_texture_filepath))

    # 3. setup scene, create planes, create camera projector and assign images

    old_scene = bpy.context.window.scene
    tmp_scene = bpy.data.scenes.new("cubemap")
    bpy.context.window.scene = tmp_scene

    meshes = []
    materials = []
    objects = []
    for i, plane in enumerate(("x+", "x-", "y+", "y-", "z+", "z-")):
        # mesh creation
        bm = bmesh.new(use_operators=True)

        bmesh.ops.create_grid(bm, x_segments=1, y_segments=1, size=1, calc_uvs=True)

        mesh = bpy.data.meshes.new(plane)
        bm.to_mesh(mesh)
        bm.free()

        mesh.uv_layers.new()

        meshes.append(mesh)

        # material creation
        material = bpy.data.materials.new(plane)
        material.use_nodes = True
        material.node_tree.nodes.clear()

        out_node = material.node_tree.nodes.new("ShaderNodeOutputMaterial")
        emission_node = material.node_tree.nodes.new("ShaderNodeEmission")
        tex_node = material.node_tree.nodes.new("ShaderNodeTexImage")
        tex_node.image = images[i]

        material.node_tree.links.new(emission_node.inputs['Color'], tex_node.outputs['Color'])
        material.node_tree.links.new(out_node.inputs['Surface'], emission_node.outputs['Emission'])

        mesh.materials.append(material)

        materials.append(material)

        # object creation
        obj = bpy.data.objects.new(mesh.name, mesh)
        obj.location = (0,) * 3
        obj.rotation_euler = (0,) * 3
        if plane == "x+":
            obj.rotation_euler.x = pi * 0.5
            obj.location.y = 1
        elif plane == "x-":
            obj.rotation_euler.x = pi * 0.5
            obj.rotation_euler.z = pi
            obj.location.y = -1
        elif plane == "y+":
            obj.rotation_euler.x = pi
            obj.rotation_euler.z = pi * 0.5
            obj.location.z = 1
        elif plane == "y-":
            obj.rotation_euler.z = pi * 0.5
            obj.location.z = -1
        elif plane == "z+":
            obj.rotation_euler.x = pi * 0.5
            obj.rotation_euler.z = pi * 0.5
            obj.location.x = -1
        elif plane == "z-":
            obj.rotation_euler.x = pi * 0.5
            obj.rotation_euler.z = -pi * 0.5
            obj.location.x = 1

        tmp_scene.collection.objects.link(obj)
        objects.append(obj)

    # camera creation
    camera = bpy.data.cameras.new("projector")
    camera.type = "PANO"
    camera.lens = 5
    camera.sensor_width = 32
    camera.cycles.panorama_type = "EQUIRECTANGULAR"
    camera.cycles.latitude_min = -pi * 0.5
    camera.cycles.latitude_max = pi * 0.5
    camera.cycles.longitude_min = pi
    camera.cycles.longitude_max = -pi

    cam_obj = bpy.data.objects.new(camera.name, camera)
    cam_obj.location = (0,) * 3
    cam_obj.rotation_euler = (pi * 0.5, 0, 0)

    tmp_scene.collection.objects.link(cam_obj)

    # 4. render & save image

    final_image_path = os.path.join(tempfile.gettempdir(), teximag_id_name + ".tga")

    tmp_scene.render.engine = "CYCLES"
    tmp_scene.cycles.samples = 1
    tmp_scene.camera = cam_obj
    tmp_scene.render.image_settings.file_format = "TARGA"
    tmp_scene.render.image_settings.color_mode = "RGBA"
    tmp_scene.render.resolution_percentage = 100
    tmp_scene.render.resolution_x = images[0].size[0] * 4
    tmp_scene.render.resolution_y = images[0].size[1] * 2
    tmp_scene.render.filepath = final_image_path
    bpy.ops.render.render(write_still=True, scene=tmp_scene.name)

    # 5. cleanup & scene restoring

    for obj in objects:
        bpy.data.objects.remove(obj)

    for mesh in meshes:
        bpy.data.meshes.remove(mesh)

    for material in materials:
        bpy.data.materials.remove(material)

    for image in images:
        bpy.data.images.remove(image)

    bpy.data.objects.remove(cam_obj)
    bpy.data.cameras.remove(camera)

    bpy.context.window.scene = old_scene
    bpy.data.scenes.remove(tmp_scene)

    # 6. load temp image and pack it

    final_image = bpy.data.images.load(final_image_path)
    final_image.name = teximag_id_name
    final_image.alpha_mode = 'CHANNEL_PACKED'
    final_image.pack()

    # 7. set filepath to original image
    final_image.filepath = abs_tobj_filepath

    return final_image