OSDN Git Service

implement pmd_import bone group.
[meshio/meshio.git] / swig / blender / pmd_import.py
old mode 100644 (file)
new mode 100755 (executable)
index 3f7220a..eb6506a
@@ -7,26 +7,53 @@
  Tooltip: 'Import PMD file for MikuMikuDance.'
 """
 __author__= ["ousttrue"]
-__version__= "1.1"
+__version__= "1.2"
 __url__=()
 __bpydoc__="""
 pmd Importer
 
 This script imports a pmd into Blender for editing.
 
-0.1: 20091126: first implement.
-0.2: 20091209: implement IK.
-0.3: 20091210: implement morph target.
-0.4: 20100305: use english name.
-0.5: 20100408: cleanup not used vertices.
-0.6: 20100416: fix fornt face. texture load fail safe. add progress.
-0.7: 20100506: C extension.
-0.8: 20100521: add shape_key group.
-1.0: 20100530: add invisilbe bone tail(armature layer 2).
-1.1: 20100608: integrate 2.4 and 2.5.
+0.1 20091126: first implement.
+0.2 20091209: implement IK.
+0.3 20091210: implement morph target.
+0.4 20100305: use english name.
+0.5 20100408: cleanup not used vertices.
+0.6 20100416: fix fornt face. texture load fail safe. add progress.
+0.7 20100506: C extension.
+0.8 20100521: add shape_key group.
+1.0 20100530: add invisilbe bone tail(armature layer 2).
+1.1 20100608: integrate 2.4 and 2.5.
+1.2 20100616: implement rigid body.
+1.3 20100619: fix for various models.
+1.4 20100623: fix constraint name.
+1.5 20100626: refactoring.
+1.6 20100629: sphere map.
+1.7 20100703: implement bone group.
 """
 
 MMD_SHAPE_GROUP_NAME='_MMD_SHAPE'
+BASE_SHAPE_NAME='Basis'
+RIGID_SHAPE_TYPE='rigid_shape_type'
+RIGID_PROCESS_TYPE='rigid_process_type'
+RIGID_BONE_NAME='rigid_bone_name'
+#RIGID_LOCATION='rigid_loation'
+RIGID_GROUP='ribid_group'
+RIGID_INTERSECTION_GROUP='rigid_intersection_group'
+RIGID_WEIGHT='rigid_weight'
+RIGID_LINEAR_DAMPING='rigid_linear_damping'
+RIGID_ANGULAR_DAMPING='rigid_angular_damping'
+RIGID_RESTITUTION='rigid_restitution'
+RIGID_FRICTION='rigid_friction'
+CONSTRAINT_NAME='constraint_name'
+CONSTRAINT_A='const_a'
+CONSTRAINT_B='const_b'
+CONSTRAINT_POS_MIN='const_pos_min'
+CONSTRAINT_POS_MAX='const_pos_max'
+CONSTRAINT_ROT_MIN='const_rot_min'
+CONSTRAINT_ROT_MAX='const_rot_max'
+CONSTRAINT_SPRING_POS='const_spring_pos'
+CONSTRAINT_SPRING_ROT='const_spring_rot'
 
 
 ###############################################################################
@@ -34,7 +61,6 @@ MMD_SHAPE_GROUP_NAME='_MMD_SHAPE'
 ###############################################################################
 import os
 import sys
-import re
 import math
 
 # C extension
@@ -51,6 +77,46 @@ if isBlender24():
 
     # wrapper
     import bl24 as bl
+
+    def createPmdMaterial(m, index):
+        material=Blender.Material.New()
+        #material.setRef(1)
+        #material.diffuseSize = 3.14/2
+        #material.setDiffuseSmooth(0)
+        #material.setSpecSize(0)
+        #material.setSpec(0)
+        # shader
+        # diffuse
+        material.setDiffuseShader(Blender.Material.Shaders.DIFFUSE_TOON)
+        material.setRGBCol([m.diffuse.r, m.diffuse.g, m.diffuse.b])
+        material.setAlpha(m.diffuse.a)
+        # specular
+        material.setSpecShader(Blender.Material.Shaders.SPEC_TOON)
+        material.setSpec(m.shinness*0.1)
+        material.setSpecCol([m.specular.r, m.specular.g, m.specular.b])
+        # ambient
+        material.setMirCol([m.ambient.r, m.ambient.g, m.ambient.b])
+        # flag
+        material.enableSSS=True if m.flag==1 else False
+        # name
+        material.name="m_%02d" % index
+        return material
+
+    def poseBoneLimit(n, b):
+        if n.endswith("_t"):
+            return
+        if n.startswith("knee_"):
+            b.lockYRot=True
+            b.lockZRot=True
+            b.limitX=True
+            b.limitMin=[0, 0, 0]
+            b.limitMax=[180, 0, 0]
+        elif n.startswith("ankle_"):
+            b.lockYRot=True
+
+    def setSphereMap(material, index, blende_type=None):
+        pass
+
 else:
     # for 2.5
     import bpy
@@ -60,435 +126,120 @@ else:
     # wrapper
     import bl25 as bl
 
+    xrange=range
 
-###############################################################################
-# progress bar
-###############################################################################
-def progress_start(base):
-    global progressBar
-    progressBar=bl.ProgressBar(base)
-
-def progress_finish():
-    global progressBar
-    progressBar.finish()
-
-def progress_print(message, progress=0.05):
-    global progressBar
-    progressBar.advance(message, progress)
-
-def progress_set(message, progress):
-    global progressBar
-    progressBar.set(message, progress)
-
-
-if isBlender24():
-    # functions
-    def convert_coord(pos):
-        """
-        Left handed y-up to Right handed z-up
-        """
-        return (pos.x, pos.z, pos.y)
-
-
-    def convert_uv(uv):
-        return (uv.x, 1.0 - uv.y)
-
-
-    def get_bone_name(l, index):
-        name=englishmap.getEnglishBoneName(l.bones[index].getName())
-        return name if name else l.bones[index].getName().encode(bl.INTERNAL_ENCODING)
-
-
-    def createMaterial():
-        """
-        create default materil 
-        """
-        material=Blender.Material.New()
-        material.setDiffuseShader(Blender.Material.Shaders.DIFFUSE_TOON)
-        material.setRef(1)
-        material.diffuseSize = 3.14/2
-        material.setDiffuseSmooth(0)
-        material.setSpecShader(Blender.Material.Shaders.SPEC_TOON)
-        material.setSpecSize(0)
-        material.setSpec(0)
+    def createPmdMaterial(m, index):
+        material = bpy.data.materials.new("Material")
+        # diffuse
+        material.diffuse_shader='FRESNEL'
+        material.diffuse_color=([m.diffuse.r, m.diffuse.g, m.diffuse.b])
+        material.alpha=m.diffuse.a
+        # specular
+        material.specular_shader='TOON'
+        material.specular_color=([m.specular.r, m.specular.g, m.specular.b])
+        material.specular_toon_size=int(m.shinness)
+        # ambient
+        material.mirror_color=([m.ambient.r, m.ambient.g, m.ambient.b])
+        # flag
+        material.subsurface_scattering.enabled=True if m.flag==1 else False
+        # other
+        material.name="m_%02d" % index
+        material.preview_render_type='FLAT'
+        material.transparency=True
         return material
 
+    def poseBoneLimit(n, b):
+        if n.endswith("_t"):
+            return
+        if n.startswith("knee_"):
+            b.ik_dof_y=False
+            b.ik_dof_z=False
+            b.ik_dof_x=True
+            b.ik_limit_x=True
+            b.ik_min_x=0
+            b.ik_max_x=180
+        elif n.startswith("ankle_"):
+            #b.ik_dof_y=False
+            pass
+
+    def setSphereMap(material, index, blend_type=None):
+        slot=material.texture_slots[index]
+        slot.texture_coordinates='REFLECTION'
+        slot.mapping='SPHERE'
+        if blend_type:
+            slot.blend_type=blend_type
 
-    def importMesh(scene, l, tex_dir):
-        """
-        @param l[in] mmd.PMDLoader
-        @param filename[in]
-        """
-
-        ############################################################
-        # shpaeキーで使われるマテリアル優先的に前に並べる
-        ############################################################
-        # shapeキーで使われる頂点インデックスを集める
-        shape_key_used_vertices=set()
-        if len(l.morph_list)>0:
-            # base 
-            base=None
-            for s in l.morph_list:
-                if s.type!=0:
-                    continue
-                base=s
-                break
-            assert(base)
-
-            for index in base.indices:
-                shape_key_used_vertices.add(index)
-
-        # マテリアルに含まれる頂点がshape_keyに含まれるか否か?
-        def isMaterialUsedInShape(offset, m):
-            for i in xrange(offset, offset+m.vertex_count): 
-                if l.indices[i] in shape_key_used_vertices:
-                    return True
-
-        # shapeキーで使われるマテリアルを記録する
-        shape_key_materials=set()
-        # 各マテリアルの開始頂点インデックスを記録する
-        face_map={}
-        face_count=0
-        for i, m in enumerate(l.materials):
-            face_map[i]=face_count
-            if isMaterialUsedInShape(face_count, m):
-                shape_key_materials.add(i)
-            face_count+=m.vertex_count
-
-        # list化
-        material_order=list(shape_key_materials)
-
-        # shapeキーに使われていないマテリアルを後ろに追加
-        for i in range(len(l.materials)):
-            if not i in material_order:
-                material_order.append(i)
-
-        # マテリアル16個ごとに分割したメッシュを作成する
-        material_offset=0
-        mesh_objects=[]
-        while material_offset<len(l.materials):
-            # create mesh
-            mesh = Blender.Mesh.New()
-            mesh.vertexUV = 1
-            # create object
-            obj = scene.objects.new(mesh)
-            obj.layers = [1]
-            mesh_objects.append(obj)
-
-            # shapeキーで使われる順に並べなおしたマテリアル16個分の
-            # メッシュを作成する
-            vertex_map=import16MaerialAndMesh(
-                    mesh, l, 
-                    material_order[material_offset:material_offset+16], 
-                    face_map, tex_dir)
-
-            # crete shape key
-            importShape(obj, l, vertex_map)
-
-            mesh.update()
-            material_offset+=16
-
-        return mesh_objects
-
-
-    def import16MaerialAndMesh(mesh, l, material_order, face_map, tex_dir):
-        ############################################################
-        # material
-        ############################################################
-        progress_print('create materials')
-        mesh_material_map={}
-        materials=[]
-        index=0
-        for material_index in material_order:
-            try:
-                m=l.materials[material_index]
-                mesh_material_map[material_index]=index
-            except KeyError:
-                break
-
-            material=createMaterial()
-            material.setRGBCol([m.diffuse.r, m.diffuse.g, m.diffuse.b])
-            material.setAlpha(m.diffuse.a)
-            material.setSpec(m.shinness*0.1)
-            material.setSpecCol([m.specular.r, m.specular.g, m.specular.b])
-            material.setMirCol([m.ambient.r, m.ambient.g, m.ambient.b])
-            material.enableSSS=True if m.flag==1 else False
-            # set texture
-            if m.getTexture()!='':
-                tex_file=re.compile('\*.*.spa$').sub('', m.getTexture())
-                tex_path = os.path.join(tex_dir, tex_file).encode(
-                        bl.INTERNAL_ENCODING)
-                tex = Blender.Texture.New()
-                tex.setType("Image")
-                try:
-                    tex.image = Blender.Image.Load(tex_path)
-                    material.setTexture(0, tex)
-                    material.getTextures()[0].texco = Blender.Texture.TexCo.UV
-                except IOError:
-                    print(material.name, "fail to load", tex_path)
-            materials.append(material)
-            # lookup table for assign
-            index+=1
-        mesh.materials=materials
-
-        ############################################################
-        # vertex
-        ############################################################
-        progress_print('create vertices')
-        # create vertices
-        vertex_groups={}
-        vertices=[]
-        for v in l.each_vertex():
-            vertices.append(convert_coord(v.pos))
-            vertex_groups[v.bone0]=True
-            vertex_groups[v.bone1]=True
-        mesh.verts.extend(vertices)
-
-        # create vertex group
-        for i in vertex_groups.keys():
-            mesh.addVertGroup(get_bone_name(l, i))
-
-        # vertex params
-        for i, v, mvert in zip(xrange(len(l.vertices)), l.each_vertex(), mesh.verts):
-            mvert.no=Mathutils.Vector(*convert_coord(v.normal))
-            mvert.uvco=convert_uv(v.uv)
-            w1=float(v.weight0)/100.0
-            w2=1.0-w1
-            mesh.assignVertsToGroup(get_bone_name(l, v.bone0), [i], w1, 
-                    Blender.Mesh.AssignModes.ADD)
-            mesh.assignVertsToGroup(get_bone_name(l, v.bone1), [i], w2, 
-                    Blender.Mesh.AssignModes.ADD)    
-
-        ############################################################
-        # face
-        ############################################################
-        progress_print('create faces')
-        # create faces
-        mesh_face_indices=[]
-        mesh_face_materials=[]
-        used_vertices=set()
-
-        def degenerate(i0, i1, i2):
-            return i0==i1 or i1==i2 or i2==i0
-
-        for material_index in material_order:
-            face_offset=face_map[material_index]
-            m=l.materials[material_index]
-            material_faces=l.indices[face_offset:face_offset+m.vertex_count]
-            for j in xrange(0, len(material_faces), 3):
-                i0=material_faces[j]
-                i1=material_faces[j+1]
-                i2=material_faces[j+2]
-                triangle=[i0, i1, i2]
-                if degenerate(*triangle):
-                    continue
-                mesh_face_indices.append(triangle)
-                mesh_face_materials.append(material_index)
-                used_vertices.add(i0)
-                used_vertices.add(i1)
-                used_vertices.add(i2)
-
-        mesh.faces.extend(mesh_face_indices, ignoreDups=True)
-
-        # face params
-        used_map={}
-        mesh.addUVLayer('NewUV')
-        for face, material_index in zip(mesh.faces, mesh_face_materials):
-            try:
-                index=mesh_material_map[material_index]
-            except KeyError as message:
-                print(message, mesh_material_map, m)
-                assert(False)
-            face.mat=index
-            material=mesh.materials[index]
-            texture=material.getTextures()[0]
-            used_map[index]=True
-            if texture:
-                face.image=texture.tex.image
-                texture.tex.imageFlags|=Blender.Texture.ImageFlags.USEALPHA
-                face.uv=[face.verts[0].uvco, face.verts[1].uvco, face.verts[2].uvco]
-            # set smooth
-            face.smooth = 1
-        # flip
-        mesh.flipNormals()
-
-        ############################################################
-        # clean up not used vertices
-        ############################################################
-        progress_print('clean up vertices not used')
-        remove_vertices=[]
-        vertex_map={}
-        for i, v in enumerate(l.each_vertex()):
-            if i in used_vertices:
-                vertex_map[i]=len(vertex_map)
-            else:
-                remove_vertices.append(i)
-        mesh.verts.delete(remove_vertices)
 
-        progress_print('%s created' % mesh.name)
-        return vertex_map
+###############################################################################
+def VtoV(v):
+    return bl.createVector(v.x, v.y, v.z)
 
+def convert_coord(pos):
+    """
+    Left handed y-up to Right handed z-up
+    """
+    return (pos.x, pos.z, pos.y)
 
-    class Builder(object):
-        def __init__(self):
-            self.boneMap={}
 
-        def build(self, armature, bones):
-            for b in bones:
-                if not b.parent:
-                    self.__build(armature, b, None, None)
-            armature.update()
+def to_radian(degree):
+    return math.pi * degree / 180
 
-        def __build(self, armature, b, p, parent):
-            name=englishmap.getEnglishBoneName(b.getName())
-            if not name:
-                name=b.getName().encode(bl.INTERNAL_ENCODING)
-            self.boneMap[name]=b
-
-            bone=Blender.Armature.Editbone()
-            bone.name=name
-            armature.bones[name]=bone
-
-            if b.tail_index==0:
-                # 先端
-                assert(b.type==6 or b.type==7)
-                bone.head = Mathutils.Vector(*convert_coord(b.pos))
-                bone.tail=bone.head+Mathutils.Vector(0, 1, 0)
-                assert(parent)
-                bone.parent=parent
-                if bone.name=="center_t":
-                    # センターボーンは(0, 1, 0)の方向を向いていないと具合が悪い
-                    parent.tail=parent.head+Mathutils.Vector(0, 1, 0)
-                    bone.head=parent.tail
-                    bone.tail=bone.head+Mathutils.Vector(0, 1, 0)
-                else:
-                    assert(parent.tail==bone.head)
-                bone.options=[Blender.Armature.CONNECTED]
-                # armature layer 2
-                bone.layerMask = (1<<1)
-            else:
-                bone.head = Mathutils.Vector(*convert_coord(b.pos))
-                bone.tail = Mathutils.Vector(*convert_coord(b.tail))
-                if parent:
-                    bone.parent=parent
-                    if parent.tail==bone.head:
-                        bone.options=[Blender.Armature.CONNECTED]
-
-            if bone.head==bone.tail:
-                bone.tail=bone.head+Mathutils.Vector(0, 1, 0)
-
-            for c in b.children:
-                self.__build(armature, c, b, bone)
-
-
-    def importArmature(scene, l):
-        # create armature
-        armature = Blender.Armature.New()
-        # link to object
-        armature_object = scene.objects.new(armature)
-        # create action
-        act = Blender.Armature.NLA.NewAction()
-        act.setActive(armature_object)
-        # set XRAY
-        armature_object.drawMode = (
-                armature_object.drawMode | Blender.Object.DrawModes.XRAY)
-        # armature settings
-        armature.drawType = Blender.Armature.OCTAHEDRON
-        armature.drawNames=True
-        armature.envelopes = False
-        armature.vertexGroups = True
-        armature.mirrorEdit = True
-
-        # create armature
-        armature.makeEditable()
-
-        ############################################################
-        # build bone
-        ############################################################
-        builder=Builder()
-        builder.build(armature, l.bones)
-
-        ############################################################
-        # IK
-        ############################################################
-        pose = armature_object.getPose()
-        cSetting = Blender.Constraint.Settings
-        for ik in l.ik_list:
-            # IKtarget->parent(=IK).name
-            target=l.bones[ik.target]
-            name = englishmap.getEnglishBoneName(target.getName())
-            p_bone = pose.bones[name]
-            if not p_bone:
-                print('not found', name)
-                continue
-            if len(ik.children) >= 16:
-                print('over MAX_CHAINLEN', ik, len(ik.children))
-                continue
-            # IK solver
-            ik_solver = p_bone.constraints.append(Blender.Constraint.Type.IKSOLVER)
-            ik_solver[cSetting.CHAINLEN]=len(ik.children)
-            ik_solver[cSetting.TARGET]=armature_object
-            ik_solver[cSetting.USETIP]=False
-
-            effector_name=englishmap.getEnglishBoneName(
-                    l.bones[ik.index].getName())
-            if not effector_name:
-                effector_name=l.bones[ik.index].getName()
-
-            ik_solver[cSetting.BONE]=effector_name
-            #ik_solver.influence=ik.weight
-            # not used. place folder when export.
-            ik_solver[cSetting.ROTWEIGHT]=ik.weight
-            ik_solver[cSetting.ITERATIONS]=ik.iterations * 10
-
-        armature.makeEditable()
-        armature.update()
-
-        return armature_object
-        
 
-    def importShape(obj, l, vertex_map):
-        if len(l.morph_list)==0:
-            return
-        obj.pinShape=True
-        mesh=obj.getData(mesh=True)
+def get_bone_name(l, index):
+    if index==0xFFFF:
+        return l.bones[0].getName()
 
-        # find base 
-        base=None
-        for s in l.morph_list:
-            if s.type==0:
-                base=s
-
-                # create vertex group
-                mesh.addVertGroup(MMD_SHAPE_GROUP_NAME)
-                indices=[]
-                hasShape=False
-                for i in s.indices:
-                    if i in vertex_map:
-                        hasShape=True
-                        indices.append(vertex_map[i])
-                mesh.assignVertsToGroup(MMD_SHAPE_GROUP_NAME, indices, 0, 
-                        Blender.Mesh.AssignModes.ADD)
-                if not hasShape:
-                    return
-
-                # create base key
-                mesh.insertKey()
-                assert(len(mesh.key.blocks)==1)
-                baseShapeIndex=0
-                baseShapeBlock=mesh.key.blocks[baseShapeIndex]
-                baseShapeBlock.name='Basis'
-                obj.activeShape=baseShapeIndex
-                mesh.update()
-                break
+    if index < len(l.bones):
+        name=englishmap.getEnglishBoneName(l.bones[index].getName())
+        if name:
+            return name
+        return l.bones[index].getName()
+    print('invalid bone index', index)
+    return l.bones[0].getName()
+
+def __importShape(obj, l, vertex_map):
+    if len(l.morph_list)==0:
+        return
 
-        assert(base)
+    # set shape_key pin
+    bl.object.pinShape(obj, True)
 
-        # each skin
-        for s in l.morph_list:
-            if s.name==base.name:
-                continue
+    # find base 
+    base=None
+    for s in l.morph_list:
+        if s.type==0:
+            base=s
 
+            # create vertex group
+            bl.object.addVertexGroup(obj, MMD_SHAPE_GROUP_NAME)
+            hasShape=False
+            for i in s.indices:
+                if i in vertex_map:
+                    hasShape=True
+                    bl.object.assignVertexGroup(
+                            obj, MMD_SHAPE_GROUP_NAME, vertex_map[i], 0)
+            if not hasShape:
+                return
+    assert(base)
+
+    # create base key
+    baseShapeBlock=bl.object.addShapeKey(obj, BASE_SHAPE_NAME)
+    # mesh
+    mesh=bl.object.getData(obj)
+    mesh.update()
+
+    # each skin
+    for s in l.morph_list:
+        if s.type==0:
+            continue
+
+        # name
+        name=englishmap.getEnglishSkinName(s.getName())
+        if not name:
+            name=s.getName()
+
+        if isBlender24():
+            # 24
             for index, offset in zip(s.indices, s.pos_list):
                 try:
                     vertex_index=vertex_map[base.indices[index]]
@@ -497,7 +248,7 @@ if isBlender24():
                     v[0]+=offset[0]
                     v[1]+=offset[1]
                     v[2]+=offset[2]
-                except IndexErrora as msg:
+                except IndexError as msg:
                     print(msg)
                     print(index, len(base.indices), len(vertex_map))
                     print(len(mesh.verts))
@@ -508,17 +259,8 @@ if isBlender24():
                     #print 'this mesh not has shape vertices'
                     break
 
-            # get skin name
-            name=englishmap.getEnglishSkinName(s.getName())
-            if not name:
-                name=s.getName().encode(bl.INTERNAL_ENCODING)
-                print(name)
-
             # create shapekey block
-            mesh.insertKey()
-            shapeIndex=len(mesh.key.blocks)-1
-            keyBlock=mesh.key.blocks[shapeIndex]
-            keyBlock.name=name
+            new_shape_key=bl.object.addShapeKey(obj, name)
 
             # copy vertex to shape key
             mesh.update()
@@ -530,544 +272,573 @@ if isBlender24():
                 mv.co[2] = v[2]
             mesh.update()
 
-        # select base shape
-        obj.activeShape=baseShapeIndex
-
-else:
-    # for 2.5
-    def to_radian(degree):
-        return math.pi * degree / 180
-
-
-    def convert_coord(pos):
-        """
-        Left handed y-up to Right handed z-up
-        """
-        return (pos.x, pos.z, pos.y)
-
-
-    def convert_uv(uv):
-        return (uv.x, 1.0 - uv.y)
+        else:
+            # 25
+            new_shape_key=bl.object.addShapeKey(obj, name)
 
+            for index, offset in zip(s.indices, s.pos_list):
+                try:
+                    vertex_index=vertex_map[base.indices[index]]
+                    bl.shapekey.assign(new_shape_key, vertex_index,
+                            mesh.verts[vertex_index].co+
+                            bl.createVector(*convert_coord(offset)))
+                except IndexError as msg:
+                    print(msg)
+                    print(index, len(base.indices), len(vertex_map))
+                    print(len(mesh.verts))
+                    print(base.indices[index])
+                    print(vertex_index)
+                    break
+                except KeyError:
+                    #print 'this mesh not has shape vertices'
+                    break
 
-    def getBoneName(bone):
-        name = englishmap.getEnglishBoneName(bone.getName())
-        return name if name else bone.getName()
+    # select base shape
+    bl.object.setActivateShapeKey(obj, 0)
 
 
-    def create_texture(directory, texture_name):
-        texture=bpy.data.textures.new(texture_name)
-        texture.type='IMAGE'
-        texture=texture.recast_type()
-        texturePath=os.path.join(directory, texture_name)
-        print('create_texture', texturePath)
-        image=bpy.data.images.load(texturePath)
-        texture.image=image
-        texture.mipmap = True
-        texture.interpolation = True
-        texture.use_alpha = True
-        return texture
+def __build(armature, b, p, parent):
+    name=englishmap.getEnglishBoneName(b.getName())
+    if not name:
+        name=b.getName()
 
+    bone=bl.armature.createBone(armature, name)
 
-    def createMaterial():
-        """
-        create default materil 
-        """
-        material = bpy.data.materials.new("Material")
-        material.diffuse_shader='TOON'
-        material.specular_shader='TOON'
-        # temporary
-        material.emit=1.0
-        return material
+    if parent and (b.tail_index==0 or b.type==6 or b.type==7 or b.type==9):
+        bone.head = bl.createVector(*convert_coord(b.pos))
+        bone.tail=bone.head+bl.createVector(0, 1, 0)
+        bone.parent=parent
+        if bone.name=="center_t":
+            # センターボーンは(0, 1, 0)の方向を向いていないと具合が悪い
+            parent.tail=parent.head+bl.createVector(0, 1, 0)
+            bone.head=parent.tail
+            bone.tail=bone.head+bl.createVector(0, 1, 0)
+        else:
+            if parent.tail==bone.head:
+                pass
+            else:
+                print('diffurence with parent.tail and head', name)
+
+        bl.bone.setConnected(bone)
+        # armature layer 2
+        bl.bone.setLayerMask(bone, [0, 1])
+    else:
+        # 通常ボーン
+        bone.head = bl.createVector(*convert_coord(b.pos))
+        bone.tail = bl.createVector(*convert_coord(b.tail))
+        if parent:
+            bone.parent=parent
+            if parent.tail==bone.head:
+                bl.bone.setConnected(bone)
+
+    if bone.head==bone.tail:
+        bone.tail=bone.head+bl.createVector(0, 1, 0)
+
+    for c in b.children:
+        __build(armature, c, b, bone)
+
+
+def __importArmature(scene, l):
+    armature, armature_object=bl.armature.create()
+
+    # build bone
+    bl.armature.makeEditable(armature_object)
+    for b in l.bones:
+        if not b.parent:
+            __build(armature, b, None, None)
+    bl.armature.update(armature)
+    bl.enterObjectMode()
+
+    # IK constraint
+    pose = bl.object.getPose(armature_object)
+    for ik in l.ik_list:
+        target=l.bones[ik.target]
+        name = englishmap.getEnglishBoneName(target.getName())
+        if not name:
+            name=target.getName()
+        p_bone = pose.bones[name]
+        if not p_bone:
+            print('not found', name)
+            continue
+        if len(ik.children) >= 16:
+            print('over MAX_CHAINLEN', ik, len(ik.children))
+            continue
+        effector_name=englishmap.getEnglishBoneName(
+                l.bones[ik.index].getName())
+        if not effector_name:
+            effector_name=l.bones[ik.index].getName()
+
+        constraint=bl.armature.createIkConstraint(armature_object, 
+                p_bone, effector_name, ik)
+
+    bl.armature.makeEditable(armature_object)
+    bl.armature.update(armature)
+    bl.enterObjectMode()
+
+    if isBlender24():
+        pass
+    else:
+        # create bone group
+        for i, g in enumerate(l.bone_group_list):
+            name=englishmap.getEnglishBoneGroupName(g.getName().strip())
+            if not name:
+                name=g.getName()
+            bl.object.createBoneGroup(armature_object, name, "THEME%02d" % (i+1))
+
+        # assign bone to group
+        for b_index, g_index in l.bone_display_list:
+            # bone
+            b=l.bones[b_index]
+            bone_name=englishmap.getEnglishBoneName(b.getName())
+            if not bone_name:
+                bone_name=b.getName()
+            # group
+            g=l.bone_group_list[g_index-1]
+            group_name=englishmap.getEnglishBoneGroupName(g.getName().strip())
+            if not group_name:
+                group_name=g.getName()
+
+            # assign
+            pose.bones[bone_name].bone_group=pose.bone_groups[group_name]
+
+        bl.enterObjectMode()
+
+    return armature_object
+        
 
+def __import16MaerialAndMesh(meshObject, l, 
+        material_order, face_map, tex_dir):
+
+    mesh=bl.object.getData(meshObject)
+    ############################################################
+    # material
+    ############################################################
+    bl.progress_print('create materials')
+    mesh_material_map={}
+    textureMap={}
+    imageMap={}
+    index=0
+
+    for material_index in material_order:
+        try:
+            m=l.materials[material_index]
+            mesh_material_map[material_index]=index
+        except KeyError:
+            break
 
-    def importMesh(scene, l, tex_dir):
-        """
-        @param l[in] mmd.PMDLoader
-        @param filename[in]
-        """
-
-        ############################################################
-        # shpaeキーで使われるマテリアル優先的に前に並べる
-        ############################################################
-        # shapeキーで使われる頂点インデックスを集める
-        shape_key_used_vertices=set()
-        if len(l.morph_list)>0:
-            # base 
-            base=None
-            for s in l.morph_list:
-                if s.type!=0:
-                    continue
-                base=s
-                break
-            assert(base)
-
-            for index in base.indices:
-                shape_key_used_vertices.add(index)
-
-        # マテリアルに含まれる頂点がshape_keyに含まれるか否か?
-        def isMaterialUsedInShape(offset, m):
-            for i in range(offset, offset+m.vertex_count): 
-                if l.indices[i] in shape_key_used_vertices:
-                    return True
-
-        # shapeキーで使われるマテリアルを記録する
-        shape_key_materials=set()
-        # 各マテリアルの開始頂点インデックスを記録する
-        face_map={}
-        face_count=0
-        for i, m in enumerate(l.materials):
-            face_map[i]=face_count
-            if isMaterialUsedInShape(face_count, m):
-                shape_key_materials.add(i)
-            face_count+=m.vertex_count
-
-        # shapeキーで使われるマテリアルを前に並べるインデックスマップを作る
-        material_map={}
-        used_index=0
-        not_used_index=len(shape_key_materials)
-        for i, m in enumerate(l.materials):
-            if i in shape_key_materials:
-                material_map[i]=used_index
-                used_index+=1
-            else:
-                material_map[i]=not_used_index
-                not_used_index+=1
-
-        # マテリアル16個ごとに分割したメッシュを作成する
-        material_index=0
-        mesh_objects=[]
-        while material_index<len(l.materials):
-            # shapeキーで使われる順に並べなおしたマテリアル16個分の
-            # メッシュを作成する
-            meshObject, used_vertices=import16MaerialAndMesh(l, 
-                    material_index, material_map, face_map, tex_dir)
-            scene.objects.link(meshObject)
-            scene.update()
-            mesh_objects.append(meshObject)
-
-            # enter Edit Mode
-            bpy.ops.object.select_all(action='DESELECT')
-            meshObject.selected=True
-            scene.objects.active=meshObject
-            bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
-     
-            # crete shape key
-            importShape(meshObject, l)
-
-            ############################################################
-            # clean up not used vertices
-            ############################################################
-            #progress_print('clean up vertices not used')
-            vertex_map={}
-            mesh=meshObject.data
-            for i, v in enumerate(mesh.verts):
-                if i in used_vertices:
-                    vertex_map[i]=len(vertex_map)
-                    v.selected=False
-                else:
-                    v.selected=True
-                    assert(mesh.verts[i].selected)
-            bpy.ops.object.mode_set(mode='EDIT', toggle=False)
-            print("%d vertices selected" % mesh.total_vert_sel)
-            print("used %d/%d" % (len(vertex_map), len(mesh.verts)))
-            bpy.ops.mesh.delete(type='VERT')
-
-            ############################################################
-            # flip face
-            ############################################################
-            bpy.ops.mesh.select_all(action='SELECT')
-            bpy.ops.mesh.flip_normals()
-            bpy.ops.mesh.select_all(action='DESELECT')
-
-            # exit Edit Mode
-            bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+        material=createPmdMaterial(m, material_index)
 
-            mesh.update()
-            material_index+=16
-
-        return mesh_objects
-
-
-    def import16MaerialAndMesh(l, 
-            material_offset, material_map, face_map, tex_dir):
-        # create mesh
-        mesh=bpy.data.meshes.new("Mesh")
-
-        # create object
-        meshObject= bpy.data.objects.new("Mesh", mesh)
-        meshObject.layers[0]=True
-
-        ############################################################
-        # material
-        ############################################################
-        #progress_print('create materials')
-        mesh_material_map={}
-        materials=[]
-        textureMap={}
-        imageMap={}
-        index=0
-        for i in range(material_offset, material_offset+16):
-            try:
-                material_index=material_map[i]
-                m=l.materials[material_index]
-                mesh_material_map[material_index]=index
-            except KeyError:
-                break
-
-            material=createMaterial()
-            material.diffuse_color=([m.diffuse.r, m.diffuse.g, m.diffuse.b])
-            material.alpha=m.diffuse.a
-            material.specular_hardness=int(m.shinness)
-            material.specular_color=([m.specular.r, m.specular.g, m.specular.b])
-            material.mirror_color=([m.ambient.r, m.ambient.g, m.ambient.b])
-            texture_name=m.getTexture()
-            if texture_name!='':
-                if texture_name in textureMap:
-                    texture=textureMap[texture_name]
+        texture_name=m.getTexture()
+        if texture_name!='':
+            for i, t in enumerate(texture_name.split('*')):
+                if t in textureMap:
+                    texture=textureMap[t]
                 else:
-                    texture=create_texture(tex_dir, texture_name)
+                    path=os.path.join(tex_dir, t)
+                    texture, image=bl.texture.create(path)
                     textureMap[texture_name]=texture
-                    imageMap[material_index]=texture.image
-                #material.add_texture(texture, "UV", {"COLOR", "ALPHA"})
-                material.add_texture(texture, "UV", "COLOR")
-
-            materials.append(material)
-            mesh.add_material(material)
-            # lookup table for assign
-            index+=1
-
-        ############################################################
-        # vertex
-        ############################################################
-        #progress_print('create vertices')
-        # create vertices
-        vertex_groups={}
-        unpackedVertices=[]
-        for v in l.each_vertex():
-            unpackedVertices.extend(
-                    convert_coord(v.pos))
-            vertex_groups[v.bone0]=True
-            vertex_groups[v.bone1]=True
-
-        ############################################################
-        # face
-        ############################################################
-        #progress_print('create faces')
-        # create faces
-        mesh_face_indices=[]
-        mesh_face_materials=[]
-        used_vertices=set()
-        for i in range(material_offset, material_offset+16):
-            try:
-                material_index=material_map[i]
-            except KeyError:
-                break
-            face_offset=face_map[material_index]
-            m=l.materials[material_index]
-            material_faces=l.indices[face_offset:face_offset+m.vertex_count]
-            for j in range(0, len(material_faces), 3):
-                i0=material_faces[j]
-                i1=material_faces[j+1]
-                i2=material_faces[j+2]
-                if i2==0:
-                    mesh_face_indices.extend([i2, i0, i1, 0])
-                else:
-                    mesh_face_indices.extend([i0, i1, i2, 0])
-                mesh_face_materials.append(material_index)
-                used_vertices.add(i0)
-                used_vertices.add(i1)
-                used_vertices.add(i2)
-
-        ############################################################
-        # create vertices & faces
-        ############################################################
-        mesh.add_geometry(
-                int(len(unpackedVertices)/3), 0, int(len(mesh_face_indices)/4))
-        mesh.verts.foreach_set("co", unpackedVertices)
-        mesh.faces.foreach_set("verts_raw", mesh_face_indices)
-        assert(len(l.vertices)==len(mesh.verts))
-
-        ############################################################
-        # face params
-        ############################################################
-        used_map={}
-        mesh.add_uv_texture()
-
-        for face, uv_face, material_index in zip(mesh.faces, 
-                mesh.uv_textures[0].data,
-                mesh_face_materials,
-                ):
-            try:
-                index=mesh_material_map[material_index]
-            except KeyError as message:
-                print(message, mesh_material_map, m)
-                assert(False)
-            face.material_index=index
-            material=mesh.materials[index]
-            used_map[index]=True
-            if material.texture_slots[0]:
-                #texture=material.texture_slots[0].texture
-                #face.image=texture.image
-                #texture.imageFlags|=Blender.Texture.ImageFlags.USEALPHA
-                uv=l.getUV(face.verts[0])
-                uv_face.uv1=[uv.x, 1.0-uv.y]
-
-                uv=l.getUV(face.verts[1])
-                uv_face.uv2=[uv.x, 1.0-uv.y]
-
-                uv=l.getUV(face.verts[2])
-                uv_face.uv3=[uv.x, 1.0-uv.y]
-            if face.material_index in imageMap:
-                uv_face.image=imageMap[face.material_index]
-                uv_face.tex=True
-
-            # set smooth
-            face.smooth = 1
-
-        ############################################################
-        # vertex weight
-        ############################################################
-        # create vertex group
-        for i in vertex_groups.keys():
-            meshObject.add_vertex_group(getBoneName(l.bones[i]))
-
-        # vertex params
-        for i, v, mvert in zip(range(len(l.vertices)), 
-                l.each_vertex(), mesh.verts):
-            mvert.normal=mathutils.Vector(convert_coord(v.normal))
-            #mvert.uvco=convert_uv(v.uv)
-            w1=float(v.weight0)/100.0
-            w2=1.0-w1
-
-            meshObject.add_vertex_to_group(i, 
-                    meshObject.vertex_groups[getBoneName(l.bones[v.bone0])], w1, 'ADD')
-            meshObject.add_vertex_to_group(i, 
-                    meshObject.vertex_groups[getBoneName(l.bones[v.bone1])], w2, 'ADD')
-        mesh.update()
+                    imageMap[material_index]=image
+                bl.material.addTexture(material, texture)
+                if t.endswith('sph'):
+                    # sphere map
+                    setSphereMap(material, i)
+                elif t.endswith('spa'):
+                    # sphere map
+                    setSphereMap(material, i, 'ADD')
+
+        bl.mesh.addMaterial(mesh, material)
+        index+=1
+
+    ############################################################
+    # vertex
+    ############################################################
+    bl.progress_print('create vertices')
+    # create vertices
+    vertices=[]
+    for v in l.each_vertex():
+        vertices.append(convert_coord(v.pos))
+
+    ############################################################
+    # face
+    ############################################################
+    bl.progress_print('create faces')
+    # create faces
+    mesh_face_indices=[]
+    mesh_face_materials=[]
+    used_vertices=set()
+
+    for material_index in material_order:
+        face_offset=face_map[material_index]
+        m=l.materials[material_index]
+        material_faces=l.indices[face_offset:face_offset+m.vertex_count]
 
-        #progress_print('%s created' % mesh.name)
-        return meshObject, used_vertices
+        def degenerate(i0, i1, i2):
+            """
+            縮退しているか?
+            """
+            return i0==i1 or i1==i2 or i2==i0
 
+        for j in xrange(0, len(material_faces), 3):
+            i0=material_faces[j]
+            i1=material_faces[j+1]
+            i2=material_faces[j+2]
+            # flip
+            triangle=[i2, i1, i0]
+            if degenerate(*triangle):
+                continue
+            mesh_face_indices.append(triangle[0:3])
+            mesh_face_materials.append(material_index)
+            used_vertices.add(i0)
+            used_vertices.add(i1)
+            used_vertices.add(i2)
+
+    ############################################################
+    # create vertices & faces
+    ############################################################
+    bl.mesh.addGeometry(mesh, vertices, mesh_face_indices)
+
+    ############################################################
+    # vertex bone weight
+    ############################################################
+    # create vertex group
+    vertex_groups={}
+    for v in l.each_vertex():
+        vertex_groups[v.bone0]=True
+        vertex_groups[v.bone1]=True
+    for i in vertex_groups.keys():
+        bl.object.addVertexGroup(meshObject, get_bone_name(l, i))
+
+    # vertex params
+    bl.mesh.useVertexUV(mesh)
+    for i, v, mvert in zip(xrange(len(l.vertices)), 
+        l.each_vertex(), mesh.verts):
+        # normal, uv
+        bl.vertex.setNormal(mvert, convert_coord(v.normal))
+        # bone weight
+        w1=float(v.weight0)/100.0
+        w2=1.0-w1
+        bl.object.assignVertexGroup(meshObject, get_bone_name(l, v.bone0),
+            i,  w1)
+        bl.object.assignVertexGroup(meshObject, get_bone_name(l, v.bone1),
+            i,  w2)
+
+    ############################################################
+    # face params
+    ############################################################
+    used_map={}
+    bl.mesh.addUV(mesh)
+    for i, (face, material_index) in enumerate(
+            zip(mesh.faces, mesh_face_materials)):
+        try:
+            index=mesh_material_map[material_index]
+        except KeyError as message:
+            print(message, mesh_material_map, m)
+            assert(False)
+        bl.face.setMaterial(face, index)
+        material=mesh.materials[index]
+        used_map[index]=True
+        if bl.material.hasTexture(material):
+            uv_array=[l.getUV(i) for i in bl.face.getIndices(face)]
+            bl.mesh.setFaceUV(mesh, i, face, 
+                    # fix uv
+                    [(uv.x, 1.0-uv.y) for uv in uv_array], 
+                    imageMap.get(index, None))
+
+        # set smooth
+        face.smooth = 1
+
+    mesh.update()
+
+    ############################################################
+    # clean up not used vertices
+    ############################################################
+    bl.progress_print('clean up vertices not used')
+    remove_vertices=[]
+    vertex_map={}
+    for i, v in enumerate(l.each_vertex()):
+        if i in used_vertices:
+            vertex_map[i]=len(vertex_map)
+        else:
+            remove_vertices.append(i)
 
-    def build_bone(armature, b, parent=None):
-        if b.tail_index==0:
-            return
+    bl.mesh.vertsDelete(mesh, remove_vertices)
 
-        name=getBoneName(b)
-        bone = armature.edit_bones.new(name if name else b.getName())
-        if parent:
-            bone.head = mathutils.Vector(convert_coord(b.pos))
-            bone.parent=parent
-            bone.connected=True if parent.tail==bone.head else False
-            bone.tail = mathutils.Vector(convert_coord(b.tail))
-            if bone.head==bone.tail:
-                bone.tail=bone.head-mathutils.Vector((0, 1, 0))
-        elif b.__class__ is pmd.BONE_IK:
-            bone.head = mathutils.Vector(convert_coord(b.pos))
-            bone.tail = mathutils.Vector(convert_coord(b.tail))
-        else:
-            # center
-            tail=mathutils.Vector(convert_coord(b.pos))
-            bone.tail = tail
-            bone.head = tail-mathutils.Vector((0, 1, 0))
-
-        for child in b.children:
-            build_bone(armature, child, bone)
-
-
-    def importArmature(scene, l):
-        # create armature
-        armature = bpy.data.armatures.new('Armature')
-        # link to object
-        armature_object=bpy.data.objects.new('Armature', armature)
-        scene.objects.link(armature_object)
-        armature_object.x_ray=True
-        armature.draw_names=True
-
-        # armature settings
-        armature.drawtype='OCTAHEDRAL'
-        armature.deform_envelope=False
-        armature.deform_vertexgroups=True
-        armature.x_axis_mirror=True
-
-        # create action
-        #act = Blender.Armature.NLA.NewAction()
-        #act.setActive(armature_object)
-
-        # select only armature object and set edit mode
-        scene.objects.active=armature_object
-        bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
-        bpy.ops.object.mode_set(mode='EDIT', toggle=False)
-
-        # create armature
-        for b in l.bones:
-            if not b.parent:
-                build_bone(armature, b)
-
-        bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
-        bpy.ops.object.select_all(action='DESELECT')
-
-        ############################################################
-        # IK
-        ############################################################
-        pose = armature_object.pose
-        for ik in l.ik_list:
-            effector=l.bones[ik.target]
-            parent=l.bones[effector.parent_index]
-            name=getBoneName(parent)
-            p_bone = pose.bones[name]
-            if not p_bone:
-                print('not found', name)
-                continue
-            if len(ik.children) >= 16:
-                print('over MAX_CHAINLEN', ik, len(ik.children))
-                continue
-            # IK
-            ik_const = p_bone.constraints.new('IK')
-            ik_const.chain_length=len(ik.children)
-            ik_const.target=armature_object
-            ik_const.subtarget=getBoneName(l.bones[ik.index])
-            # ROT
-            rot_const = p_bone.constraints.new('LIMIT_ROTATION')
-            rot_const.influence = ik.weight
-            rot_const.owner_space = 'LOCAL'
-            rot_const.use_limit_x=True
-            rot_const.use_limit_z=True
-            rot_const.minimum_x=to_radian(ik.iterations)
-            rot_const.maximum_x=to_radian(180)
-            rot_const.minimum_z=to_radian(180 - ik.iterations)
-            rot_const.maximum_z=to_radian(0)
-
-        return armature_object
-        
+    bl.progress_print('%s created' % mesh.name)
+    return vertex_map
 
-    def importShape(meshObject, l):
-        if len(l.morph_list)==0:
-            return
 
+def __importMesh(scene, io, tex_dir):
+    """
+    @param l[in] mmd.PMDLoader
+    @param filename[in]
+    """
+    ############################################################
+    # shpaeキーで使われるマテリアル優先的に前に並べる
+    ############################################################
+    # shapeキーで使われる頂点インデックスを集める
+    shape_key_used_vertices=set()
+    if len(io.morph_list)>0:
         # base 
         base=None
-        for s in l.morph_list:
+        for s in io.morph_list:
             if s.type!=0:
                 continue
             base=s
             break
         assert(base)
 
-        # create base key
-        baseblock=meshObject.add_shape_key("Basis")
+        for index in base.indices:
+            shape_key_used_vertices.add(index)
 
-        # mesh
-        mesh=meshObject.data
+    # マテリアルに含まれる頂点がshape_keyに含まれるか否か?
+    def isMaterialUsedInShape(offset, m):
+        for i in xrange(offset, offset+m.vertex_count): 
+            if io.indices[i] in shape_key_used_vertices:
+                return True
 
-        # each skin
-        for s in l.morph_list:
-            if s.getName()==base.name:
-                # skip base
-                continue
+    material_with_shape=set()
 
-            # restore
-            #for v, base_pos in zip(mesh.verts, baseblock.data):
-            #    v.co=base_pos.co
-            #mesh.update()
+    # 各マテリアルの開始頂点インデックスを記録する
+    face_map={}
+    face_count=0
+    for i, m in enumerate(io.materials):
+        face_map[i]=face_count
+        if isMaterialUsedInShape(face_count, m):
+            material_with_shape.add(i)
+        face_count+=m.vertex_count
 
-            # name
-            name=englishmap.getEnglishSkinName(s.getName())
-            if not name:
-                name=s.getName()
-            new_shape_key=meshObject.add_shape_key(name)
-            #new_shape_key.value=1.0
+    # shapeキーで使われる頂点のあるマテリアル
+    material_with_shape=list(material_with_shape)
+    material_with_shape.sort()
+
+    # shapeキーに使われていないマテリアル
+    material_without_shape=[]
+    for i in range(len(io.materials)):
+        if not i in material_with_shape:
+            material_without_shape.append(i)
+
+    # メッシュの生成
+    def __splitList(l, length):
+        for i in range(0, len(l), length):
+            yield l[i:i+length]
+
+    def __importMeshAndShape(material16, name):
+        mesh, meshObject=bl.mesh.create(name)
+
+        # activate object
+        bl.object.deselectAll()
+        bl.object.activate(meshObject)
+
+        # shapeキーで使われる順に並べなおしたマテリアル16個分の
+        # メッシュを作成する
+        vertex_map=__import16MaerialAndMesh(
+                meshObject, io, material16, face_map, tex_dir)
+
+        # crete shape key
+        __importShape(meshObject, io, vertex_map)
+
+        mesh.update()
+        return meshObject
+
+    mesh_objects=[__importMeshAndShape(material16, 'with_shape')
+        for material16 in __splitList(material_with_shape, 16)]
+    
+    mesh_objects+=[__importMeshAndShape(material16, 'mesh')
+        for material16 in __splitList(material_without_shape, 16)]
+    return mesh_objects
+
+
+def __importConstraints(scene, io):
+    if isBlender24():
+        return
+    print("create constraint")
+    container=bl.object.createEmpty('Constraints')
+    layer=[
+            True, False, False, False, False, False, False, False,
+            False, False, False, False, False, False, False, False,
+            False, False, False, False, False, False, False, False,
+            False, False, False, False, False, False, False, False,
+            ]
+    material=bl.material.create('constraint')
+    material.diffuse_color=(1, 0, 0)
+    constraintMeshes=[]
+    for i, c in enumerate(io.constraints):
+        bpy.ops.mesh.primitive_uv_sphere_add(
+                segments=8,
+                rings=4,
+                size=0.1,
+                location=(c.pos.x, c.pos.z, c.pos.y),
+                layer=layer
+                )
+        meshObject=scene.objects.active
+        constraintMeshes.append(meshObject)
+        mesh=bl.object.getData(meshObject)
+        bl.mesh.addMaterial(mesh, material)
+        meshObject.name='c_%d' % i
+        #meshObject.draw_transparent=True
+        #meshObject.draw_wire=True
+        meshObject.max_draw_type='SOLID'
+        rot=c.rot
+        meshObject.rotation_euler=(-rot.x, -rot.z, -rot.y)
+
+        meshObject[CONSTRAINT_NAME]=c.getName()
+        meshObject[CONSTRAINT_A]=io.rigidbodies[c.rigidA].getName()
+        meshObject[CONSTRAINT_B]=io.rigidbodies[c.rigidB].getName()
+        meshObject[CONSTRAINT_POS_MIN]=VtoV(c.constraintPosMin)
+        meshObject[CONSTRAINT_POS_MAX]=VtoV(c.constraintPosMax)
+        meshObject[CONSTRAINT_ROT_MIN]=VtoV(c.constraintRotMin)
+        meshObject[CONSTRAINT_ROT_MAX]=VtoV(c.constraintRotMax)
+        meshObject[CONSTRAINT_SPRING_POS]=VtoV(c.springPos)
+        meshObject[CONSTRAINT_SPRING_ROT]=VtoV(c.springRot)
+
+    for meshObject in reversed(constraintMeshes):
+        bl.object.makeParent(container, meshObject)
+
+    return container
+
+
+def __importRigidBodies(scene, io):
+    if isBlender24():
+        return
+    print("create rigid bodies")
+
+    container=bl.object.createEmpty('RigidBodies')
+    layer=[
+            True, False, False, False, False, False, False, False,
+            False, False, False, False, False, False, False, False,
+            False, False, False, False, False, False, False, False,
+            False, False, False, False, False, False, False, False,
+            ]
+    material=bl.material.create('rigidBody')
+    rigidMeshes=[]
+    for rigid in io.rigidbodies:
+        if rigid.boneIndex==0xFFFF:
+            # no reference bone
+            bone=io.bones[0]
+        else:
+            bone=io.bones[rigid.boneIndex]
+        pos=bone.pos+rigid.position
+
+        if rigid.shapeType==pmd.SHAPE_SPHERE:
+            bpy.ops.mesh.primitive_ico_sphere_add(
+                    location=(pos.x, pos.z, pos.y),
+                    layer=layer
+                    )
+            bpy.ops.transform.resize(
+                    value=(rigid.w, rigid.w, rigid.w))
+        elif rigid.shapeType==pmd.SHAPE_BOX:
+            bpy.ops.mesh.primitive_cube_add(
+                    location=(pos.x, pos.z, pos.y),
+                    layer=layer
+                    )
+            bpy.ops.transform.resize(
+                    value=(rigid.w, rigid.d, rigid.h))
+        elif rigid.shapeType==pmd.SHAPE_CAPSULE:
+            bpy.ops.mesh.primitive_tube_add(
+                    location=(pos.x, pos.z, pos.y),
+                    layer=layer
+                    )
+            bpy.ops.transform.resize(
+                    value=(rigid.w, rigid.w, rigid.h))
+        else:
+            assert(False)
+
+        meshObject=scene.objects.active
+        mesh=bl.object.getData(meshObject)
+        rigidMeshes.append(meshObject)
+        bl.mesh.addMaterial(mesh, material)
+        meshObject.name=rigid.getName()
+        #meshObject.draw_transparent=True
+        #meshObject.draw_wire=True
+        meshObject.max_draw_type='WIRE'
+        rot=rigid.rotation
+        meshObject.rotation_euler=(-rot.x, -rot.z, -rot.y)
+
+        # custom properties
+        meshObject[RIGID_SHAPE_TYPE]=rigid.shapeType
+        meshObject[RIGID_PROCESS_TYPE]=rigid.processType
+
+        bone_name = englishmap.getEnglishBoneName(bone.getName())
+        if not bone_name:
+            bone_name=bone.getName()
+        meshObject[RIGID_BONE_NAME]=bone_name
+
+        meshObject[RIGID_GROUP]=rigid.group
+        meshObject[RIGID_INTERSECTION_GROUP]=rigid.target
+        meshObject[RIGID_WEIGHT]=rigid.weight
+        meshObject[RIGID_LINEAR_DAMPING]=rigid.linearDamping
+        meshObject[RIGID_ANGULAR_DAMPING]=rigid.angularDamping
+        meshObject[RIGID_RESTITUTION]=rigid.restitution
+        meshObject[RIGID_FRICTION]=rigid.friction
+
+    for meshObject in reversed(rigidMeshes):
+        bl.object.makeParent(container, meshObject)
+
+    return container
 
-            # morph
-            for i, offset in zip(s.indices, s.pos_list):
-                try:
-                    vertex_index=base.indices[i]
-                    new_shape_key.data[vertex_index].co=[p+o for p, o in zip(
-                        mesh.verts[vertex_index].co, convert_coord(offset))]
-                except IndexError as msg:
-                    print(IndexError, msg)
-                    print(i, len(base.indices))
-                    print(vertex_index, len(mesh.verts))
-                    print(base.indices[i])
-                    break
-                except KeyError:
-                    #print 'this mesh not has shape vertices'
-                    break
-            
-            # set ipo curve
-            #icu=ipo.addCurve(name)
-            #icu.interpolation = Blender.IpoCurve.InterpTypes.LINEAR
-            #icu.append( (0.0, 0.0) )
 
-   
 def __execute(filename, scene):
     """
     load pmd file to context.
     """
+           
     # load pmd
-    progress_set('load %s' % filename, 0.0)
+    bl.progress_set('load %s' % filename, 0.0)
 
     io=pmd.IO()
     if not io.read(filename):
-        print("fail to load %s" % filename)
+        bl.message("fail to load %s" % filename)
         return
-    progress_set('loaded %s' % filename, 0.1)
+    bl.progress_set('loaded %s' % filename, 0.1)
 
     # create root object
-    root=bl.createEmptyObject(scene, 
-            io.english_name if len(io.english_name)>0 else io.getName().encode(bl.INTERNAL_ENCODING))
+    model_name=io.getEnglishName()
+    if len(model_name)==0:
+        model_name=io.getName()
+    root=bl.object.createEmpty(model_name)
 
     # import mesh
-    mesh_objects=importMesh(scene, io, os.path.dirname(filename))
+    mesh_objects=__importMesh(scene, io, os.path.dirname(filename))
     for o in mesh_objects:
-        bl.objectMakeParent(root, o)
+        bl.object.makeParent(root, o)
 
     # import armature
-    armature_object=importArmature(scene, io)
+    armature_object=__importArmature(scene, io)
     if armature_object:
-        bl.objectMakeParent(root, armature_object)
-        armature = bl.objectGetData(armature_object) 
+        bl.object.makeParent(root, armature_object)
+        armature = bl.object.getData(armature_object) 
 
         # add armature modifier
         for o in mesh_objects:
-            bl.objectAddArmatureModifier(o, armature_object)
+            bl.modifier.addArmature(o, armature_object)
 
         # Limitation
-        for n, b in bl.objectGetPose(armature_object).bones.items():
-            bl.poseBoneLimit(n, b)
+        for n, b in bl.object.getPose(armature_object).bones.items():
+            poseBoneLimit(n, b)
+
+    # import rigid bodies
+    rigidBodies=__importRigidBodies(scene, io)
+    if rigidBodies:
+        bl.object.makeParent(root, rigidBodies)
+
+    # import constraints
+    constraints=__importConstraints(scene, io)
+    if constraints:
+        bl.object.makeParent(root, constraints)
+
+    bl.object.activate(root)
 
-    # select objects
-    bl.objectSelect(root)
-    for o in mesh_objects:
-        bl.objectSelect(o)
-    bl.objectSelect(armature_object)
 
 if isBlender24():
     # for 2.4
     def execute_24(filename):
-        """
-        @param filename
-        """
-        filename=filename.decode(bl.INTERNAL_ENCODING)
-        print(bl.INTERNAL_ENCODING, bl.FS_ENCODING)
-
-        # set object mode
-        mode_edit = Blender.Window.EditMode() 
-        if mode_edit: 
-            Blender.Window.EditMode(0)
-            
-        progress_start('pmd_import')
-        scene = bpy.data.scenes.active
-        __execute(filename, scene)
-        scene.update(0)
-        progress_finish()
-
-        # restore edit mode
-        if mode_edit: 
-            Blender.Window.EditMode(1)
-        Blender.Window.RedrawAll()
+        scene=bpy.data.scenes.active
+        bl.initialize('pmd_import', scene)
+        __execute(
+                filename.decode(bl.INTERNAL_ENCODING), 
+                scene)
+        bl.finalize()
 
     Blender.Window.FileSelector(
             execute_24, 
@@ -1076,10 +847,10 @@ if isBlender24():
 
 else:
     # for 2.5
-    def execute_25(*args):
-        progress_start('pmd_import')
-        __execute(*args)
-        progress_finish()
+    def execute_25(filename, scene):
+        bl.initialize('pmd_import', scene)
+        __execute(filename, scene)
+        bl.finalize()
 
     # import operator
     class IMPORT_OT_pmd(bpy.types.Operator):