Skip to content
Snippets Groups Projects
import_obj.py 44 KiB
Newer Older
# ##### BEGIN GPL LICENSE BLOCK #####
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU General Public License
#  as published by the Free Software Foundation; either version 2
#  of the License, or (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software Foundation,
#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####

# <pep8 compliant>

# Script copyright (C) Campbell Barton
# Contributors: Campbell Barton, Jiri Hnidek, Paolo Ciccone

"""
This script imports a Wavefront OBJ files to Blender.

Usage:
Run this script from "File->Import" menu and then load the desired OBJ file.
Note, This loads mesh objects and materials only, nurbs and curves are not supported.

http://wiki.blender.org/index.php/Scripts/Manual/Import/wavefront_obj
"""

import os
import time
import bpy
import mathutils
from bpy_extras.io_utils import unpack_list
from bpy_extras.image_utils import load_image
    Returns 1 string representing the value for this line
    None will be returned if theres only 1 word
Campbell Barton's avatar
Campbell Barton committed
    length = len(line_split)
    if length == 1:
        return None

    elif length == 2:
        return line_split[1]

    elif length > 2:
        return b' '.join(line_split[1:])
def obj_image_load(imagepath, DIR, recursive, relpath):
    Mainly uses comprehensiveImageLoad
    but tries to replace '_' with ' ' for Max's exporter replaces spaces with underscores.
    if b'_' in imagepath:
        image = load_image(imagepath.replace(b'_', b' '), DIR, recursive=recursive, relpath=relpath)
    return load_image(imagepath, DIR, recursive=recursive, place_holder=True, relpath=relpath)
def create_materials(filepath, relpath,
                     material_libs, unique_materials, unique_material_images,
                     use_image_search, float_func):
    Create all the used materials in this obj,
    assign colors and images to the materials from all referenced material libs
Campbell Barton's avatar
Campbell Barton committed
    DIR = os.path.dirname(filepath)

    def load_material_image(blender_material, context_material_name, imagepath, type):
        """
        Set textures defined in .mtl file.
        """
Campbell Barton's avatar
Campbell Barton committed
        texture = bpy.data.textures.new(name=type, type='IMAGE')

        # Absolute path - c:\.. etc would work here
        image = obj_image_load(imagepath, DIR, use_image_search, relpath)
        if image is not None:
            texture.image = image

        # Adds textures for materials (rendering)
        if type == 'Kd':
            mtex = blender_material.texture_slots.add()
            mtex.texture = texture
            mtex.texture_coords = 'UV'
            mtex.use_map_color_diffuse = True

            # adds textures to faces (Textured/Alt-Z mode)
            # Only apply the diffuse texture to the face if the image has not been set with the inline usemat func.
            unique_material_images[context_material_name] = image  # set the texface image

        elif type == 'Ka':
            mtex = blender_material.texture_slots.add()
            mtex.use_map_color_diffuse = False

            mtex.texture = texture
            mtex.texture_coords = 'UV'
            mtex.use_map_ambient = True

        elif type == 'Ks':
            mtex = blender_material.texture_slots.add()
            mtex.use_map_color_diffuse = False

            mtex.texture = texture
            mtex.texture_coords = 'UV'
            mtex.use_map_specular = True

        elif type == 'Bump':
            mtex = blender_material.texture_slots.add()
            mtex.use_map_color_diffuse = False

            mtex.texture = texture
            mtex.texture_coords = 'UV'
            mtex.use_map_normal = True

        elif type == 'D':
            mtex = blender_material.texture_slots.add()
            mtex.use_map_color_diffuse = False

            mtex.texture = texture
            mtex.texture_coords = 'UV'
            mtex.use_map_alpha = True
            blender_material.use_transparency = True
            blender_material.transparency_method = 'Z_TRANSPARENCY'
            if "alpha" not in context_material_vars:
                blender_material.alpha = 0.0
            # Todo, unset deffuse material alpha if it has an alpha channel

        elif type == 'disp':
            mtex = blender_material.texture_slots.add()
            mtex.use_map_color_diffuse = False

            mtex.texture = texture
            mtex.texture_coords = 'UV'
            mtex.use_map_displacement = True

        elif type == 'refl':
            mtex = blender_material.texture_slots.add()
            mtex.use_map_color_diffuse = False

            mtex.texture_coords = 'REFLECTION'
            mtex.use_map_color_diffuse = True
            raise Exception("invalid type %r" % type)

    # Add an MTL with the same name as the obj if no MTLs are spesified.
    temp_mtl = os.path.splitext((os.path.basename(filepath)))[0] + b'.mtl'

    if os.path.exists(os.path.join(DIR, temp_mtl)) and temp_mtl not in material_libs:
Campbell Barton's avatar
Campbell Barton committed
        material_libs.append(temp_mtl)
    # Create new materials
Campbell Barton's avatar
Campbell Barton committed
    for name in unique_materials:  # .keys()
Campbell Barton's avatar
Campbell Barton committed
        if name is not None:
            unique_materials[name] = bpy.data.materials.new(name.decode('utf-8', "replace"))
            unique_material_images[name] = None  # assign None to all material images to start with, add to later.
Campbell Barton's avatar
Campbell Barton committed
    unique_materials[None] = None
    unique_material_images[None] = None
Campbell Barton's avatar
Campbell Barton committed
        mtlpath = os.path.join(DIR, libname)
            print("\tMaterial not found MTL: %r" % mtlpath)
            # print('\t\tloading mtl: %e' % mtlpath)
Campbell Barton's avatar
Campbell Barton committed
            context_material = None
            mtl = open(mtlpath, 'rb')
Campbell Barton's avatar
Campbell Barton committed
            for line in mtl:  # .readlines():
                line = line.strip()
                if not line or line.startswith(b'#'):
                    continue

                line_split = line.split()
                line_id = line_split[0].lower()

                if line_id == b'newmtl':
                    context_material_name = line_value(line_split)
Campbell Barton's avatar
Campbell Barton committed
                    context_material = unique_materials.get(context_material_name)

                elif context_material:
                    # we need to make a material to assign properties to it.
Loading
Loading full blame...