diff --git a/io_scene_fbx/cycles_shader_compat.py b/io_scene_fbx/cycles_shader_compat.py
index 2f1b9fb2653a082ce185800b0c1116936f2862fe..7fb06467114553ca698b37cd20f05a90747d220e 100644
--- a/io_scene_fbx/cycles_shader_compat.py
+++ b/io_scene_fbx/cycles_shader_compat.py
@@ -52,6 +52,7 @@ class CyclesShaderWrapper():
         "node_mix_color_bump",
 
         "node_normalmap",
+        "node_texcoords",
         
         "node_image_alpha",
         "node_image_diff",
@@ -276,6 +277,15 @@ class CyclesShaderWrapper():
         links.new(self.node_mix_color_bump.outputs["Color"],
                   self.node_out.inputs["Displacement"])
 
+        # --------------------------------------------------------------------
+        # Tex Coords
+        node = nodes.new(type='ShaderNodeTexCoord')
+        node.label = "Texture Coords"
+        node.location = self._grid_location(-3, 3)
+        self.node_texcoords = node
+        del node
+        # no links, only use when needed!
+
     @staticmethod
     def _image_create_helper(image, node_dst, sockets_dst, use_alpha=False):
         tree = node_dst.id_data
@@ -291,6 +301,41 @@ class CyclesShaderWrapper():
                       socket)
         return node
 
+    @staticmethod
+    def _mapping_create_helper(node_dst, socket_src,
+                               translation, rotation, scale):
+        tree = node_dst.id_data
+        nodes = tree.nodes
+        links = tree.links
+        
+        # in most cases:
+        # (socket_src == self.node_texcoords.outputs['UV'])
+
+        node_map = nodes.new(type='ShaderNodeMapping')
+        node_map.location = node_dst.location
+        node_map.location.x -= CyclesShaderWrapper._col_size
+
+        node_map.width = 160.0
+
+        if translation is not None:
+            node_map.translation = translation
+        if scale is not None:
+            node_map.scale = scale
+        if rotation is not None:
+            node_map.rotation = rotation
+
+        # link mapping -> image node
+        links.new(node_map.outputs["Vector"],
+                  node_dst.inputs["Vector"])
+
+        # link coord -> mapping
+        links.new(socket_src,
+                  node_map.inputs["Vector"])
+        return node_map
+
+    # note, all ***_mapping_set() functions currenly work the same way
+    # (only with different image arg), could generalize.
+
     @staticmethod
     def _grid_location(x, y):
         return (x * CyclesShaderWrapper._col_size,
@@ -301,8 +346,13 @@ class CyclesShaderWrapper():
 
     def diffuse_image_set(self, image):
         node = self.node_mix_color_diff
-        (self.node_image_diff =
-         self._image_create_helper(image, node, (node.inputs["Color2"],)))
+        self.node_image_diff = (
+            self._image_create_helper(image, node, (node.inputs["Color2"],)))
+
+    def diffuse_mapping_set(self, coords='UV',
+                            translation=None, rotation=None, scale=None):
+        return self._mapping_create_helper(
+            self.node_image_diff, self.node_texcoords.outputs[coords], translation, rotation, scale)
 
     def specular_color_set(self, color):
         self.node_bsdf_spec.mute = max(color) <= 0.0
@@ -310,8 +360,13 @@ class CyclesShaderWrapper():
 
     def specular_image_set(self, image):
         node = self.node_mix_color_spec
-        (self.node_image_spec =
-         self._image_create_helper(image, node, (node.inputs["Color2"],)))
+        self.node_image_spec = (
+            self._image_create_helper(image, node, (node.inputs["Color2"],)))
+
+    def specular_mapping_set(self, coords='UV',
+                             translation=None, rotation=None, scale=None):
+        return self._mapping_create_helper(
+            self.node_image_spec, self.node_texcoords.outputs[coords], translation, rotation, scale)
 
     def hardness_value_set(self, value):
         node = self.node_mix_color_hard
@@ -319,8 +374,13 @@ class CyclesShaderWrapper():
 
     def hardness_image_set(self, image):
         node = self.node_mix_color_hard
-        (self.node_image_hard =
-         self._image_create_helper(image, node, (node.inputs["Color2"],)))
+        self.node_image_hard = (
+            self._image_create_helper(image, node, (node.inputs["Color2"],)))
+
+    def hardness_mapping_set(self, coords='UV',
+                             translation=None, rotation=None, scale=None):
+        return self._mapping_create_helper(
+            self.node_image_hard, self.node_texcoords.outputs[coords], translation, rotation, scale)
 
     def reflect_color_set(self, color):
         node = self.node_mix_color_refl
@@ -335,8 +395,13 @@ class CyclesShaderWrapper():
     def reflect_image_set(self, image):
         self.node_bsdf_refl.mute = False
         node = self.node_mix_color_refl
-        (self.node_image_refl =
-         self._image_create_helper(image, node, (node.inputs["Color2"],)))
+        self.node_image_refl = (
+            self._image_create_helper(image, node, (node.inputs["Color2"],)))
+
+    def reflect_mapping_set(self, coords='UV',
+                            translation=None, rotation=None, scale=None):
+        return self._mapping_create_helper(
+            self.node_image_refl, self.node_texcoords.outputs[coords], translation, rotation, scale)
 
     def alpha_value_set(self, value):
         self.node_bsdf_alpha.mute &= (value >= 1.0)
@@ -349,8 +414,13 @@ class CyclesShaderWrapper():
         # note: use_alpha may need to be configurable
         # its not always the case that alpha channels use the image alpha
         # a greyscale image may also be used.
-        (self.node_image_alpha =
-         self._image_create_helper(image, node, (node.inputs["Color2"],), use_alpha=True))
+        self.node_image_alpha = (
+            self._image_create_helper(image, node, (node.inputs["Color2"],), use_alpha=True))
+
+    def alpha_mapping_set(self, coords='UV',
+                          translation=None, rotation=None, scale=None):
+        return self._mapping_create_helper(
+            self.node_image_alpha, self.node_texcoords.outputs[coords], translation, rotation, scale)
 
     def alpha_image_set_from_diffuse(self):
         # XXX, remove?
@@ -358,10 +428,14 @@ class CyclesShaderWrapper():
         links = tree.links
 
         self.node_bsdf_alpha.mute = False
-        node_image = self.node_mix_color_diff.inputs["Color2"].links[0].from_node
+        node_image = self.node_image_diff
         node = self.node_mix_color_alpha
-        links.new(node_image.outputs["Alpha"],
-                  node.inputs["Color2"])
+        if 1:
+            links.new(node_image.outputs["Alpha"],
+                      node.inputs["Color2"])
+        else:
+            self.alpha_image_set(node_image.image)
+            self.node_image_alpha.label = "Image Texture_ALPHA"
 
     def normal_factor_set(self, value):
         node = self.node_normalmap
@@ -370,10 +444,15 @@ class CyclesShaderWrapper():
     def normal_image_set(self, image):
         self.node_normalmap.mute = False
         node = self.node_normalmap
-        (self.node_image_normalmap =
-         self._image_create_helper(image, node, (node.inputs["Color"],)))
+        self.node_image_normalmap = (
+            self._image_create_helper(image, node, (node.inputs["Color"],)))
         self.node_image_normalmap.color_space = 'NONE'
 
+    def normal_mapping_set(self, coords='UV',
+                           translation=None, rotation=None, scale=None):
+        return self._mapping_create_helper(
+            self.node_image_normalmap, self.node_texcoords.outputs[coords], translation, rotation, scale)
+
     def bump_factor_set(self, value):
         node = self.node_mix_color_bump
         node.mute = (value <= 0.0)
@@ -381,5 +460,10 @@ class CyclesShaderWrapper():
 
     def bump_image_set(self, image):
         node = self.node_mix_color_bump
-        (self.node_image_bump =
-         self._image_create_helper(image, node, (node.inputs["Color2"],)))
+        self.node_image_bump = (
+            self._image_create_helper(image, node, (node.inputs["Color2"],)))
+
+    def bump_mapping_set(self, coords='UV',
+                         translation=None, rotation=None, scale=None):
+        return self._mapping_create_helper(
+            self.node_image_bump, self.node_texcoords.outputs[coords], translation, rotation, scale)
diff --git a/io_scene_fbx/import_fbx.py b/io_scene_fbx/import_fbx.py
index 29f7acee086938c3348b61fc17c84165fd0cdfd1..b386e47a9451a2a55348e37560e505176e7ccbf1 100644
--- a/io_scene_fbx/import_fbx.py
+++ b/io_scene_fbx/import_fbx.py
@@ -708,6 +708,7 @@ def blen_read_material(fbx_tmpl, fbx_obj,
         ma_wrap = cycles_shader_compat.CyclesShaderWrapper(ma)
         ma_wrap.diffuse_color_set(ma_diff)
         ma_wrap.specular_color_set([c * ma_spec_intensity for c in ma_spec])
+        ma_wrap.hardness_value_set(((ma_spec_hardness + 3.0) / 5.0) - 0.65)
         ma_wrap.alpha_value_set(ma_alpha)
         ma_wrap.reflect_factor_set(ma_refl_factor)
         ma_wrap.reflect_color_set(ma_refl_color)
@@ -1134,10 +1135,23 @@ def load(operator, context, filepath="",
 
         # textures that use this material
         def texture_bumpfac_get(fbx_obj):
+            assert(fbx_obj.id == b'Material')
             fbx_props = (elem_find_first(fbx_obj, b'Properties70'),
                          elem_find_first(fbx_tmpl, b'Properties70', fbx_elem_nil))
             assert(fbx_props[0] is not None)
-            return elem_props_get_number(fbx_props, b'BumpFactor', 1.0)
+            # (x / 7.142) is only a guess, cycles usable range is (0.0 -> 0.5)
+            return elem_props_get_number(fbx_props, b'BumpFactor', 2.5) / 7.142
+
+        def texture_mapping_get(fbx_obj):
+            assert(fbx_obj.id == b'Texture')
+
+            fbx_props = (elem_find_first(fbx_obj, b'Properties70'),
+                         elem_find_first(fbx_tmpl, b'Properties70', fbx_elem_nil))
+            assert(fbx_props[0] is not None)
+            return (elem_props_get_vector_3d(fbx_props, b'Translation', (0.0, 0.0, 0.0)),
+                    elem_props_get_vector_3d(fbx_props, b'Rotation', (0.0, 0.0, 0.0)),
+                    elem_props_get_vector_3d(fbx_props, b'Scaling', (1.0, 1.0, 1.0)),
+                    )
 
         if not use_cycles:
             # Simple function to make a new mtex and set defaults
@@ -1170,26 +1184,57 @@ def load(operator, context, filepath="",
 
                         ma_wrap = cycles_material_wrap_map[material]
 
+                        # tx/rot/scale
+                        tex_map = texture_mapping_get(fbx_lnk)
+                        if (tex_map[0] == (0.0, 0.0, 0.0) and
+                            tex_map[1] == (0.0, 0.0, 0.0) and
+                            tex_map[2] == (1.0, 1.0, 1.0)):
+
+                            use_mapping = False
+                        else:
+                            use_mapping = True
+                            tex_map_kw = {
+                                "translation": tex_map[0],
+                                "rotation": tex_map[1],
+                                "scale": tex_map[2],
+                                }
+
                         if lnk_type == b'DiffuseColor':
                             ma_wrap.diffuse_image_set(image)
+                            if use_mapping:
+                                ma_wrap.diffuse_mapping_set(**tex_map_kw)
                         elif lnk_type == b'SpecularColor':
                             ma_wrap.specular_image_set(image)
+                            if use_mapping:
+                                ma_wrap.specular_mapping_set(**tex_map_kw)
                         elif lnk_type == b'ReflectionColor':
                             ma_wrap.reflect_image_set(image)
+                            if use_mapping:
+                                ma_wrap.reflect_mapping_set(**tex_map_kw)
                         elif lnk_type == b'TransparentColor':  # alpha
                             ma_wrap.alpha_image_set(image)
+                            if use_mapping:
+                                ma_wrap.alpha_mapping_set(**tex_map_kw)
                             if use_alpha_decals:
                                 material_decals.add(material)
                         elif lnk_type == b'DiffuseFactor':
                             pass  # TODO
                         elif lnk_type == b'ShininessExponent':
                             ma_wrap.hardness_image_set(image)
-                        elif lnk_type == b'NormalMap':
+                            if use_mapping:
+                                ma_wrap.hardness_mapping_set(**tex_map_kw)
+                        elif lnk_type == b'NormalMap' or lnk_type == b'Bump':  # XXX, applications abuse bump!
                             ma_wrap.normal_image_set(image)
                             ma_wrap.normal_factor_set(texture_bumpfac_get(fbx_obj))
+                            if use_mapping:
+                                ma_wrap.normal_mapping_set(**tex_map_kw)
+                            """
                         elif lnk_type == b'Bump':
                             ma_wrap.bump_image_set(image)
                             ma_wrap.bump_factor_set(texture_bumpfac_get(fbx_obj))
+                            if use_mapping:
+                                ma_wrap.bump_mapping_set(**tex_map_kw)
+                            """
                         else:
                             print("WARNING: material link %r ignored" % lnk_type)
 
@@ -1220,13 +1265,15 @@ def load(operator, context, filepath="",
                             mtex.use_map_diffuse = True
                         elif lnk_type == b'ShininessExponent':
                             mtex.use_map_hardness = True
-                        elif lnk_type == b'NormalMap':
+                        elif lnk_type == b'NormalMap' or lnk_type == b'Bump':  # XXX, applications abuse bump!
                             mtex.texture.use_normal_map = True  # not ideal!
                             mtex.use_map_normal = True
                             mtex.normal_factor = texture_bumpfac_get(fbx_obj)
+                            """
                         elif lnk_type == b'Bump':
                             mtex.use_map_normal = True
                             mtex.normal_factor = texture_bumpfac_get(fbx_obj)
+                            """
                         else:
                             print("WARNING: material link %r ignored" % lnk_type)