OSDN Git Service

fixed by @santarh
[meshio/meshio.git] / blender24 / pmd_import.py
diff --git a/blender24/pmd_import.py b/blender24/pmd_import.py
deleted file mode 100644 (file)
index 221041c..0000000
+++ /dev/null
@@ -1,552 +0,0 @@
-#!BPY
-# coding:utf-8
-"""
- Name: 'MikuMikuDance model (.pmd)...'
- Blender: 248
- Group: 'Import'
- Tooltip: 'Import PMD file for MikuMikuDance.'
-"""
-__author__= ["ousttrue"]
-__version__= "0.7"
-__url__=()
-__bpydoc__="""
-0.1: 20091126
-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.
-"""
-import Blender
-from Blender import Mathutils
-import bpy
-
-import os
-import sys
-
-# extension
-from meshio import pmd, englishmap
-
-
-if os.path.exists(os.path.dirname(sys.argv[0])+"/utf8"):
-    FS_ENCODING='utf-8'
-else:
-    FS_ENCODING=sys.getfilesystemencoding()
-print FS_ENCODING
-
-
-def cp932_to_utf8(cp932):
-    return str(cp932).decode('cp932').encode('utf-8')
-
-
-class ProgressBar(object):
-    def __init__(self, base):
-        print "#### %s ####" % base
-        self.base=base
-        self.start=Blender.sys.time() 
-        self.set('<start>', 0)
-
-    def advance(self, message, progress):
-        self.progress+=float(progress)
-        self._print(message)
-
-    def set(self, message, progress):
-        self.progress=float(progress)
-        self._print(message)
-
-    def _print(self, message):
-        print message
-        message="%s: %s" % (self.base, message)
-        if message.__class__ is unicode:
-            message=message.encode('utf-8')
-        Blender.Window.DrawProgressBar(self.progress, message)
-
-    def finish(self):
-        self.progress=1.0
-        message='finished in %.2f sec' % (Blender.sys.time()-self.start)
-        self.set(message, 1.0)
-
-def progress_start(base):
-    global progressBar
-    progressBar=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)
-
-
-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].name.decode('cp932'))
-    return name if name else cp932_to_utf8(l.bones[index].name)
-
-
-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)
-    return material
-
-
-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
-
-    # 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):
-        # 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_index, material_map, face_map, tex_dir)
-
-        # crete shape key
-        importShape(mesh, l, vertex_map)
-
-        mesh.update()
-        material_index+=16
-
-    return mesh_objects
-
-
-def import16MaerialAndMesh(mesh, l, 
-        material_offset, material_map, face_map, tex_dir):
-    ############################################################
-    # material
-    ############################################################
-    progress_print('create materials')
-    mesh_material_map={}
-    materials=[]
-    index=0
-    for i in xrange(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.setRGBCol([m.diffuse.r, m.diffuse.g, m.diffuse.b])
-        material.setAlpha(m.diffuse.a)
-        material.setHardness(int(m.shinness))
-        material.setSpecCol([m.specular.r, m.specular.g, m.specular.b])
-        material.setMirCol([m.ambient.r, m.ambient.g, m.ambient.b])
-        # set texture
-        if m.texture!='':
-            if not tex_dir.endswith("\\") and not tex_dir.endswith("/"):
-                tex_dir+="/"
-            tex_path = tex_dir+m.texture
-            tex = Blender.Texture.New()
-            tex.setType("Image")
-            try:
-                tex.image = Blender.Image.Load(cp932_to_utf8(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()
-    for i in xrange(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 xrange(0, len(material_faces), 3):
-            i0=material_faces[j]
-            i1=material_faces[j+1]
-            i2=material_faces[j+2]
-            mesh_face_indices.append([i0, i1, i2])
-            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)
-    assert(len(mesh.faces)==len(mesh_face_indices))
-
-    # 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, 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 build_bone(armature, b, parent=None):
-    if b.tail_index==0:
-        return
-
-    bone = Blender.Armature.Editbone()
-    name=englishmap.getEnglishBoneName(b.name.decode('cp932'))
-    bone.name = name if name else cp932_to_utf8(b.name)
-    armature.bones[bone.name] = bone
-    if parent:
-        bone.head = Mathutils.Vector(*convert_coord(b.pos))
-        bone.parent=parent
-        options=[]
-        if parent.tail==bone.head:
-            options.append(Blender.Armature.CONNECTED)
-        bone.options=options
-        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 = 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.envelopes = False
-    armature.vertexGroups = True
-    armature.mirrorEdit = True
-
-    # create armature
-    armature.makeEditable()
-    for b in l.bones:
-        if not b.parent:
-            build_bone(armature, b)
-    armature.update()
-
-    ############################################################
-    # IK
-    ############################################################
-    pose = armature_object.getPose()
-    cSetting = Blender.Constraint.Settings
-    for ik in l.ik_list:
-        # IKtarget->parent(=IK).name
-        target=l.bones[ik.target]
-        parent=l.bones[target.parent_index]
-        name = englishmap.getEnglishBoneName(parent.name.decode('cp932'))
-        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_const = p_bone.constraints.append(Blender.Constraint.Type.IKSOLVER)
-        ik_const[cSetting.CHAINLEN] = len(ik.children)
-        ik_const[cSetting.TARGET] = armature_object
-        ik_const[cSetting.BONE] = englishmap.getEnglishBoneName(
-                l.bones[ik.index].name.decode('cp932'))
-        lrot_const = p_bone.constraints.append(Blender.Constraint.Type.LIMITROT)
-        lrot_const.influence = ik.weight
-        lrot_const[cSetting.OWNERSPACE] = cSetting.SPACE_LOCAL
-        lrot_const[cSetting.LIMIT] = (cSetting.LIMIT_XROT | cSetting.LIMIT_ZROT)
-        lrot_const[cSetting.XMIN] = ik.iterations
-        lrot_const[cSetting.XMAX] = 180
-        lrot_const[cSetting.ZMIN] = 180 - ik.iterations
-        lrot_const[cSetting.ZMAX] = 0
-
-    armature.makeEditable()
-    armature.update()
-
-    return armature_object
-    
-
-def importShape(mesh, l, vertex_map):
-    if len(l.morph_list)==0:
-        return
-    # base 
-    base=None
-    for s in l.morph_list:
-        if s.type!=0:
-            continue
-        base=s
-        break
-    assert(base)
-    mesh.insertKey()
-    baseblock=mesh.key.blocks[-1]
-    ipo=Blender.Ipo.New('Key', 'pmd')
-    mesh.key.ipo=ipo
-
-    # each skin
-    for s in l.morph_list:
-        if s.name==base.name:
-            continue
-        name=englishmap.getEnglishSkinName(s.name.decode('cp932'))
-        if not name:
-            name=cp932_to_utf8(s.name)
-        for index, offset in zip(s.indices, s.pos_list):
-            try:
-                vertex_index=vertex_map[base.indices[index]]
-                v=mesh.verts[vertex_index].co
-                offset=convert_coord(offset)
-                v[0]+=offset[0]
-                v[1]+=offset[1]
-                v[2]+=offset[2]
-            except IndexError, msg:
-                print IndexError, msg
-                print index, len(base.indices)
-                print vertex_index, len(mesh.verts)
-                print base.indices[index]
-                break
-            except KeyError:
-                #print 'this mesh not has shape vertices'
-                break
-        
-        # set shapekey block
-        mesh.update()
-        mesh.insertKey()
-        mesh.key.blocks[-1].name=name
-
-        # set ipo curve
-        icu=ipo.addCurve(name)
-        icu.interpolation = Blender.IpoCurve.InterpTypes.LINEAR
-        icu.append( (0.0, 0.0) )
-        
-        # restore
-        for mv, v in zip(mesh.verts, baseblock.getData()):
-            mv.co[0] = v[0]
-            mv.co[1] = v[1]
-            mv.co[2] = v[2]
-        mesh.update()
-
-
-def run(filename):
-    """
-    @param filename
-    """
-    filename=filename.decode(FS_ENCODING)
-    tex_dir=os.path.dirname(filename)
-
-    # progress
-    progress_start('pmd_import')
-
-    # load pmd
-    progress_set('load %s' % filename, 0.0)
-
-    import locale
-    locale.setlocale(locale.LC_ALL, '')
-
-    l=pmd.IO()
-    if not l.read(filename.encode('cp932')):
-        print "fail to load %s" % filename
-        return
-    progress_set('loaded %s' % filename, 0.1)
-
-    # set object mode
-    mode_edit = Blender.Window.EditMode() 
-    if mode_edit: 
-        Blender.Window.EditMode(0)
-        
-    scene = bpy.data.scenes.active
-
-    # import objects container
-    root=scene.objects.new("Empty")
-    root.setName(l.english_model_name)
-
-    # import mesh
-    mesh_objects=importMesh(scene, l, tex_dir)
-    root.makeParent(mesh_objects)
-
-    # import armature
-    armature_object=importArmature(scene, l)
-    if armature_object:
-        armature = armature_object.getData()
-        armature.drawNames=True
-        root.makeParent([armature_object])
-
-        # add armature modifier
-        for o in mesh_objects:
-            mod=o.modifiers.append(Blender.Modifier.Types.ARMATURE)
-            mod[Blender.Modifier.Settings.OBJECT] = armature_object
-            mod[Blender.Modifier.Settings.ENVELOPES] = False
-            o.makeDisplayList()
-    # redraw
-    scene.update(0)
-
-    # restore edit mode
-    if mode_edit: 
-        Blender.Window.EditMode(1)
-
-    progress_finish()
-    Blender.Window.RedrawAll()
-
-
-if __name__=="__main__":
-    Blender.Window.FileSelector(
-            run, 
-            'Import PMD file', 
-            Blender.sys.makename(ext='.pmd'))
-