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.image_utils import load_image
from bpy_extras.wm_utils.progress_report import ProgressReport
def line_value(line_split):
Returns 1 string representing the value for this line
None will be returned if there's only 1 word
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(context_imagepath_map, line, DIR, recursive, relpath):
But we try all space-separated items from current line when file is not found with last one
(users keep generating/using image files with spaces in a format that does not support them, sigh...)
Also tries to replace '_' with ' ' for Max's exporter replaces spaces with underscores.
filepath_parts = line.split(b' ')
image = None
for i in range(-1, -len(filepath_parts), -1):
imagepath = os.fsdecode(b" ".join(filepath_parts[i:]))
image = context_imagepath_map.get(imagepath, ...)
if image is ...:
image = load_image(imagepath, DIR, recursive=recursive, relpath=relpath)
if image is None and "_" in imagepath:
image = load_image(imagepath.replace("_", " "), DIR, recursive=recursive, relpath=relpath)
if image is not None:
context_imagepath_map[imagepath] = image
break;
if image is None:
imagepath = os.fsdecode(filepath_parts[-1])
image = load_image(imagepath, DIR, recursive=recursive, place_holder=True, relpath=relpath)
context_imagepath_map[imagepath] = image
return image
Campbell Barton
committed
def create_materials(filepath, relpath,
material_libs, unique_materials,
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
committed
context_material_vars = set()
# Don't load the same image multiple times
context_imagepath_map = {}
nodal_material_wrap_map = {}
def load_material_image(blender_material, mat_wrap, context_material_name, img_data, line, type):
"""
Set textures defined in .mtl file.
"""
map_options = {}
curr_token = []
for token in img_data[:-1]:
if token.startswith(b'-') and token[1:].isalpha():
if curr_token:
map_options[curr_token[0]] = curr_token[1:]
curr_token[:] = []
curr_token.append(token)
Bastien Montagne
committed
if curr_token:
map_options[curr_token[0]] = curr_token[1:]
# Absolute path - c:\.. etc would work here
image = obj_image_load(context_imagepath_map, line, DIR, use_image_search, relpath)
map_offset = map_options.get(b'-o')
map_scale = map_options.get(b'-s')
def _generic_tex_set(nodetex, image, texcoords, translation, scale):
nodetex.image = image
nodetex.texcoords = texcoords
if translation is not None:
nodetex.translation = translation
if scale is not None:
nodetex.scale = scale
# Adds textures for materials (rendering)
if type == 'Kd':
_generic_tex_set(mat_wrap.base_color_texture, image, 'UV', map_offset, map_scale)
elif type == 'Ka':
# XXX Not supported?
print("WARNING, currently unsupported ambient texture, skipped.")
elif type == 'Ks':
_generic_tex_set(mat_wrap.specular_texture, image, 'UV', map_offset, map_scale)
Bastien Montagne
committed
elif type == 'Ke':
# XXX Not supported?
print("WARNING, currently unsupported emit texture, skipped.")
elif type == 'Bump':
bump_mult = map_options.get(b'-bm')
Bastien Montagne
committed
bump_mult = float(bump_mult[0]) if (bump_mult and len(bump_mult[0]) > 1) else 1.0
mat_wrap.normalmap_strength_set(bump_mult)
_generic_tex_set(mat_wrap.normalmap_texture, image, 'UV', map_offset, map_scale)
elif type == 'D':
_generic_tex_set(mat_wrap.transmission_texture, image, 'UV', map_offset, map_scale)
Campbell Barton
committed
elif type == 'disp':
# XXX Not supported?
print("WARNING, currently unsupported displacement texture, skipped.")
# ~ mat_wrap.bump_image_set(image)
# ~ mat_wrap.bump_mapping_set(coords='UV', translation=map_offset, scale=map_scale)
elif type == 'refl':
map_type = map_options.get(b'-type')
if map_type and map_type != [b'sphere']:
print("WARNING, unsupported reflection type '%s', defaulting to 'sphere'"
"" % ' '.join(i.decode() for i in map_type))
_generic_tex_set(mat_wrap.base_color_texture, image, 'Reflection', map_offset, map_scale)
mat_wrap.base_color_texture.projection = 'SPHERE'
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] + ".mtl"
if os.path.exists(os.path.join(DIR, temp_mtl)):
material_libs.add(temp_mtl)
del temp_mtl
ma = unique_materials[name] = bpy.data.materials.new(name.decode('utf-8', "replace"))
from bpy_extras import node_shader_utils
ma_wrap = node_shader_utils.PrincipledBSDFWrapper(ma, is_readonly=False)
nodal_material_wrap_map[ma] = ma_wrap
for libname in sorted(material_libs):
if not os.path.exists(mtlpath):
print("\tMaterial not found MTL: %r" % mtlpath)
Loading
Loading full blame...