Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBastien Montagne <montagne29@wanadoo.fr>2017-05-27 14:05:59 +0300
committerBastien Montagne <montagne29@wanadoo.fr>2017-05-27 14:07:43 +0300
commit0ed2792d30d726cca252fac298741ee6247f3f03 (patch)
tree9cd033cd321a7730e034326346cba5ba1e9eb0e1
parentc441b2fd05e383da6b071b5efdd627c2f445ade7 (diff)
OBJ import: Add basic support for Cycles shaders.
This code uses same wrapper as FBX importer to generate a basic nodal shader for Cycles material. Note that not all MTL features are supported, some might be possible to add later though.
-rw-r--r--io_scene_obj/__init__.py1
-rw-r--r--io_scene_obj/import_obj.py150
-rw-r--r--modules/cycles_shader_compat.py7
3 files changed, 118 insertions, 40 deletions
diff --git a/io_scene_obj/__init__.py b/io_scene_obj/__init__.py
index 71587533..6d1312ec 100644
--- a/io_scene_obj/__init__.py
+++ b/io_scene_obj/__init__.py
@@ -139,6 +139,7 @@ class ImportOBJ(bpy.types.Operator, ImportHelper, IOOBJOrientationHelper):
from_up=self.axis_up,
).to_4x4()
keywords["global_matrix"] = global_matrix
+ keywords["use_cycles"] = (context.scene.render.engine == 'CYCLES')
if bpy.data.is_saved and context.user_preferences.filepaths.use_relative_paths:
import os
diff --git a/io_scene_obj/import_obj.py b/io_scene_obj/import_obj.py
index 24a3b04f..36b0106d 100644
--- a/io_scene_obj/import_obj.py
+++ b/io_scene_obj/import_obj.py
@@ -88,7 +88,7 @@ def obj_image_load(context_imagepath_map, line, DIR, recursive, relpath):
def create_materials(filepath, relpath,
material_libs, unique_materials, unique_material_images,
- use_image_search, float_func):
+ use_image_search, use_cycles, float_func):
"""
Create all the used materials in this obj,
assign colors and images to the materials from all referenced material libs
@@ -99,7 +99,9 @@ def create_materials(filepath, relpath,
# Don't load the same image multiple times
context_imagepath_map = {}
- def load_material_image(blender_material, context_material_name, img_data, line, type):
+ cycles_material_wrap_map = {}
+
+ def load_material_image(blender_material, mat_wrap, use_cycles, context_material_name, img_data, line, type):
"""
Set textures defined in .mtl file.
"""
@@ -113,16 +115,22 @@ def create_materials(filepath, relpath,
curr_token[:] = []
curr_token.append(token)
- texture = bpy.data.textures.new(name=type, type='IMAGE')
-
# Absolute path - c:\.. etc would work here
image = obj_image_load(context_imagepath_map, line, DIR, use_image_search, relpath)
+ texture = bpy.data.textures.new(name=type, type='IMAGE')
if image is not None:
texture.image = image
+ map_offset = map_options.get(b'-o')
+ map_scale = map_options.get(b'-s')
+
# Adds textures for materials (rendering)
if type == 'Kd':
+ if use_cycles:
+ mat_wrap.diffuse_image_set(image)
+ mat_wrap.diffuse_mapping_set(coords='UV', translation=map_offset, scale=map_scale)
+
mtex = blender_material.texture_slots.add()
mtex.texture = texture
mtex.texture_coords = 'UV'
@@ -133,45 +141,62 @@ def create_materials(filepath, relpath,
unique_material_images[context_material_name] = image # set the texface image
elif type == 'Ka':
+ if use_cycles:
+ # XXX Not supported?
+ print("WARNING, currently unsupported ambient texture, skipped.")
+
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':
+ if use_cycles:
+ mat_wrap.specular_image_set(image)
+ mat_wrap.specular_mapping_set(coords='UV', translation=map_offset, scale=map_scale)
+
mtex = blender_material.texture_slots.add()
mtex.use_map_color_diffuse = False
-
mtex.texture = texture
mtex.texture_coords = 'UV'
mtex.use_map_color_spec = True
elif type == 'Ke':
+ if use_cycles:
+ # XXX Not supported?
+ print("WARNING, currently unsupported emit texture, skipped.")
+
mtex = blender_material.texture_slots.add()
mtex.use_map_color_diffuse = False
-
mtex.texture = texture
mtex.texture_coords = 'UV'
mtex.use_map_emit = True
elif type == 'Bump':
+ bump_mult = map_options.get(b'-bm')
+
+ if use_cycles:
+ mat_wrap.normal_image_set(image)
+ mat_wrap.normal_mapping_set(coords='UV', translation=map_offset, scale=map_scale)
+ if bump_mult:
+ mat_wrap.normal_factor_set(bump_mult[0])
+
mtex = blender_material.texture_slots.add()
mtex.use_map_color_diffuse = False
-
mtex.texture = texture
mtex.texture_coords = 'UV'
mtex.use_map_normal = True
-
- bump_mult = map_options.get(b'-bm')
if bump_mult:
mtex.normal_factor = bump_mult[0]
elif type == 'D':
+ if use_cycles:
+ mat_wrap.alpha_image_set(image)
+ mat_wrap.alpha_mapping_set(coords='UV', translation=map_offset, scale=map_scale)
+
mtex = blender_material.texture_slots.add()
mtex.use_map_color_diffuse = False
-
mtex.texture = texture
mtex.texture_coords = 'UV'
mtex.use_map_alpha = True
@@ -179,34 +204,38 @@ def create_materials(filepath, relpath,
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
+ # Todo, unset diffuse material alpha if it has an alpha channel
elif type == 'disp':
+ if use_cycles:
+ mat_wrap.bump_image_set(image)
+ mat_wrap.bump_mapping_set(coords='UV', translation=map_offset, scale=map_scale)
+
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':
+ 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))
+
+ if use_cycles:
+ mat_wrap.diffuse_image_set(image, projection='SPHERE')
+ mat_wrap.diffuse_mapping_set(coords='Reflection', translation=map_offset, scale=map_scale)
+
mtex = blender_material.texture_slots.add()
mtex.use_map_color_diffuse = False
-
mtex.texture = texture
mtex.texture_coords = 'REFLECTION'
mtex.use_map_color_diffuse = True
-
- 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))
mtex.mapping = 'SPHERE'
else:
raise Exception("invalid type %r" % type)
- map_offset = map_options.get(b'-o')
- map_scale = map_options.get(b'-s')
if map_offset:
mtex.offset.x = float(map_offset[0])
if len(map_offset) >= 2:
@@ -230,8 +259,13 @@ def create_materials(filepath, relpath,
# Create new materials
for name in unique_materials: # .keys()
if name is not None:
- unique_materials[name] = bpy.data.materials.new(name.decode('utf-8', "replace"))
+ ma = 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.
+ if use_cycles:
+ from modules import cycles_shader_compat
+ ma_wrap = cycles_shader_compat.CyclesShaderWrapper(ma)
+ cycles_material_wrap_map[ma] = ma_wrap
+
# XXX Why was this needed? Cannot find any good reason, and adds stupid empty matslot in case we do not separate
# mesh (see T44947).
@@ -255,6 +289,7 @@ def create_materials(filepath, relpath,
# print('\t\tloading mtl: %e' % mtlpath)
context_material = None
+ context_mat_wrap = None
mtl = open(mtlpath, 'rb')
for line in mtl: # .readlines():
line = line.strip()
@@ -269,6 +304,8 @@ def create_materials(filepath, relpath,
if context_material:
emit_value = sum(emit_colors) / 3.0
if emit_value > 1e-6:
+ if use_cycles:
+ print("WARNING, currently unsupported emit value, skipped.")
# We have to adapt it to diffuse color too...
emit_value /= sum(context_material.diffuse_color) / 3.0
context_material.emit = emit_value
@@ -277,10 +314,17 @@ def create_materials(filepath, relpath,
context_material.ambient = 0.0
if do_highlight:
+ if use_cycles:
+ context_mat_wrap.hardness_value_set = 1.0
# FIXME, how else to use this?
context_material.specular_intensity = 1.0
+ else:
+ if use_cycles:
+ context_mat_wrap.hardness_value_set = 0.0
if do_reflection:
+ if use_cycles:
+ context_mat_wrap.reflect_factor_set = 1.0
context_material.raytrace_mirror.use = True
context_material.raytrace_mirror.reflect_factor = 1.0
@@ -288,13 +332,19 @@ def create_materials(filepath, relpath,
context_material.use_transparency = True
context_material.transparency_method = 'RAYTRACE' if do_raytrace else 'Z_TRANSPARENCY'
if "alpha" not in context_material_vars:
+ if use_cycles:
+ context_mat_wrap.alpha_value_set(0.0)
context_material.alpha = 0.0
if do_glass:
+ if use_cycles:
+ print("WARNING, currently unsupported glass material, skipped.")
if "ior" not in context_material_vars:
context_material.raytrace_transparency.ior = 1.5
if do_fresnel:
+ if use_cycles:
+ print("WARNING, currently unsupported fresnel option, skipped.")
context_material.raytrace_mirror.fresnel = 1.0 # could be any value for 'ON'
"""
@@ -309,6 +359,8 @@ def create_materials(filepath, relpath,
context_material_name = line_value(line_split)
context_material = unique_materials.get(context_material_name)
+ if use_cycles:
+ context_mat_wrap = cycles_material_wrap_map[context_material]
context_material_vars.clear()
emit_colors[:] = [0.0, 0.0, 0.0]
@@ -324,33 +376,48 @@ def create_materials(filepath, relpath,
elif context_material:
# we need to make a material to assign properties to it.
if line_id == b'ka':
- context_material.mirror_color = (
- float_func(line_split[1]), float_func(line_split[2]), float_func(line_split[3]))
+ col = (float_func(line_split[1]), float_func(line_split[2]), float_func(line_split[3]))
+ if use_cycles:
+ context_mat_wrap.reflect_color_set(col)
+ context_material.mirror_color = col
# This is highly approximated, but let's try to stick as close from exporter as possible... :/
context_material.ambient = sum(context_material.mirror_color) / 3
elif line_id == b'kd':
- context_material.diffuse_color = (
- float_func(line_split[1]), float_func(line_split[2]), float_func(line_split[3]))
+ col = (float_func(line_split[1]), float_func(line_split[2]), float_func(line_split[3]))
+ if use_cycles:
+ context_mat_wrap.diffuse_color_set(col)
+ context_material.diffuse_color = col
context_material.diffuse_intensity = 1.0
elif line_id == b'ks':
- context_material.specular_color = (
- float_func(line_split[1]), float_func(line_split[2]), float_func(line_split[3]))
+ col = (float_func(line_split[1]), float_func(line_split[2]), float_func(line_split[3]))
+ if use_cycles:
+ context_mat_wrap.specular_color_set(col)
+ context_mat_wrap.hardness_value_set(1.0)
+ context_material.specular_color = col
context_material.specular_intensity = 1.0
elif line_id == b'ke':
# We cannot set context_material.emit right now, we need final diffuse color as well for this.
emit_colors[:] = [
float_func(line_split[1]), float_func(line_split[2]), float_func(line_split[3])]
elif line_id == b'ns':
+ if use_cycles:
+ context_mat_wrap.hardness_value_set(((float_func(line_split[1]) + 3.0) / 50.0) - 0.65)
context_material.specular_hardness = int((float_func(line_split[1]) * 0.51) + 1)
elif line_id == b'ni': # Refraction index (between 1 and 3).
+ if use_cycles:
+ print("WARNING, currently unsupported glass material, skipped.")
context_material.raytrace_transparency.ior = max(1, min(float_func(line_split[1]), 3))
context_material_vars.add("ior")
elif line_id == b'd': # dissolve (transparency)
+ if use_cycles:
+ context_mat_wrap.alpha_value_set(float_func(line_split[1]))
context_material.alpha = float_func(line_split[1])
context_material.use_transparency = True
context_material.transparency_method = 'Z_TRANSPARENCY'
context_material_vars.add("alpha")
elif line_id == b'tr': # translucency
+ if use_cycles:
+ print("WARNING, currently unsupported translucency option, skipped.")
context_material.translucency = float_func(line_split[1])
elif line_id == b'tf':
# rgb, filter color, blender has no support for this.
@@ -415,37 +482,45 @@ def create_materials(filepath, relpath,
elif line_id == b'map_ka':
img_data = line.split()[1:]
if img_data:
- load_material_image(context_material, context_material_name, img_data, line, 'Ka')
+ load_material_image(context_material, context_mat_wrap, use_cycles,
+ context_material_name, img_data, line, 'Ka')
elif line_id == b'map_ks':
img_data = line.split()[1:]
if img_data:
- load_material_image(context_material, context_material_name, img_data, line, 'Ks')
+ load_material_image(context_material, context_mat_wrap, use_cycles,
+ context_material_name, img_data, line, 'Ks')
elif line_id == b'map_kd':
img_data = line.split()[1:]
if img_data:
- load_material_image(context_material, context_material_name, img_data, line, 'Kd')
+ load_material_image(context_material, context_mat_wrap, use_cycles,
+ context_material_name, img_data, line, 'Kd')
elif line_id == b'map_ke':
img_data = line.split()[1:]
if img_data:
- load_material_image(context_material, context_material_name, img_data, line, 'Ke')
+ load_material_image(context_material, context_mat_wrap, use_cycles,
+ context_material_name, img_data, line, 'Ke')
elif line_id in {b'map_bump', b'bump'}: # 'bump' is incorrect but some files use it.
img_data = line.split()[1:]
if img_data:
- load_material_image(context_material, context_material_name, img_data, line, 'Bump')
+ load_material_image(context_material, context_mat_wrap, use_cycles,
+ context_material_name, img_data, line, 'Bump')
elif line_id in {b'map_d', b'map_tr'}: # Alpha map - Dissolve
img_data = line.split()[1:]
if img_data:
- load_material_image(context_material, context_material_name, img_data, line, 'D')
+ load_material_image(context_material, context_mat_wrap, use_cycles,
+ context_material_name, img_data, line, 'D')
elif line_id in {b'map_disp', b'disp'}: # displacementmap
img_data = line.split()[1:]
if img_data:
- load_material_image(context_material, context_material_name, img_data, line, 'disp')
+ load_material_image(context_material, context_mat_wrap, use_cycles,
+ context_material_name, img_data, line, 'disp')
elif line_id in {b'map_refl', b'refl'}: # reflectionmap
img_data = line.split()[1:]
if img_data:
- load_material_image(context_material, context_material_name, img_data, line, 'refl')
+ load_material_image(context_material, context_mat_wrap, use_cycles,
+ context_material_name, img_data, line, 'refl')
else:
print("\t%r:%r (ignored)" % (filepath, line))
mtl.close()
@@ -889,6 +964,7 @@ def load(context,
use_split_groups=True,
use_image_search=True,
use_groups_as_vgroups=False,
+ use_cycles=True,
relpath=None,
global_matrix=None
):
@@ -1179,7 +1255,7 @@ def load(context,
progress.step("Done, loading materials and images...")
create_materials(filepath, relpath, material_libs, unique_materials,
- unique_material_images, use_image_search, float_func)
+ unique_material_images, use_image_search, use_cycles, float_func)
progress.step("Done, building geometries (verts:%i faces:%i materials: %i smoothgroups:%i) ..." %
(len(verts_loc), len(faces), len(unique_materials), len(unique_smooth_groups)))
diff --git a/modules/cycles_shader_compat.py b/modules/cycles_shader_compat.py
index e0adbea7..8a967f46 100644
--- a/modules/cycles_shader_compat.py
+++ b/modules/cycles_shader_compat.py
@@ -287,13 +287,14 @@ class CyclesShaderWrapper():
# no links, only use when needed!
@staticmethod
- def _image_create_helper(image, node_dst, sockets_dst, use_alpha=False):
+ def _image_create_helper(image, node_dst, sockets_dst, use_alpha=False, projection='FLAT'):
tree = node_dst.id_data
nodes = tree.nodes
links = tree.links
node = nodes.new(type='ShaderNodeTexImage')
node.image = image
+ node.projection = projection
node.location = node_dst.location
node.location.x -= CyclesShaderWrapper._col_size
for socket in sockets_dst:
@@ -365,10 +366,10 @@ class CyclesShaderWrapper():
def diffuse_color_set(self, color):
self.node_mix_color_diff.inputs["Color1"].default_value[0:3] = color
- def diffuse_image_set(self, image):
+ def diffuse_image_set(self, image, projection='FLAT'):
node = self.node_mix_color_diff
self.node_image_diff = (
- self._image_create_helper(image, node, (node.inputs["Color2"],)))
+ self._image_create_helper(image, node, (node.inputs["Color2"],), projection=projection))
def diffuse_mapping_set(self, coords='UV',
translation=None, rotation=None, scale=None, clamp=None):