OSDN Git Service

implement pmd_import.py.
authorousttrue <ousttrue@gmail.com>
Thu, 6 May 2010 13:18:52 +0000 (22:18 +0900)
committerousttrue <ousttrue@gmail.com>
Thu, 6 May 2010 13:18:52 +0000 (22:18 +0900)
blender24/mqo_export.py [changed mode: 0755->0644]
blender24/mqo_import.py [changed mode: 0755->0644]
blender24/pmd_export.py [new file with mode: 0644]
blender24/pmd_import.py [new file with mode: 0644]
blender24/vmd_import.py [new file with mode: 0644]
include/pmd.h
src/binary.cpp
src/pmd.cpp
swig/englishmap.py [new file with mode: 0644]
swig/mqo.i
swig/pmd.i

old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
diff --git a/blender24/pmd_export.py b/blender24/pmd_export.py
new file mode 100644 (file)
index 0000000..6bf83e0
--- /dev/null
@@ -0,0 +1,440 @@
+#!BPY
+# coding: utf-8
+"""
+ Name: 'MikuMikuDance model (.pmd)...'
+ Blender: 248
+ Group: 'Export'
+ Tooltip: 'Export PMD file for MikuMikuDance.'
+"""
+__author__= ["ousttrue"]
+__version__= "0.1"
+__url__=()
+__bpydoc__="""
+0.1: 20100318 first implementation.
+"""
+import Blender
+import os
+
+import mmd
+
+if os.path.exists(os.path.dirname(sys.argv[0])+"/utf8"):
+    FS_ENCODING='utf-8'
+else:
+    FS_ENCODING=sys.getfilesystemencoding()
+print FS_ENCODING
+
+FILE_EXT = '.pmd'
+
+
+###############################################################################
+# outlineの木構造からエクスポートするオブジェクトを選び出す。
+# (Blender.Objectがparentしか持たず下っていくことができないため
+# wrapして扱いやすくする)
+###############################################################################
+class Node(object):
+    __slots__=['name', 'children']
+    def __init__(self, name="__scene__"):
+        self.name=name
+        self.children=[]
+
+    def addChild(self, child):
+        self.children.append(child)
+
+    def printTree(self, level=0):
+        print " " * (level*2) + self.name
+        for child in self.children:
+            child.printTree(level+1)
+
+
+class OutlineTree(object):
+    __slots__=["root", "dict"]
+    def __init__(self):
+        self.root=Node()
+        self.dict={}
+
+    def addObject(self, object):
+        # already added
+        if object.name in self.dict:
+            return
+
+        parent=object.getParent()
+        node=Node(object.name)
+        if parent:
+            if not parent.name in self.dict:
+                addNode(self.dict, parent)
+            self.dict[parent.name].addChild(node)
+        else:
+            self.root.addChild(node)
+        self.dict[object.name]=node
+
+    def get(self, name):
+        if name in self.dict:
+            return self.dict[name]
+        else:
+            return None
+
+
+###############################################################################
+# Blenderのメッシュをワンスキンメッシュ化する
+###############################################################################
+def near(x, y, EPSILON=1e-5):
+    d=x-y
+    return d>=-EPSILON and d<=EPSILON
+
+class VertexKey(object):
+    """
+    重複頂点の検索キー
+    """
+    __slots__=[
+            'x', 'y', 'z', # 位置
+            'nx', 'ny', 'nz', # 法線
+            'u', 'v', # uv
+            ]
+
+    def __init__(self, x, y, z, nx, ny, nz, u, v):
+        self.x=x
+        self.y=y
+        self.z=z
+        self.nx=nx
+        self.ny=ny
+        self.nz=nz
+        self.u=u
+        self.v=v
+
+    def __hash__(self):
+        return int((self.x+self.y+self.z+self.nx+self.ny+self.nz+self.u+self.v)*100)
+
+    def __eq__(self, rhs):
+        return near(self.x, rhs.x) and near(self.y, rhs.y) and near(self.z, rhs.z) and near(self.nx, rhs.nx) and near(self.ny, rhs.ny) and near(self.nz, rhs.nz) and near(self.u, rhs.u) and near(self.v, rhs.v)
+
+
+class VertexArray(object):
+    """
+    頂点配列
+    """
+    def __init__(self):
+        # マテリアル毎に分割したインデックス配列
+        self.indexArrays={}
+        # 頂点属性
+        self.vertices=[]
+        self.normals=[]
+        self.uvs=[]
+        # skinning属性
+        self.b0=[]
+        self.b1=[]
+        self.weight=[]
+
+        self.vertexMap={}
+
+    def __str__(self):
+        return "<VertexArray %d vertices, %d indexArrays>" % (
+                len(self.vertices), len(self.indexArrays))
+
+    def getIndex(self, pos, normal, uv, b0, b1, weight0):
+        """
+        頂点属性からその頂点のインデックスを得る
+        """
+        key=VertexKey(
+                pos[0], pos[1], pos[2],
+                normal[0], normal[1], normal[2],
+                uv[0], uv[1])
+        if not key in self.vertexMap:
+            self.vertexMap[key]=len(self.vertices)
+            self.vertices.append((pos.x, pos.y, pos.z))
+            self.normals.append((normal.x, normal.y, normal.z))
+            self.uvs.append((uv.x, uv.y))
+            # ToDo
+            self.b0.append(b0)
+            self.b1.append(b1)
+            self.weight.append(weight0)
+        return self.vertexMap[key]
+
+    def addTriangle(self,
+            material,
+            pos0, pos1, pos2,
+            n0, n1, n2,
+            uv0, uv1, uv2,
+            b0_0, b0_1, b0_2,
+            b1_0, b1_1, b1_2,
+            weight0, weight1, weight2
+            ):
+        if not material in self.indexArrays:
+            self.indexArrays[material]=[]
+
+        index0=self.getIndex(pos0, n0, uv0, b0_0, b1_0, weight0)
+        index1=self.getIndex(pos1, n1, uv1, b0_1, b1_1, weight1)
+        index2=self.getIndex(pos2, n2, uv2, b0_2, b1_2, weight2)
+
+        self.indexArrays[material]+=[index0, index1, index2]
+
+
+class OneSkinMesh(object):
+    __slots__=['armatureObj', 'vertexArray']
+    def __init__(self):
+        self.armatureObj=None
+        self.vertexArray=VertexArray()
+
+    def create(self, node):
+        obj=Blender.Object.Get(node.name)
+
+        type=obj.getType()
+        if type=='Mesh':
+            self.addMesh(obj)
+
+        for child in node.children:
+            self.create(child)
+
+    def addMesh(self, obj):
+        if obj.restrictDisplay:
+            return
+
+        if len(obj.getData(mesh=True).verts)==0:
+            return
+
+        print("export", obj.name)
+
+        # search modifier
+        for m in obj.modifiers:
+            if m.name=="Armature":
+                armatureObj=m[Blender.Modifier.Settings.OBJECT]
+                if not self.armatureObj:
+                    self.armatureObj=armatureObj
+                elif self.armatureObj!=armatureObj:
+                    print "warning! found multiple armature. ignored.", armatureObj.name
+
+        # bone weight
+        mesh=obj.getData(mesh=True)
+        weightMap={}
+        secondWeightMap={}
+        for name in mesh.getVertGroupNames():
+            for i, w in mesh.getVertsFromGroup(name, 1):
+                if w>0:
+                    if i in weightMap:
+                        if i in secondWeightMap:
+                            # 上位2つのweightを採用する
+                            if w<secondWeightMap[i]:
+                                pass
+                            elif w<weightMap[i]:
+                                # 2つ目を入れ替え
+                                secondWeightMap[i]=(name, w)
+                            else:
+                                # 1つ目を入れ替え
+                                weightMap[i]=(name, w)
+                        else:
+                            if w>weightMap[i][1]:
+                                # 多い方をweightMapに
+                                secondWeightMap[i]=weightMap[i]
+                                weightMap[i]=(name, w)
+                            else:
+                                secondWeightMap[i]=(name, w)
+                    else:
+                        weightMap[i]=(name, w)
+
+        # 合計値が1になるようにする
+        for i in xrange(len(mesh.verts)):
+        #for i, name_weight in weightMap.items():
+            if i in secondWeightMap:
+                secondWeightMap[i]=(secondWeightMap[i][0], 1.0-weightMap[i][1])
+            elif i in weightMap:
+                weightMap[i]=(weightMap[i][0], 1.0)
+                secondWeightMap[i]=("", 0)
+            else:
+                print "no weight vertex"
+                weightMap[i]=("", 0)
+                secondWeightMap[i]=("", 0)
+                
+
+        ############################################################
+        # faces
+        # 新たにメッシュを生成する
+        ############################################################
+        mesh=Blender.Mesh.New()
+        # not applied modifiers
+        mesh.getFromObject(obj.name, 1)
+        # apply object transform
+        mesh.transform(obj.getMatrix())
+        if len(mesh.verts)==0:
+            return
+
+        for face in mesh.faces:
+            faceVertexCount=len(face.v)
+            material=mesh.materials[face.mat]
+            if faceVertexCount==3:
+                v0=face.v[0]
+                v1=face.v[1]
+                v2=face.v[2]
+                # triangle
+                self.vertexArray.addTriangle(
+                        material.name,
+                        v0.co, v1.co, v2.co,
+                        v0.no, v1.no, v2.no,
+                        face.uv[0], face.uv[1], face.uv[2],
+                        weightMap[v0.index][0],
+                        weightMap[v1.index][0],
+                        weightMap[v2.index][0],
+                        secondWeightMap[v0.index][0],
+                        secondWeightMap[v1.index][0],
+                        secondWeightMap[v2.index][0],
+                        weightMap[v0.index][1],
+                        weightMap[v1.index][1],
+                        weightMap[v2.index][1]
+                        )
+            elif faceVertexCount==4:
+                v0=face.v[0]
+                v1=face.v[1]
+                v2=face.v[2]
+                v3=face.v[3]
+                # quadrangle
+                self.vertexArray.addTriangle(
+                        material.name,
+                        v0.co, v1.co, v2.co,
+                        v0.no, v1.no, v2.no,
+                        face.uv[0], face.uv[1], face.uv[2],
+                        weightMap[v0.index][0],
+                        weightMap[v1.index][0],
+                        weightMap[v2.index][0],
+                        secondWeightMap[v0.index][0],
+                        secondWeightMap[v1.index][0],
+                        secondWeightMap[v2.index][0],
+                        weightMap[v0.index][1],
+                        weightMap[v1.index][1],
+                        weightMap[v2.index][1]
+                        )
+                self.vertexArray.addTriangle(
+                        material.name,
+                        v2.co, v3.co, v0.co,
+                        v2.no, v3.no, v0.no,
+                        face.uv[2], face.uv[3], face.uv[0],
+                        weightMap[v2.index][0],
+                        weightMap[v3.index][0],
+                        weightMap[v0.index][0],
+                        secondWeightMap[v2.index][0],
+                        secondWeightMap[v3.index][0],
+                        secondWeightMap[v0.index][0],
+                        weightMap[v2.index][1],
+                        weightMap[v3.index][1],
+                        weightMap[v0.index][1]
+                        )
+
+
+class BoneBuilder(object):
+    __slots__=['bones', 'boneMap']
+    def __init__(self):
+        self.bones=[]
+        self.boneMap={}
+
+    def build(self, armatureObj):
+        if armatureObj:
+            armature=armatureObj.getData()
+            for b in armature.bones.values():
+                if not b.parent:
+                    # root bone
+                    bone=mmd.createBone(b.name, 0)
+                    self.addBone(bone)
+                    self.getBone(bone, b)
+
+    def getBone(self, parent, b):
+        if len(b.children)==0:
+            return
+
+        for i, c in enumerate(b.children):
+            bone=mmd.createBone(c.name, 0)
+            self.addBone(bone)
+            if parent:
+                bone.parentIndex=parent.index
+                if i==0:
+                    parent.tailIndex=bone.index
+            pos=c.head['ARMATURESPACE']
+            # convert to right-handed z-up to len-handed y-up
+            bone.pos=(pos.x, pos.z, pos.y)
+            self.getBone(bone, c)
+
+    def addBone(self, bone):
+        bone.index=len(self.bones)
+        self.bones.append(bone)
+        self.boneMap[bone.name]=bone.index
+
+
+###############################################################################
+# エクスポータ
+###############################################################################
+def export_pmd(filename):
+    filename=filename.decode(FS_ENCODING)
+    if not filename.lower().endswith(FILE_EXT):
+        filename += FILE_EXT
+    print "## pmd exporter ##", filename
+
+    Blender.Window.WaitCursor(1)
+    t = Blender.sys.time()
+
+    # parse scene
+    scene=Blender.Scene.GetCurrent()
+    tree=OutlineTree()
+    for object in scene.objects:
+        tree.addObject(object)
+
+    # 出力準備
+    mesh=OneSkinMesh()
+    mesh.create(tree.get(scene.objects.active.name))
+
+    # setup pmd
+    pmd=mmd.PMDLoader()
+    pmd.model_name="blender export"
+    pmd.comment="blender export"
+
+    # bones
+    builder=BoneBuilder()
+    builder.build(mesh.armatureObj)
+    for b in builder.bones:
+        pmd.bones.append(b)
+
+    # 頂点
+    vArray=mesh.vertexArray
+    for pos, normal, uv, b0, b1, weight  in zip(
+            vArray.vertices, vArray.normals, vArray.uvs,
+            vArray.b0, vArray.b1, vArray.weight):
+        # convert right-handed z-up to left-handed y-up
+        v=mmd.Vertex(
+            pos[0], pos[2], pos[1],
+            normal[0], normal[2], normal[1],
+            uv[0], uv[1],
+            builder.boneMap[b0] if b0 in builder.boneMap else 0,
+            builder.boneMap[b1] if b1 in builder.boneMap else 0,
+            int(100*weight), 
+            0 # edge flag, 0: enable edge, 1: not edge
+            )
+        pmd.vertices.append(v)
+
+    for m, indices in vArray.indexArrays.items():
+        material=Blender.Material.Get(m)
+        # マテリアル
+        material=mmd.Material(
+                material.R, material.G, material.B, material.alpha,
+                material.spec, material.specR, material.specG, material.specB,
+                0, 0, 0
+                #material.amb, material.amb, material.amb
+                )
+        material.vertex_count=len(indices)
+        pmd.materials.append(material)
+        # 面
+        for i in xrange(0, len(indices), 3):
+            #pmd.faces.append(mmd.Face(indices[i], indices[i+1], indices[i+2]))
+            pmd.faces.append(mmd.Face(indices[i+2], indices[i+1], indices[i]))
+
+    # 書き込み
+    if not pmd.write(filename):
+        return
+
+    # clean up
+    print 'My Script finished in %.2f seconds' % (Blender.sys.time()-t)
+    Blender.Redraw()
+    Blender.Window.WaitCursor(0)
+    print
+
+
+if __name__=="__main__":
+    Blender.Window.FileSelector(
+            export_pmd,
+            'Export Metasequoia PMD',
+            Blender.sys.makename(ext=FILE_EXT))
+
diff --git a/blender24/pmd_import.py b/blender24/pmd_import.py
new file mode 100644 (file)
index 0000000..04820a5
--- /dev/null
@@ -0,0 +1,552 @@
+#!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.vertices:
+        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.vertices, 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.vertices):
+        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'))
+
diff --git a/blender24/vmd_import.py b/blender24/vmd_import.py
new file mode 100644 (file)
index 0000000..bc14309
--- /dev/null
@@ -0,0 +1,279 @@
+#!BPY
+# coding: utf-8
+""" 
+Name: 'MikuMikuDance motion and shape (.vmd)...'
+Blender: 248
+Group: 'Import'
+Tooltip: 'Import motion from MikuMikuDance motion file (.vmd)'
+"""
+__author__= 'ousttrue'
+__url__ = ["http://gunload.web.fc2.com/blender/"]
+__version__= '0.5 2010/04/16'
+__bpydoc__= '''\
+VMD Importer
+
+This script imports a vmd file into Blender.
+
+0.1 2009/11/23
+0.2 2009/12/09 implement shape key
+0.3 2010/03/05 use english name
+0.4 2010/04/05 fix slerp
+0.5 2010/04/16 add progress
+'''
+import Blender
+import os
+import sys
+import math
+import mmd
+
+
+if os.path.exists(os.path.dirname(sys.argv[0])+"/utf8"):
+    FS_ENCODING='utf-8'
+else:
+    FS_ENCODING=sys.getfilesystemencoding()
+print FS_ENCODING
+
+
+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.01):
+    global progressBar
+    progressBar.advance(message, progress)
+
+def progress_set(message, progress):
+    global progressBar
+    progressBar.set(message, progress)
+
+
+EPSILON=1e-5
+THRESHOLD=-0.85
+
+
+def ToDegree(x):
+    return x/math.pi * 180.0
+
+
+def clampDegree(d):
+    return d % 360
+
+
+def multQuat(l, r):
+    q=Blender.Mathutils.Quaternion(l.w*r.w-(l.x*r.x+l.y*r.y+l.z*r.z), 0, 0, 0)
+    q.x=l.w*r.x+r.w*l.x+l.y*r.z-l.z*r.y
+    q.y=l.w*r.y+r.w*l.y+l.z*r.x-l.x*r.z
+    q.z=l.w*r.z+r.w*l.z+l.x*r.y-l.y*r.x
+    return q
+
+
+def import_motion_key(l, o, progressCount):
+    print 'import_motion_key: %s' % o.name
+    act = o.getAction()
+    if not act: # Add a pose action if we dont have one
+        act = Armature.NLA.NewAction()
+        act.setActive(o)
+    
+    armature = o.data
+    pose = o.getPose()
+    not_in_map={}
+    not_found={}
+    counter=0
+    for n, motions in l.motions.items():
+        boneName=mmd.getEnglishBoneName(n)
+        try:
+            poseBone=pose.bones[boneName]
+            bone=armature.bones[boneName]
+            # rot
+            armRotate=bone.matrix['ARMATURESPACE'].rotationPart()
+            # quat
+            armRotateQuaternion=armRotate.toQuat()
+            if armRotateQuaternion.w<0:
+                armRotateQuaternion.w=-armRotateQuaternion.w
+                armRotateQuaternion.x=-armRotateQuaternion.x
+                armRotateQuaternion.y=-armRotateQuaternion.y
+                armRotateQuaternion.z=-armRotateQuaternion.z
+
+            # inv
+            armRotateInv=Blender.Mathutils.Matrix(armRotate).transpose()
+            # quat
+            armRotateInvQuaternion=armRotateInv.toQuat()
+            if armRotateInvQuaternion.w<0:
+                armRotateInvQuaternion.w=-armRotateInvQuaternion.w
+                armRotateInvQuaternion.x=-armRotateInvQuaternion.x
+                armRotateInvQuaternion.y=-armRotateInvQuaternion.y
+                armRotateInvQuaternion.z=-armRotateInvQuaternion.z
+
+            reverseFlag=False
+            lastQ=None
+
+            for m in motions:
+                ####################
+                # rotation
+                ####################
+                if lastQ and lastQ.dot(m.q)<0:
+                    reverseFlag=not reverseFlag
+                lastQ=m.q
+
+                # convert left-handed y-up to right-handed z-up
+                if reverseFlag:
+                    # reverse quaternion for slerp
+                    q=Blender.Mathutils.Quaternion(-m.q.w, 0, 0, 0)
+                    q.x=m.q.x
+                    q.y=m.q.z
+                    q.z=m.q.y
+                else:
+                    q=Blender.Mathutils.Quaternion(m.q.w, 0, 0, 0)
+                    q.x=-m.q.x
+                    q.y=-m.q.z
+                    q.z=-m.q.y
+
+                poseBone.quat=(
+                        multQuat(armRotateInvQuaternion, 
+                            multQuat(q, armRotateQuaternion)))
+
+                ####################
+                # location
+                ####################
+                poseBone.loc = Blender.Mathutils.Vector(
+                        float(m.pos.x), float(m.pos.z), float(m.pos.y))
+
+                # insert
+                poseBone.insertKey(o, m.frame, 
+                        [Blender.Object.Pose.LOC, Blender.Object.Pose.ROT],
+                        1)
+
+                counter+=1
+                if counter % progressCount==0:
+                    progress_print("")
+
+        except KeyError, msg:
+            not_found[boneName]=True
+            continue
+            
+    print "bone not exists"
+    for name in not_found.keys():
+        print name
+
+
+def IPO_CURVE_get_or_create(ipo, name):
+    for c in ipo:
+        if c.name == name:
+            return c
+    print name, type(name)
+    return ipo.addCurve(name)
+
+
+def import_shape_key(l, mesh, progressCount):
+    print 'import_shape_key: %s' % mesh.name
+    key = mesh.getData().key
+    if key is None:
+        Draw.PupMenu('selecting mesh not has a Key')
+        return
+    # get or create IPO  
+    ipo = key.getIpo()
+    if ipo == None:
+        ipo = Blender.Ipo.New("Key", "ShapeKey")
+        key.ipo = ipo
+
+    # insert shape keys
+    counter=0
+    for n, shapes in l.shapes.items():
+        name=mmd.getEnglishSkinName(n)
+        try:
+            curve=IPO_CURVE_get_or_create(ipo, name)
+        except NameError, msg:
+            print NameError, msg
+            continue
+        curve.interpolation = Blender.IpoCurve.InterpTypes.LINEAR
+        for shape in shapes:
+            curve[shape.frame]=shape.ratio
+
+            counter+=1
+            if counter % progressCount==0:
+                progress_print("")
+
+
+def run(filename):
+    filename=filename.decode(FS_ENCODING)
+
+    # progress
+    progress_start('vmd_import')
+
+    # load pmd
+    progress_set('load %s' % filename, 0.0)
+    l=mmd.load_vmd(filename)
+    if not l:
+        print "failt to load", filename
+        return
+    progress_set('loaded %s' % filename, 1.0)
+
+    scene=Blender.Scene.GetCurrent()
+
+    # for progress
+    armtureCount=0
+    shapeCount=0
+    for o in scene.objects.selected:
+        if o.type=='Armature':
+            armtureCount+=1
+        elif o.type=='Mesh':
+            shapeCount+=1
+    keyCount=armtureCount*l.getMotionCount()+shapeCount*l.getShapeCount()
+    progressCount=int(keyCount/100)
+    print keyCount, progressCount
+
+    # import
+    for o in scene.objects.selected:
+        if o.type=='Armature':
+            import_motion_key(l, o, progressCount)
+        elif o.type=='Mesh':
+            import_shape_key(l, o, progressCount)
+
+    # set end frame
+    scene.getRenderingContext().eFrame = l.last_frame
+    print l.last_frame
+
+    progress_finish()
+
+
+if __name__=="__main__":
+    if 0<len([o for o in Blender.Scene.GetCurrent().objects.selected if 
+        o.type=='Armature' or o.type=='Mesh']):
+        Blender.Window.FileSelector(
+                run, 
+                'Import VMD motion', 
+                Blender.sys.makename(ext='.vmd'))
+    else:
+        Blender.Draw.PupMenu('select target armature and mesh objects.')
+
index 840a675..a402015 100644 (file)
@@ -160,6 +160,16 @@ struct Bone
        unsigned short ik_index;
        // \83{\81[\83\93\8dÀ\95W
        Vector3 pos;
+       //! \89p\8cê\96¼
+       char english_name[20];
+       //! \83{\81[\83\93\8aK\91w\8d\\92z\97p
+       Bone* parent;
+       Vector3 tail;
+       std::vector<Bone*> children;
+
+       Bone()
+               : parent(0)
+               {}
 };
 inline std::ostream &operator<<(std::ostream &os,
                const Bone &rhs)
@@ -228,6 +238,8 @@ struct Morph
        std::vector<unsigned int> indices;
        //! \88Ú\93®\97Ê
        std::vector<Vector3> pos_list;
+       //! \89p\8cê\96¼
+       char english_name[20];
 };
 inline std::ostream &operator<<(std::ostream &os, const Morph &rhs)
 {
@@ -328,7 +340,7 @@ struct IO
        char comment[256];
        std::vector<Vertex> vertices;
        std::vector<unsigned short> indices;
-       std::vector<Material> materials;
+       std::vector<Material*> materials;
        std::vector<Bone> bones;
        std::vector<IK> ik_list;
        std::vector<Morph> morph_list;
@@ -337,7 +349,11 @@ struct IO
        std::vector<RigidBody> rigidbodies;
        std::vector<Constraint> constraints;
 
+       char english_model_name[20];
+       char english_comment[256];
+
        IO();
+       ~IO();
        bool read(binary::IReader &reader);
        bool read(const char *path);
        bool write(std::ostream &os);
index 7e6ec6c..5a0f4ba 100644 (file)
@@ -72,8 +72,31 @@ bool MemoryReader::isEnd()const
 }
 
 ///////////////////////////////////////////////////////////////////////////////
+static void readALL_(FILE *fp, std::vector<char> &buf)
+{
+       int iRet = fseek(fp, 0L, SEEK_END);
+       if(iRet!=0){
+               return;
+       }
+
+       fpos_t pos;
+       iRet = fgetpos(fp, &pos);
+       if(iRet != 0){
+               return;
+       }
+
+       iRet = fseek(fp, 0L, SEEK_SET);
+       if(iRet != 0){
+               return;
+       }
+
+       buf.resize((long)pos);
+       fread(&buf[0], (long)pos, 1, fp);
+}
+
 void readAll(const char *path, std::vector<char> &buf)
 {
+       /*
        std::ifstream io(path, std::ios::binary);
        if(!io){
                return;
@@ -84,8 +107,14 @@ void readAll(const char *path, std::vector<char> &buf)
        io.seekg(0, std::fstream::beg);
        unsigned int begPos = io.tellg();
        unsigned int size = eofPos - begPos;
-       buf.resize(size);
        io.read(&buf[0], buf.size());
+       */
+
+       FILE* fp = fopen(path, "rb");
+       if(fp){
+               readALL_(fp, buf);
+               fclose(fp);
+       }
 }
 
 } // namespace binary
index 8618d53..6d0a95d 100644 (file)
@@ -266,7 +266,8 @@ private:
        {
                int count=io_.morph_list.size()-1;
                for(int i=0; i<count; ++i){
-                       std::string english_morph_name=reader_.getString(20);
+                       text::copyStringAndFillZero(
+                                       io_.morph_list[i].english_name, reader_.getString(20));
                }
                return true;
        }
@@ -274,15 +275,18 @@ private:
        bool parseEnglishBone()
        {
                for(size_t i=0; i<io_.bones.size(); ++i){
-                       std::string english_bone_name=reader_.getString(20);
+                       text::copyStringAndFillZero(
+                                       io_.bones[i].english_name, reader_.getString(20));
                }
                return true;
        }
 
        bool parseEnglishName()
        {
-               std::string english_mdoel_name=reader_.getString(20);
-               std::string english_comment=reader_.getString(256);
+               text::copyStringAndFillZero(io_.english_model_name, 
+                               reader_.getString(20));
+               text::copyStringAndFillZero(io_.english_comment, 
+                               reader_.getString(256));
                return true;
        }
 
@@ -349,8 +353,8 @@ private:
        {
                unsigned int count=reader_.getUint();
                for(unsigned int i=0; i<count; ++i){
-                       io_.materials.push_back(Material());
-                       read(reader_, io_.materials.back());
+                       io_.materials.push_back(new Material());
+                       read(reader_, *io_.materials.back());
                }
                return true;
        }
@@ -400,6 +404,14 @@ IO::IO()
 : version(0)
 {}
 
+IO::~IO()
+{
+       for(size_t i=0; i<materials.size(); ++i){
+               delete materials[i];
+       }
+       materials.clear();
+}
+
 bool IO::read(binary::IReader &input)
 {
        Impl impl(*this, input);
@@ -408,7 +420,7 @@ bool IO::read(binary::IReader &input)
        }
 
        ////////////////////////////////////////////////////////////
-       // validation
+       // post process
        ////////////////////////////////////////////////////////////
        if(!morph_list.empty()){
                // validate morph
@@ -424,6 +436,19 @@ bool IO::read(binary::IReader &input)
                        assert(m.type!=MORPH_BASE);
                }
        }
+       ////////////////////////////////////////////////////////////
+       // setup bone
+       ////////////////////////////////////////////////////////////
+       for(size_t i=0; i<bones.size(); ++i){
+               Bone &bone=bones[i];
+               if(bone.parent_index!=0xFFFF){
+                       bone.parent=&bones[bone.parent_index];
+                       bone.parent->children.push_back(&bone);
+               }
+               if(bone.tail_index!=0xFFFF){
+                       bone.tail=bones[bone.tail_index].pos;
+               }
+       }
 
        return true;
 }
diff --git a/swig/englishmap.py b/swig/englishmap.py
new file mode 100644 (file)
index 0000000..4226ccd
--- /dev/null
@@ -0,0 +1,192 @@
+#!/usr/bin/env python
+# coding: utf8
+
+###############################################################################
+# 日本語名との変換マップ
+###############################################################################
+boneMap={
+"center":u"センター",
+"upper body":u"上半身",
+"neck":u"首",
+"head":u"頭",
+"eye_L":u"左目",
+"eye_R":u"右目",
+"necktie1":u"ネクタイ1",
+"necktie2":u"ネクタイ2",
+"necktie3":u"ネクタイ3",
+"lower body":u"下半身",
+"waist accessory":u"腰飾り",
+"hair1_L":u"左髪1",
+"hair2_L":u"左髪2",
+"hair3_L":u"左髪3",
+"hair4_L":u"左髪4",
+"hair5_L":u"左髪5",
+"hair6_L":u"左髪6",
+"shoulder_L":u"左肩",
+"arm_L":u"左腕",
+"arm twist_L":u"左腕捩",
+"elbow_L":u"左ひじ",
+"wrist twist_L":u"左手捩",
+"wrist_L":u"左手首",
+"sleeve_L":u"左袖",
+"thumb1_L":u"左親指1",
+"thumb2_L":u"左親指2",
+"fore1_L":u"左人指1",
+"fore2_L":u"左人指2",
+"fore3_L":u"左人指3",
+"middle1_L":u"左中指1",
+"middle2_L":u"左中指2",
+"middle3_L":u"左中指3",
+"third1_L":u"左薬指1",
+"third2_L":u"左薬指2",
+"third3_L":u"左薬指3",
+"little1_L":u"左小指1",
+"little2_L":u"左小指2",
+"little3_L":u"左小指3",
+"front skirt_L":u"左スカート前",
+"back skirt_L":u"左スカート後",
+"leg_L":u"左足",
+"knee_L":u"左ひざ",
+"ankle_L":u"左足首",
+"hair1_R":u"右髪1",
+"hair2_R":u"右髪2",
+"hair3_R":u"右髪3",
+"hair4_R":u"右髪4",
+"hair5_R":u"右髪5",
+"hair6_R":u"右髪6",
+"shoulder_R":u"右肩",
+"arm_R":u"右腕",
+"arm twist_R":u"右腕捩",
+"elbow_R":u"右ひじ",
+"wrist twist_R":u"右手捩",
+"wrist_R":u"右手首",
+"sleeve_R":u"右袖",
+"thumb1_R":u"右親指1",
+"thumb2_R":u"右親指2",
+"fore1_R":u"右人指1",
+"fore2_R":u"右人指2",
+"fore3_R":u"右人指3",
+"middle1_R":u"右中指1",
+"middle2_R":u"右中指2",
+"middle3_R":u"右中指3",
+"third1_R":u"右薬指1",
+"third2_R":u"右薬指2",
+"third3_R":u"右薬指3",
+"little1_R":u"右小指1",
+"little2_R":u"右小指2",
+"little3_R":u"右小指3",
+"front skirt_R":u"右スカート前",
+"back skirt_R":u"右スカート後",
+"leg_R":u"右足",
+"knee_R":u"右ひざ",
+"ankle_R":u"右足首",
+"eyes":u"両目",
+"front hair1":u"前髪1",
+"front hair2":u"前髪2",
+"front hair3":u"前髪3",
+"eyelight_L":u"左目光",
+"eyelight_R":u"右目光",
+"necktie4":u"ネクタイ4",
+"hair7_L":u"左髪7",
+"hair7_R":u"右髪7",
+"toe_L":u"左つま先",
+"toe_R":u"右つま先",
+"necktie IK":u"ネクタイIK",
+"hair IK_L":u"左髪IK",
+"hair IK_R":u"右髪IK",
+"leg IK_L":u"左足IK",
+"leg IK_R":u"右足IK",
+"toe IK_L":u"左つま先IK",
+"toe IK_R":u"右つま先IK",
+"bone093":u"下半身先",
+"bone094":u"頭先",
+"bone095":u"左目先",
+"bone096":u"右目先",
+"bone097":u"腰飾り先",
+"bone098":u"左袖先",
+"bone099":u"左手先",
+"bone100":u"左親指先",
+"bone101":u"左人差指先",
+"bone102":u"左中指先",
+"bone103":u"左薬指先",
+"bone104":u"左小指先",
+"bone105":u"左スカート前先",
+"bone106":u"左スカート後先",
+"bone107":u"右袖先",
+"bone108":u"右手先",
+"bone109":u"右親指先",
+"bone110":u"右人差指先",
+"bone111":u"右中指先",
+"bone112":u"右薬指先",
+"bone113":u"右小指先",
+"bone114":u"右スカート前先",
+"bone115":u"右スカート後先",
+"bone116":u"センター先",
+"bone117":u"両目先",
+"bone118":u"ネクタイIK先",
+"bone119":u"左髪IK先",
+"bone120":u"右髪IK先",
+"bone121":u"左足IK先",
+"bone122":u"右足IK先",
+"bone123":u"左つま先IK先",
+"bone124":u"右つま先IK先",
+"bone125":u"前髪1先",
+"bone126":u"前髪2先",
+"bone127":u"前髪3先",
+"bone128":u"左目光先",
+"bone129":u"右目光先",
+"bone130":u"左腕捩先",
+"bone131":u"左手捩先",
+"bone132":u"右腕捩先",
+"bone133":u"右手捩先",
+"bone134":u"左腕捩1",
+"bone135":u"左腕捩2",
+"bone136":u"左腕捩3",
+"bone137":u"右腕捩1",
+"bone138":u"右腕捩2",
+"bone139":u"右腕捩3",
+}
+def getEnglishBoneName(name):
+    for k, v in boneMap.items():
+        if v==name:
+            return k
+
+
+skinMap={
+"skin000":u"base",
+"serious":u"真面目",
+"sadness":u"困る",
+"cheerful":u"にこり",
+"anger":u"怒り",
+"go up":u"上",
+"go down":u"下",
+"blink":u"まばたき",
+"smile":u"笑い",
+"wink":u"ウィンク",
+"wink2":u"ウィンク2",
+"wink_R":u"ウィンク右",
+"wink2_R":u"ウィンク2右",
+"close><":u"はぅ",
+"calm":u"なごみ",
+"surprise":u"びっくり",
+"doubt":u"じと目",
+"confuse":u"なぬ!",
+"pupil":u"瞳小",
+"a":u"あ",
+"i":u"い",
+"u":u"う",
+"o":u"お",
+"triangle":u"▲",
+"regret":u"∧",
+"omega":u"ω",
+"omegabox":u"ω□",
+"fool":u"はんっ!",
+"tongue":u"ぺろっ",
+"e-":u"えー",
+"grin":u"にやり",
+}
+def getEnglishSkinName(name):
+    for k, v in skinMap.items():
+        if v==name:
+            return k
+
index 2620685..8a23f73 100644 (file)
@@ -6,9 +6,9 @@ using namespace mqo;
 %}
 %include "std_string.i"
 %include "std_vector.i"
+%include "../include/mqo.h"
 %include "../include/la.h"
 %include "../include/color.h"
-%include "../include/mqo.h"
 
 %template(MaterialVector) std::vector<meshio::mqo::Material>;
 %template(ObjectVector) std::vector<meshio::mqo::Object>;
index 7fd2b74..6bdfd28 100644 (file)
@@ -2,6 +2,22 @@
 %{
 #include <pmd.h>
 using namespace meshio;
+using namespace pmd;
 %}
+%include "std_vector.i"
+%include "../include/color.h"
+%include "../include/la.h"
 %include "../include/pmd.h"
 
+%template(VertexVector) std::vector<meshio::pmd::Vertex>;
+%template(MaterialVector) std::vector<meshio::pmd::Material*>;
+%template(BoneVector) std::vector<meshio::pmd::Bone>;
+%template(IKVector) std::vector<meshio::pmd::IK>;
+%template(MorphVector) std::vector<meshio::pmd::Morph>;
+%template(RigidBodyVector) std::vector<meshio::pmd::RigidBody>;
+%template(ConstraintVector) std::vector<meshio::pmd::Constraint>;
+%template(UintVector) std::vector<unsigned int>;
+%template(UshortVector) std::vector<unsigned short>;
+%template(Vector3Vector) std::vector<meshio::pmd::Vector3>;
+%template(PBoneVector) std::vector<meshio::pmd::Bone*>;
+