diff --git a/io_import_scene_lwo.py b/io_import_scene_lwo.py
new file mode 100644
index 0000000000000000000000000000000000000000..4fae120aeb32163c43f4a20748970d7398c2a86c
--- /dev/null
+++ b/io_import_scene_lwo.py
@@ -0,0 +1,1134 @@
+# ##### 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>
+
+# Copyright (c) Ken Nign 2010
+# ken@virginpi.com
+#
+# Version 1.0 - Sep 1, 2010
+#
+# Loads a LightWave .lwo object file, including the vertex maps such as
+# UV, Morph, Color and Weight maps.
+#
+# Will optionally create an Armature from an embedded Skelegon rig.
+#
+# Point orders are maintained so that .mdds can exchanged with other
+# 3D programs.
+#
+#
+# Notes:
+# NGons, polygons with more than 4 points are supported, but are
+# added (as triangles) after the vertex maps have been applied. Thus they
+# won't contain all the vertex data that the original ngon had.
+# 
+# Blender is limited to only 8 UV Texture and 8 Vertex Color maps,
+# thus only the first 8 of each can be imported.
+
+
+bl_addon_info= {
+    "name": "Import LightWave Objects",
+    "author": "Ken Nign (Ken9)",
+    "version": (1,0),
+    "blender": (2, 5, 3),
+    "api": 31744,
+    "location": "File > Import > LightWave Object (.lwo)",
+    "description": "Imports a LWO file including any UV, Morph and Color maps. Can convert Skelegons to an Armature.",
+    "warning": "",
+    "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
+        "Scripts/File_I-O/LightWave_Object",
+    "tracker_url": "",
+    "category": "Import/Export"}
+
+
+import os
+import io
+import time
+import struct
+import chunk
+
+import bpy
+import mathutils
+from geometry import PolyFill
+
+
+class _obj_layer():
+    def __init__(self):
+        self.name= ""
+        self.index= -1
+        self.parent_index= -1
+        self.pivot= [0,0,0]
+        self.pols= []
+        self.bones= []
+        self.bone_names= {}
+        self.bone_rolls= {}
+        self.pnts= []
+        self.wmaps= {}
+        self.colmaps= {}
+        self.uvmaps= {}
+        self.morphs= {}
+        self.surf_tags= {}
+        self.has_subds= False
+
+
+class _obj_surf():
+    def __init__(self):
+        self.bl_mat= None
+        self.name= "Default"
+        self.source_name= ""
+        self.colr= [1.0, 1.0, 1.0]
+        self.diff= 1.0   # Diffuse
+        self.lumi= 0.0   # Luminosity
+        self.spec= 0.0   # Specular
+        self.refl= 0.0   # Reflectivity
+        self.rblr= 0.0   # Reflection Bluring
+        self.tran= 0.0   # Transparency (the opposite of Blender's Alpha value)
+        self.rind= 1.0   # RT Transparency IOR
+        self.tblr= 0.0   # Refraction Bluring
+        self.trnl= 0.0   # Translucency
+        self.glos= 0.4   # Glossiness
+        self.shrp= 0.0   # Diffuse Sharpness
+        self.smooth= False  # Surface Smoothing
+        
+
+def load_lwo(filename,
+             context,
+             ADD_SUBD_MOD= True,
+             LOAD_HIDDEN= False,
+             SKEL_TO_ARM= True):
+    '''Read the LWO file, hand off to version specific function.'''
+    name, ext= os.path.splitext(os.path.basename(filename))
+    file= open(filename, 'rb')
+    
+    try:
+        header, chunk_size, chunk_name = struct.unpack(">4s1L4s", file.read(12))
+    except:
+        print("Error parsing file header!")
+        file.close()
+        return
+    
+    layers= []
+    surfs= {}
+    tags= []
+    # Gather the object data using the version specific handler.
+    if chunk_name == b'LWO2':
+        read_lwo2(file, filename, layers, surfs, tags, ADD_SUBD_MOD, LOAD_HIDDEN, SKEL_TO_ARM)
+    elif chunk_name == b'LWOB' or chunk_name == b'LWLO':    # LWLO is a layered object.
+        read_lwob(file, filename, layers, surfs, tags, ADD_SUBD_MOD)
+    else:
+        print("Not a supported file type!")
+        file.close()
+        return
+    
+    file.close()
+    
+    # With the data gathered, build the object(s).
+    build_objects(layers, surfs, tags, name, ADD_SUBD_MOD, SKEL_TO_ARM)
+    
+    layers= None
+    surfs.clear()
+    tags= None
+
+
+def read_lwo2(file, filename, layers, surfs, tags, add_subd_mod, load_hidden, skel_to_arm):
+    '''Read version 2 file, LW 6+.'''
+    handle_layer= True
+    last_pols_count= 0
+    just_read_bones= False
+    print("Importing LWO: " + filename + "\nLWO v2 Format")
+    
+    while True:
+        try:
+            rootchunk = chunk.Chunk(file)
+        except EOFError:
+            break
+        
+        if rootchunk.chunkname == b'TAGS':
+            read_tags(rootchunk.read(), tags)
+        elif rootchunk.chunkname == b'LAYR':
+            handle_layer= read_layr(rootchunk.read(), layers, load_hidden)
+        elif rootchunk.chunkname == b'PNTS' and handle_layer:
+            read_pnts(rootchunk.read(), layers)
+        elif rootchunk.chunkname == b'VMAP' and handle_layer:
+            vmap_type = rootchunk.read(4)
+            
+            if vmap_type == b'WGHT':
+                read_weightmap(rootchunk.read(), layers)
+            elif vmap_type == b'MORF':
+                read_morph(rootchunk.read(), layers)
+            elif vmap_type == b'TXUV':
+                read_uvmap(rootchunk.read(), layers)
+            elif vmap_type == b'RGB ' or vmap_type == b'RGBA':
+                read_colmap(rootchunk.read(), layers)
+            else:
+                rootchunk.skip()
+                
+        elif rootchunk.chunkname == b'VMAD' and handle_layer:
+            vmad_type= rootchunk.read(4)
+            
+            if vmad_type == b'TXUV':
+                read_uv_vmad(rootchunk.read(), layers, last_pols_count)
+            elif vmad_type == b'RGB ' or vmad_type == b'RGBA':
+                read_color_vmad(rootchunk.read(), layers, last_pols_count)
+            else:
+                rootchunk.skip()
+                
+        elif rootchunk.chunkname == b'POLS' and handle_layer:
+            face_type = rootchunk.read(4)
+            just_read_bones= False
+            # PTCH is LW's Subpatches, SUBD is CatmullClark.
+            if (face_type == b'FACE' or face_type == b'PTCH' or face_type == b'SUBD') and handle_layer:
+                last_pols_count= read_pols(rootchunk.read(), layers)
+                if face_type != b'FACE':
+                    layers[-1].has_subds= True
+            elif face_type == b'BONE' and handle_layer:
+                read_bones(rootchunk.read(), layers)
+                just_read_bones= True
+            else:
+                rootchunk.skip()
+                
+        elif rootchunk.chunkname == b'PTAG' and handle_layer:
+            tag_type,= struct.unpack("4s", rootchunk.read(4));
+            if tag_type == b'SURF' and not just_read_bones:
+                # We have to ignore the surface data if we just read a bones chunk.
+                read_surf_tags(rootchunk.read(), layers, last_pols_count)
+                
+            elif skel_to_arm:
+                if tag_type == b'BNUP':
+                    read_bone_tags(rootchunk.read(), layers, tags, 'BNUP')
+                elif tag_type == b'BONE':
+                    read_bone_tags(rootchunk.read(), layers, tags, 'BONE')
+                else:
+                    rootchunk.skip()
+            else:
+                rootchunk.skip()
+        elif rootchunk.chunkname == b'SURF':
+            read_surf(rootchunk.read(), surfs)
+        else:
+            #if handle_layer:
+                #print("Skipping Chunk: " + str(rootchunk.chunkname))
+            rootchunk.skip()
+
+
+def read_lwob(file, filename, layers, surfs, tags, add_subd_mod):
+    '''Read version 1 file, LW < 6.'''
+    last_pols_count= 0
+    print("Importing LWO: " + filename + "\nLWO v1 Format")
+    
+    while True:
+        try:
+            rootchunk = chunk.Chunk(file)
+        except EOFError:
+            break
+        
+        if rootchunk.chunkname == b'SRFS':
+            read_tags(rootchunk.read(), tags)
+        elif rootchunk.chunkname == b'LAYR':
+            read_layr_5(rootchunk.read(), layers)
+        elif rootchunk.chunkname == b'PNTS':
+            if len(layers) == 0:    # LWOB files have no LAYR chunk to set this up
+                nlayer= _obj_layer()
+                nlayer.name= "Layer 1"
+                layers.append(nlayer)
+            read_pnts(rootchunk.read(), layers)
+        elif rootchunk.chunkname == b'POLS':
+            last_pols_count= read_pols_5(rootchunk.read(), layers)
+        elif rootchunk.chunkname == b'PCHS':
+            last_pols_count= read_pols_5(rootchunk.read(), layers)
+            layers[-1].has_subds= True
+        elif rootchunk.chunkname == b'PTAG':
+            tag_type,= struct.unpack("4s", rootchunk.read(4));
+            if tag_type == b'SURF':
+                read_surf_tags_5(rootchunk.read(), layers, last_pols_count)
+            else:
+                rootchunk.skip()
+        elif rootchunk.chunkname == b'SURF':
+            read_surf_5(rootchunk.read(), surfs)
+        else:
+            # For Debugging \/.
+            #if handle_layer:
+                #print("Skipping Chunk: " + str(rootchunk.chunkname))
+            rootchunk.skip()
+
+
+def read_lwostring(raw_name):
+    '''Parse a zero-padded string.'''
+
+    i = raw_name.find(b'\0')
+    name_len = i + 1
+    if name_len % 2 == 1:   # Test for oddness.
+        name_len += 1
+        
+    if i > 0:
+        # Some plugins put non-text strings in the tags chunk.
+        name = raw_name[0:i].decode("utf-8", "ignore")
+    else:
+        name = ""
+
+    return name, name_len
+
+    
+def read_vx(pointdata):
+    '''Read a variable-length index.'''
+    if pointdata[0] != 255:
+        index= pointdata[0]*256 + pointdata[1]
+        size= 2
+    else:
+        index= pointdata[1]*65536 + pointdata[2]*256 + pointdata[3]
+        size= 4
+    
+    return index, size
+
+    
+def read_tags(tag_bytes, object_tags):
+    '''Read the object's Tags chunk.'''
+    offset= 0
+    chunk_len= len(tag_bytes)
+
+    while offset < chunk_len:
+        tag, tag_len= read_lwostring(tag_bytes[offset:])
+        offset+= tag_len
+        object_tags.append(tag)
+
+
+def read_layr(layr_bytes, object_layers, load_hidden):
+    '''Read the object's layer data.'''
+    new_layr= _obj_layer()
+    new_layr.index, flags= struct.unpack(">HH", layr_bytes[0:4])
+    
+    if flags > 0 and not load_hidden:
+        return False
+    
+    print("Reading Object Layer")
+    offset= 4
+    new_layr.pivot= struct.unpack(">fff", layr_bytes[offset:offset+12])
+    offset+= 12
+    layr_name, name_len = read_lwostring(layr_bytes[offset:])
+    offset+= name_len
+    
+    if layr_name:
+        new_layr.name= layr_name
+    else:
+        new_layr.name= "Layer " + str(new_layr.index + 1)
+        
+    if len(layr_bytes) == offset+2:
+        new_layr.parent_index,= struct.unpack(">h", layr_bytes[offset:offset+2])
+    
+    object_layers.append(new_layr)
+    return True
+
+
+def read_layr_5(layr_bytes, object_layers):
+    '''Read the object's layer data.'''
+    # XXX: Need to check what these two exactly mean for a LWOB/LWLO file.
+    new_layr= _obj_layer()
+    new_layr.index, flags= struct.unpack(">HH", layr_bytes[0:4])
+    
+    print("Reading Object Layer")
+    offset= 4
+    layr_name, name_len = read_lwostring(layr_bytes[offset:])
+    offset+= name_len
+    
+    if name_len > 2 and layr_name != 'noname':
+        new_layr.name= layr_name
+    else:
+        new_layr.name= "Layer " + str(new_layr.index)
+        
+    object_layers.append(new_layr)
+    
+
+def read_pnts(pnt_bytes, object_layers):
+    '''Read the layer's points.'''
+    print("\tReading Layer ("+object_layers[-1].name+") Points")
+    offset= 0
+    chunk_len= len(pnt_bytes)
+    
+    while offset < chunk_len:
+        pnts= struct.unpack(">fff", pnt_bytes[offset:offset+12])
+        offset+= 12
+        # Re-order the points so that the mesh has the right pitch.
+        pnts= [pnts[0] - object_layers[-1].pivot[0],\
+               pnts[2] - object_layers[-1].pivot[2],\
+               pnts[1] - object_layers[-1].pivot[1]]
+        object_layers[-1].pnts.append(pnts)
+
+
+def read_weightmap(weight_bytes, object_layers):
+    '''Read a weight map's values.'''
+    chunk_len= len(weight_bytes)
+    offset= 2
+    name, name_len= read_lwostring(weight_bytes[offset:])
+    offset+= name_len
+    weights= []
+    
+    while offset < chunk_len:
+        pnt_id, pnt_id_len= read_vx(weight_bytes[offset:offset+4])
+        offset+= pnt_id_len
+        value,= struct.unpack(">f", weight_bytes[offset:offset+4])
+        offset+= 4
+        weights.append([pnt_id, value])
+    
+    object_layers[-1].wmaps[name]= weights
+
+
+def read_morph(morph_bytes, object_layers):
+    '''Read an endomorph's displacement values.'''
+    chunk_len= len(morph_bytes)
+    offset= 2
+    name, name_len= read_lwostring(morph_bytes[offset:])
+    offset+= name_len
+    deltas= []
+    
+    while offset < chunk_len:
+        pnt_id, pnt_id_len= read_vx(morph_bytes[offset:offset+4])
+        offset+= pnt_id_len
+        pos= struct.unpack(">fff", morph_bytes[offset:offset+12]) 
+        offset+= 12
+        deltas.append([pnt_id, pos[0], pos[1], pos[2]])
+    
+    object_layers[-1].morphs[name]= deltas
+    
+
+def read_colmap(col_bytes, object_layers):
+    '''Read the RGB or RGBA color map.'''
+    chunk_len= len(col_bytes)
+    dia,= struct.unpack(">H", col_bytes[0:2])
+    offset= 2
+    name, name_len= read_lwostring(col_bytes[offset:])
+    offset+= name_len
+    colors= {}
+    
+    if dia == 3:
+        while offset < chunk_len:
+            pnt_id, pnt_id_len= read_vx(col_bytes[offset:offset+4])
+            offset+= pnt_id_len
+            col= struct.unpack(">fff", col_bytes[offset:offset+12]) 
+            offset+= 12
+            colors[pnt_id]= (col[0], col[1], col[2])
+    elif dia == 4:
+        while offset < chunk_len:
+            pnt_id, pnt_id_len= read_vx(col_bytes[offset:offset+4])
+            offset+= pnt_id_len
+            col= struct.unpack(">ffff", col_bytes[offset:offset+16]) 
+            offset+= 16
+            colors[pnt_id]= (col[0], col[1], col[2])
+    
+    if name in object_layers[-1].colmaps:
+        if "PointMap" in object_layers[-1].colmaps[name]:
+            object_layers[-1].colmaps[name]["PointMap"].update(colors)
+        else:
+            object_layers[-1].colmaps[name]["PointMap"]= colors
+    else:
+        object_layers[-1].colmaps[name]= dict(PointMap= colors)
+
+
+def read_color_vmad(col_bytes, object_layers, last_pols_count):
+    '''Read the Discontinous (per-polygon) RGB values.'''
+    chunk_len= len(col_bytes)
+    dia,= struct.unpack(">H", col_bytes[0:2])
+    offset= 2
+    name, name_len= read_lwostring(col_bytes[offset:])
+    offset+= name_len
+    colors= {}
+    abs_pid= len(object_layers[-1].pols) - last_pols_count
+    
+    if dia == 3:
+        while offset < chunk_len:
+            pnt_id, pnt_id_len= read_vx(col_bytes[offset:offset+4])
+            offset+= pnt_id_len
+            pol_id, pol_id_len= read_vx(col_bytes[offset:offset+4])
+            offset+= pol_id_len
+            
+            # The PolyID in a VMAD can be relative, this offsets it.
+            pol_id+= abs_pid
+            col= struct.unpack(">fff", col_bytes[offset:offset+12]) 
+            offset+= 12
+            if pol_id in colors:
+                colors[pol_id][pnt_id]= (col[0], col[1], col[2])
+            else:
+                colors[pol_id]= dict({pnt_id: (col[0], col[1], col[2])})
+    elif dia == 4:
+        while offset < chunk_len:
+            pnt_id, pnt_id_len= read_vx(col_bytes[offset:offset+4])
+            offset+= pnt_id_len
+            pol_id, pol_id_len= read_vx(col_bytes[offset:offset+4])
+            offset+= pol_id_len
+            
+            pol_id+= abs_pid
+            col= struct.unpack(">ffff", col_bytes[offset:offset+16]) 
+            offset+= 16
+            if pol_id in colors:
+                colors[pol_id][pnt_id]= (col[0], col[1], col[2])
+            else:
+                colors[pol_id]= dict({pnt_id: (col[0], col[1], col[2])})
+        
+    if name in object_layers[-1].colmaps:
+        if "FaceMap" in object_layers[-1].colmaps[name]:
+            object_layers[-1].colmaps[name]["FaceMap"].update(colors)
+        else:
+            object_layers[-1].colmaps[name]["FaceMap"]= colors
+    else:
+        object_layers[-1].colmaps[name]= dict(FaceMap= colors)
+        
+
+def read_uvmap(uv_bytes, object_layers):
+    '''Read the simple UV coord values.'''
+    chunk_len= len(uv_bytes)
+    offset= 2
+    name, name_len= read_lwostring(uv_bytes[offset:])
+    offset+= name_len
+    uv_coords= {}
+    
+    while offset < chunk_len:
+        pnt_id, pnt_id_len= read_vx(uv_bytes[offset:offset+4])
+        offset+= pnt_id_len
+        pos= struct.unpack(">ff", uv_bytes[offset:offset+8]) 
+        offset+= 8
+        uv_coords[pnt_id]= (pos[0], pos[1])
+    
+    if name in object_layers[-1].uvmaps:
+        if "PointMap" in object_layers[-1].uvmaps[name]:
+            object_layers[-1].uvmaps[name]["PointMap"].update(uv_coords)
+        else:
+            object_layers[-1].uvmaps[name]["PointMap"]= uv_coords
+    else:
+        object_layers[-1].uvmaps[name]= dict(PointMap= uv_coords)
+
+
+def read_uv_vmad(uv_bytes, object_layers, last_pols_count):
+    '''Read the Discontinous (per-polygon) uv values.'''
+    chunk_len= len(uv_bytes)
+    offset= 2
+    name, name_len= read_lwostring(uv_bytes[offset:])
+    offset+= name_len
+    uv_coords= {}
+    abs_pid= len(object_layers[-1].pols) - last_pols_count
+    
+    while offset < chunk_len:
+        pnt_id, pnt_id_len= read_vx(uv_bytes[offset:offset+4])
+        offset+= pnt_id_len
+        pol_id, pol_id_len= read_vx(uv_bytes[offset:offset+4])
+        offset+= pol_id_len
+        
+        pol_id+= abs_pid
+        pos= struct.unpack(">ff", uv_bytes[offset:offset+8]) 
+        offset+= 8
+        if pol_id in uv_coords:
+            uv_coords[pol_id][pnt_id]= (pos[0], pos[1])
+        else:
+            uv_coords[pol_id]= dict({pnt_id: (pos[0], pos[1])})
+            
+    if name in object_layers[-1].uvmaps:
+        if "FaceMap" in object_layers[-1].uvmaps[name]:
+            object_layers[-1].uvmaps[name]["FaceMap"].update(uv_coords)
+        else:
+            object_layers[-1].uvmaps[name]["FaceMap"]= uv_coords
+    else:
+        object_layers[-1].uvmaps[name]= dict(FaceMap= uv_coords)
+
+
+def read_pols(pol_bytes, object_layers):
+    '''Read the layer's polygons, each one is just a list of point indexes.'''
+    print("\tReading Layer ("+object_layers[-1].name+") Polygons")
+    offset= 0
+    pols_count = len(pol_bytes)
+    old_pols_count= len(object_layers[-1].pols)
+    
+    while offset < pols_count:
+        pnts_count,= struct.unpack(">H", pol_bytes[offset:offset+2])
+        offset+= 2
+        all_face_pnts= []
+        for j in range(pnts_count):
+            face_pnt, data_size= read_vx(pol_bytes[offset:offset+4])
+            offset+= data_size
+            all_face_pnts.append(face_pnt)
+            
+        object_layers[-1].pols.append(all_face_pnts)
+    
+    return len(object_layers[-1].pols) - old_pols_count
+
+
+def read_pols_5(pol_bytes, object_layers):
+    '''
+    Read the polygons, each one is just a list of point indexes.
+    But it also includes the surface index.
+    '''
+    print("\tReading Layer ("+object_layers[-1].name+") Polygons")
+    offset= 0
+    chunk_len= len(pol_bytes)
+    old_pols_count= len(object_layers[-1].pols)
+    poly= 0
+    
+    while offset < chunk_len:
+        pnts_count,= struct.unpack(">H", pol_bytes[offset:offset+2])
+        offset+= 2
+        all_face_pnts= []
+        for j in range(pnts_count):
+            face_pnt,= struct.unpack(">H", pol_bytes[offset:offset+2])
+            offset+= 2
+            all_face_pnts.append(face_pnt)
+            
+        object_layers[-1].pols.append(all_face_pnts)
+        sid,= struct.unpack(">h", pol_bytes[offset:offset+2])
+        offset+= 2
+        sid= abs(sid) - 1
+        if sid not in object_layers[-1].surf_tags:
+            object_layers[-1].surf_tags[sid]= []
+        object_layers[-1].surf_tags[sid].append(poly)
+        poly+= 1
+    
+    return len(object_layers[-1].pols) - old_pols_count
+
+
+def read_bones(bone_bytes, object_layers):
+    '''Read the layer's skelegons.'''
+    print("\tReading Layer ("+object_layers[-1].name+") Bones")
+    offset= 0
+    bones_count = len(bone_bytes)
+    
+    while offset < bones_count:
+        pnts_count,= struct.unpack(">H", bone_bytes[offset:offset+2])
+        offset+= 2
+        all_bone_pnts= []
+        for j in range(pnts_count):
+            bone_pnt, data_size= read_vx(bone_bytes[offset:offset+4])
+            offset+= data_size
+            all_bone_pnts.append(bone_pnt)
+            
+        object_layers[-1].bones.append(all_bone_pnts)
+    
+    
+def read_bone_tags(tag_bytes, object_layers, object_tags, type):
+    '''Read the bone name or roll tags.'''
+    offset= 0
+    chunk_len= len(tag_bytes)
+    
+    if type == 'BONE':
+        bone_dict= object_layers[-1].bone_names
+    elif type == 'BNUP':
+        bone_dict= object_layers[-1].bone_rolls
+    else:
+        return
+    
+    while offset < chunk_len:
+        pid, pid_len= read_vx(tag_bytes[offset:offset+4])
+        offset+= pid_len
+        tid,= struct.unpack(">H", tag_bytes[offset:offset+2])
+        offset+= 2
+        bone_dict[pid]= object_tags[tid]
+            
+    
+def read_surf_tags(tag_bytes, object_layers, last_pols_count):
+    '''Read the list of PolyIDs and tag indexes.'''
+    print("\tReading Layer ("+object_layers[-1].name+") Surface Assignments")
+    offset= 0
+    chunk_len= len(tag_bytes)
+    
+    # Read in the PolyID/Surface Index pairs.
+    abs_pid= len(object_layers[-1].pols) - last_pols_count
+    while offset < chunk_len:
+        pid, pid_len= read_vx(tag_bytes[offset:offset+4])
+        offset+= pid_len
+        sid,= struct.unpack(">H", tag_bytes[offset:offset+2])
+        offset+=2
+        if sid not in object_layers[-1].surf_tags:
+            object_layers[-1].surf_tags[sid]= []
+        object_layers[-1].surf_tags[sid].append(pid + abs_pid)
+    
+
+def read_surf(surf_bytes, object_surfs):
+    '''Read the object's surface data.'''
+    if len(object_surfs) == 0:
+        print("Reading Object Surfaces")
+    
+    surf= _obj_surf()
+    name, name_len= read_lwostring(surf_bytes)
+    if len(name) != 0:
+        surf.name = name
+    
+    # We have to read this, but we won't use it...yet.
+    s_name, s_name_len= read_lwostring(surf_bytes[name_len:])
+    offset= name_len+s_name_len
+    block_size= len(surf_bytes)
+    while offset < block_size:
+        subchunk_name,= struct.unpack("4s", surf_bytes[offset:offset+4])
+        offset+= 4
+        subchunk_len,= struct.unpack(">H", surf_bytes[offset:offset+2])
+        offset+= 2
+        
+        # Now test which subchunk it is.
+        if subchunk_name == b'COLR':
+            surf.colr= struct.unpack(">fff", surf_bytes[offset:offset+12])
+            # Don't bother with any envelopes for now.
+            
+        elif subchunk_name == b'DIFF':
+            surf.diff,= struct.unpack(">f", surf_bytes[offset:offset+4])
+
+        elif subchunk_name == b'LUMI':
+            surf.lumi,= struct.unpack(">f", surf_bytes[offset:offset+4])
+            
+        elif subchunk_name == b'SPEC':
+            surf.spec,= struct.unpack(">f", surf_bytes[offset:offset+4])
+            
+        elif subchunk_name == b'REFL':
+            surf.refl,= struct.unpack(">f", surf_bytes[offset:offset+4])
+            
+        elif subchunk_name == b'RBLR':
+            surf.rblr,= struct.unpack(">f", surf_bytes[offset:offset+4])
+
+        elif subchunk_name == b'TRAN':
+            surf.tran,= struct.unpack(">f", surf_bytes[offset:offset+4])
+            
+        elif subchunk_name == b'RIND':
+            surf.rind,= struct.unpack(">f", surf_bytes[offset:offset+4])
+            
+        elif subchunk_name == b'TBLR':
+            surf.tblr,= struct.unpack(">f", surf_bytes[offset:offset+4])
+            
+        elif subchunk_name == b'TRNL':
+            surf.trnl,= struct.unpack(">f", surf_bytes[offset:offset+4])
+            
+        elif subchunk_name == b'GLOS':
+            surf.glos,= struct.unpack(">f", surf_bytes[offset:offset+4])
+            
+        elif subchunk_name == b'SHRP':
+            surf.shrp,= struct.unpack(">f", surf_bytes[offset:offset+4])
+        
+        elif subchunk_name == b'SMAN':
+            s_angle,= struct.unpack(">f", surf_bytes[offset:offset+4])
+            if s_angle > 0.0:
+                surf.smooth = True
+        
+        offset+= subchunk_len
+        
+    object_surfs[surf.name]= surf
+    
+    
+def read_surf_5(surf_bytes, object_surfs):
+    '''Read the object's surface data.'''
+    if len(object_surfs) == 0:
+        print("Reading Object Surfaces")
+        
+    surf= _obj_surf()
+    name, name_len= read_lwostring(surf_bytes)
+    if len(name) != 0:
+        surf.name = name
+    
+    offset= name_len
+    chunk_len= len(surf_bytes)
+    while offset < chunk_len:
+        subchunk_name,= struct.unpack("4s", surf_bytes[offset:offset+4])
+        offset+= 4
+        subchunk_len,= struct.unpack(">H", surf_bytes[offset:offset+2])
+        offset+= 2
+        
+        # Now test which subchunk it is.
+        if subchunk_name == b'COLR':
+            color= struct.unpack(">BBBB", surf_bytes[offset:offset+4])
+            surf.colr= [color[0] / 255.0, color[1] / 255.0, color[2] / 255.0]
+            
+        elif subchunk_name == b'DIFF':
+            surf.diff,= struct.unpack(">h", surf_bytes[offset:offset+2])
+            surf.diff/= 256.0    # Yes, 256 not 255.
+
+        elif subchunk_name == b'LUMI':
+            surf.lumi,= struct.unpack(">h", surf_bytes[offset:offset+2])
+            surf.lumi/= 256.0
+            
+        elif subchunk_name == b'SPEC':
+            surf.spec,= struct.unpack(">h", surf_bytes[offset:offset+2])
+            surf.spec/= 256.0
+            
+        elif subchunk_name == b'REFL':
+            surf.refl,= struct.unpack(">h", surf_bytes[offset:offset+2])
+            surf.refl/= 256.0
+
+        elif subchunk_name == b'TRAN':
+            surf.tran,= struct.unpack(">h", surf_bytes[offset:offset+2])
+            surf.tran/= 256.0
+            
+        elif subchunk_name == b'RIND':
+            surf.rind,= struct.unpack(">f", surf_bytes[offset:offset+4])
+            
+        elif subchunk_name == b'GLOS':
+            surf.glos,= struct.unpack(">h", surf_bytes[offset:offset+2])
+            
+        elif subchunk_name == b'SMAN':
+            s_angle,= struct.unpack(">f", surf_bytes[offset:offset+4])
+            if s_angle > 0.0:
+                surf.smooth = True
+        
+        offset+= subchunk_len
+        
+    object_surfs[surf.name]= surf
+
+
+def create_mappack(data, map_name, map_type):
+    '''Match the map data to faces.'''
+    pack= {}
+    
+    def color_pointmap(map):
+        for fi in range(len(data.pols)):
+            if fi not in pack:
+                pack[fi]= []
+            for pnt in data.pols[fi]:
+                if pnt in map:
+                    pack[fi].append(map[pnt])
+                else:
+                    pack[fi].append((1.0, 1.0, 1.0))
+        
+    def color_facemap(map):
+        for fi in range(len(data.pols)):
+            if fi not in pack:
+                pack[fi]= []
+                for p in data.pols[fi]:
+                    pack[fi].append((1.0, 1.0, 1.0))
+            if fi in map:
+                for po in range(len(data.pols[fi])):
+                    if data.pols[fi][po] in map[fi]:
+                        pack[fi].insert(po, map[fi][data.pols[fi][po]])
+                        del pack[fi][po+1]
+                        
+    def uv_pointmap(map):
+        for fi in range(len(data.pols)):
+            if fi not in pack:
+                pack[fi]= []
+                for p in data.pols[fi]:
+                    pack[fi].append((-0.1,-0.1))
+            for po in range(len(data.pols[fi])):
+                pnt_id= data.pols[fi][po]
+                if pnt_id in map:
+                    pack[fi].insert(po, map[pnt_id])
+                    del pack[fi][po+1]
+                    
+    def uv_facemap(map):
+        for fi in range(len(data.pols)):
+            if fi not in pack:
+                pack[fi]= []
+                for p in data.pols[fi]:
+                    pack[fi].append((-0.1,-0.1))
+            if fi in map:
+                for po in range(len(data.pols[fi])):
+                    pnt_id= data.pols[fi][po]
+                    if pnt_id in map[fi]:
+                        pack[fi].insert(po, map[fi][pnt_id])
+                        del pack[fi][po+1]
+                    
+    if map_type == "COLOR":
+        # Look at the first map, is it a point or face map
+        if "PointMap" in data.colmaps[map_name]:
+            color_pointmap(data.colmaps[map_name]["PointMap"])
+            
+        if "FaceMap" in data.colmaps[map_name]:
+            color_facemap(data.colmaps[map_name]["FaceMap"])
+    elif map_type == "UV":
+        if "PointMap" in data.uvmaps[map_name]:
+            uv_pointmap(data.uvmaps[map_name]["PointMap"])
+            
+        if "FaceMap" in data.uvmaps[map_name]:
+            uv_facemap(data.uvmaps[map_name]["FaceMap"])
+
+    return pack
+    
+    
+def build_armature(layer_data, bones):
+    '''Build an armature from the skelegon data in the mesh.'''
+    print("Building Armature")
+
+    # New Armatures include a default bone, remove it.
+    bones.remove(bones[0])
+    
+    # Now start adding the bones at the point locations.
+    prev_bone= None
+    for skb_idx in range(len(layer_data.bones)):
+        if skb_idx in layer_data.bone_names:
+            nb= bones.new(layer_data.bone_names[skb_idx])
+        else:
+            nb= bones.new("Bone")
+        
+        nb.head= layer_data.pnts[layer_data.bones[skb_idx][0]]
+        nb.tail= layer_data.pnts[layer_data.bones[skb_idx][1]]
+        
+        if skb_idx in layer_data.bone_rolls:
+            xyz= layer_data.bone_rolls[skb_idx].split(' ')
+            vec= mathutils.Vector()
+            vec.x= float(xyz[0])
+            vec.y= float(xyz[1])
+            vec.z= float(xyz[2])
+            quat= vec.to_track_quat('Y', 'Z')
+            nb.roll= quat.to_euler('XYZ')[2] * -1
+            # XXX: This code may need a second look and test.
+        else:
+            nb.roll= 0.0
+        
+        if prev_bone != None:
+            if nb.head == prev_bone.tail:
+                nb.parent= prev_bone
+                
+        nb.use_connect= True
+        prev_bone= nb
+    
+    
+def build_objects(object_layers, object_surfs, object_tags, object_name, add_subd_mod, skel_to_arm):
+    '''Using the gathered data, create the objects.'''
+    ob_dict= {} # Used for the parenting setup.
+    print("Adding "+str(len(object_surfs))+" Materials")
+
+    for surf_key in object_surfs:
+        surf_data= object_surfs[surf_key]
+        surf_data.bl_mat= bpy.data.materials.new(surf_data.name)
+        surf_data.bl_mat.diffuse_color= (surf_data.colr[:])
+        surf_data.bl_mat.diffuse_intensity= surf_data.diff
+        surf_data.bl_mat.emit= surf_data.lumi
+        surf_data.bl_mat.specular_intensity= surf_data.spec
+        if surf_data.refl != 0.0:
+            surf_data.bl_mat.raytrace_mirror.use= True
+        surf_data.bl_mat.raytrace_mirror.reflect_factor= surf_data.refl
+        surf_data.bl_mat.raytrace_mirror.gloss_factor= 1.0-surf_data.rblr
+        if surf_data.tran != 0.0:
+            surf_data.bl_mat.use_transparency= True
+            surf_data.bl_mat.transparency_method= 'RAYTRACE'
+        surf_data.bl_mat.alpha= 1.0 - surf_data.tran
+        surf_data.bl_mat.raytrace_transparency.ior= surf_data.rind
+        surf_data.bl_mat.raytrace_transparency.gloss_factor= 1.0 - surf_data.tblr
+        surf_data.bl_mat.translucency= surf_data.trnl
+        surf_data.bl_mat.specular_hardness= int(4*((10*surf_data.glos)*(10*surf_data.glos)))
+        # XXX: The gloss converion needs another look
+    
+    # Single layer objects use the object file's name instead.
+    if len(object_layers) and object_layers[-1].name == 'Layer 1':
+        object_layers[-1].name= object_name
+        print("Building "+object_name+" Object")
+    else:
+        print("Building "+str(len(object_layers))+" Objects")
+    
+    for layer_data in object_layers:
+        me= bpy.data.meshes.new(layer_data.name)        
+        me.vertices.add(len(layer_data.pnts))
+        me.faces.add(len(layer_data.pols))
+        
+        for vi in range(len(layer_data.pnts)):
+            me.vertices[vi].co= layer_data.pnts[vi]
+        
+        ngons= {}   # To keep the FaceIdx consistant, handle NGons later.
+        has_edges= False
+        for fi in range(len(layer_data.pols)):
+            layer_data.pols[fi].reverse()   # Reversing gives correct normal directions
+            # PointID 0 in the last element causes Blender to think it's un-used.
+            if layer_data.pols[fi][-1] == 0:
+                layer_data.pols[fi].insert(0, layer_data.pols[fi][-1])
+                del layer_data.pols[fi][-1]
+            
+            vlen= len(layer_data.pols[fi])
+            if vlen == 3 or vlen == 4:
+                for i in range(vlen):
+                    me.faces[fi].vertices_raw[i]= layer_data.pols[fi][i]
+            elif vlen == 2:
+                has_edges= True
+                # This IS an odd way to create edges, but using edges.add() was causing
+                # crashes if there were faces and edges being created in the same layer.
+                opp= layer_data.pols[fi]
+                me.faces[fi].vertices= [opp[0], opp[1], opp[0]]
+            elif vlen != 1:
+                ngons[fi]= layer_data.pols[fi]  # Deal with them later
+        
+        ob= bpy.data.objects.new(layer_data.name, me)
+        bpy.context.scene.objects.link(ob)
+        ob_dict[layer_data.index]= [ob, layer_data.parent_index]
+        
+        # Move the object so the pivot is in the right place.
+        ob.location= [layer_data.pivot[0], layer_data.pivot[2], layer_data.pivot[1]]
+    
+        # Create the Material Slots and assign the MatIndex to the correct faces.
+        mat_slot= 0
+        for surf_key in layer_data.surf_tags:
+            if object_tags[surf_key] in object_surfs:
+                me.materials.append(object_surfs[object_tags[surf_key]].bl_mat)
+                
+                for fi in layer_data.surf_tags[surf_key]:
+                    me.faces[fi].material_index= mat_slot
+                    me.faces[fi].use_smooth= object_surfs[object_tags[surf_key]].smooth
+                    
+                mat_slot+=1
+        
+        # Create the Vertex Groups (LW's Weight Maps).
+        if len(layer_data.wmaps) > 0:
+            print("Adding "+str(len(layer_data.wmaps))+" Vertex Groups")
+            for wmap_key in layer_data.wmaps:
+                vgroup= ob.vertex_groups.new()
+                vgroup.name= wmap_key
+                wlist= layer_data.wmaps[wmap_key]
+                for pvp in wlist:
+                    ob.vertex_groups.assign([pvp[0]], vgroup, pvp[1], 'REPLACE')
+        
+        # Create the Shape Keys (LW's Endomorphs).
+        if len(layer_data.morphs) > 0:
+            print("Adding "+str(len(layer_data.morphs))+" Shapes Keys")
+            ob.add_shape_key('Basis')   # Got to have a Base Shape.
+            for morph_key in layer_data.morphs:
+                skey= ob.add_shape_key(morph_key)
+                dlist= layer_data.morphs[morph_key]
+                for pdp in dlist:
+                    me.shape_keys.keys[skey.name].data[pdp[0]].co= [layer_data.pnts[pdp[0]][0]+pdp[1], layer_data.pnts[pdp[0]][1]+pdp[3], layer_data.pnts[pdp[0]][2]+pdp[2]]
+        
+        # Create the Vertex Color maps.
+        if len(layer_data.colmaps) > 0:
+            print("Adding "+str(len(layer_data.colmaps))+" Vertex Color Maps")
+            for cmap_key in layer_data.colmaps:
+                map_pack= create_mappack(layer_data, cmap_key, "COLOR")
+                vcol= me.vertex_colors.new(cmap_key)
+                if not vcol:
+                    break
+                for fi in map_pack:
+                    if fi > len(vcol.data):
+                        continue
+                    face= map_pack[fi]
+                    colf= vcol.data[fi]
+                    
+                    if len(face) > 2:
+                        colf.color1= face[0]
+                        colf.color2= face[1]
+                        colf.color3= face[2]
+                    if len(face) == 4:
+                        colf.color4= face[3]
+                        
+        # Create the UV Maps.
+        if len(layer_data.uvmaps) > 0:
+            print("Adding "+str(len(layer_data.uvmaps))+" UV Textures")
+            for uvmap_key in layer_data.uvmaps:
+                map_pack= create_mappack(layer_data, uvmap_key, "UV")
+                uvm= me.uv_textures.new(uvmap_key)
+                if not uvm:
+                    break
+                for fi in map_pack:
+                    if fi > len(uvm.data):
+                        continue
+                    face= map_pack[fi]
+                    uvf= uvm.data[fi]
+                    
+                    if len(face) > 2:
+                        uvf.uv1= face[0]
+                        uvf.uv2= face[1]
+                        uvf.uv3= face[2]
+                    if len(face) == 4:
+                        uvf.uv4= face[3]
+
+        # Now add the NGons.
+        if len(ngons) > 0:
+            for ng_key in ngons:
+                face_offset= len(me.faces)
+                ng= ngons[ng_key]
+                v_locs= []
+                for vi in range(len(ng)):
+                    v_locs.append(mathutils.Vector(layer_data.pnts[ngons[ng_key][vi]]))
+                tris= PolyFill([v_locs])
+                me.faces.add(len(tris))
+                for tri in tris:
+                    face= me.faces[face_offset]
+                    face.vertices_raw[0]= ng[tri[0]]
+                    face.vertices_raw[1]= ng[tri[1]]
+                    face.vertices_raw[2]= ng[tri[2]]
+                    face.material_index= me.faces[ng_key].material_index
+                    face.use_smooth= me.faces[ng_key].use_smooth
+                    face_offset+= 1
+        
+        me.update()
+        
+        # Non-face edges won't show up until Edit Mode cycling
+        if has_edges:
+            bpy.ops.object.select_all(action='DESELECT')
+            ob.users_scene[0].objects.active= ob
+            bpy.ops.object.mode_set(mode='EDIT')
+            bpy.ops.object.mode_set(mode='OBJECT')
+        
+        # Unfortunately we can't exlude certain faces from the subdivision.
+        if layer_data.has_subds and add_subd_mod:
+            ob.modifiers.new(name="Subsurf", type='SUBSURF')
+        
+        # Should we build an armature from the embedded rig?
+        if len(layer_data.bones) > 0 and skel_to_arm:
+            bpy.ops.object.armature_add()
+            arm_object= bpy.context.active_object
+            arm_object.name= "ARM_" + layer_data.name
+            arm_object.data.name= arm_object.name
+            arm_object.location= layer_data.pivot
+            bpy.ops.object.mode_set(mode='EDIT')
+            build_armature(layer_data, arm_object.data.edit_bones)
+            bpy.ops.object.mode_set(mode='OBJECT')
+        
+        # Clear out the dictionaries for this layer.
+        layer_data.bone_names.clear()
+        layer_data.bone_rolls.clear()
+        layer_data.wmaps.clear()
+        layer_data.colmaps.clear()
+        layer_data.uvmaps.clear()
+        layer_data.morphs.clear()
+        layer_data.surf_tags.clear()
+    
+    # With the objects made, setup the parents and re-adjust the locations.
+    for ob_key in ob_dict:
+        if ob_dict[ob_key][1] != -1 and ob_dict[ob_key][1] in ob_dict:
+            parent_ob = ob_dict[ob_dict[ob_key][1]]
+            ob_dict[ob_key][0].parent= parent_ob[0]
+            ob_dict[ob_key][0].location-= parent_ob[0].location
+            
+    bpy.context.scene.update()
+    
+    print("Done Importing LWO File")
+    
+    
+from bpy.props import *
+
+class IMPORT_OT_lwo(bpy.types.Operator):
+    '''Import LWO Operator.'''
+    bl_idname= "import_scene.lwo"
+    bl_label= "Import LWO"
+    bl_description= "Import a LightWave Object file."
+    bl_options= {'REGISTER', 'UNDO'}
+    
+    filepath= StringProperty(name="File Path", description="Filepath used for importing the LWO file", maxlen=1024, default="")
+    
+    ADD_SUBD_MOD= BoolProperty(name="Apply SubD Modifier", description="Apply the Subdivision Surface modifier to layers with Subpatches", default= True)
+    LOAD_HIDDEN= BoolProperty(name="Load Hidden Layers", description="Load object layers that have been marked as hidden", default= False)
+    SKEL_TO_ARM= BoolProperty(name="Create Armature", description="Create an armature from an embedded Skelegon rig", default= True)
+    
+    def execute(self, context):
+        load_lwo(self.properties.filepath,
+                 context,
+                 self.properties.ADD_SUBD_MOD,
+                 self.properties.LOAD_HIDDEN,
+                 self.properties.SKEL_TO_ARM)
+        return {'FINISHED'}
+    
+    def invoke(self, context, event):
+        wm= context.window_manager
+        wm.add_fileselect(self)
+        return {'RUNNING_MODAL'}
+
+
+def menu_func(self, context):
+    self.layout.operator(IMPORT_OT_lwo.bl_idname, text="LightWave Object (.lwo)")
+
+def register():
+    bpy.types.INFO_MT_file_import.append(menu_func)
+    
+def unregister():
+    bpy.types.INFO_MT_file_import.remove(menu_func)
+
+if __name__ == "__main__":
+    register()
\ No newline at end of file