--- /dev/null
+#!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))
+
--- /dev/null
+#!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'))
+
--- /dev/null
+#!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.')
+
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)
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)
{
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;
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);
}
///////////////////////////////////////////////////////////////////////////////
+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;
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
{
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;
}
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;
}
{
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;
}
: 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);
}
////////////////////////////////////////////////////////////
- // validation
+ // post process
////////////////////////////////////////////////////////////
if(!morph_list.empty()){
// validate morph
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;
}
--- /dev/null
+#!/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
+
%}
%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>;
%{
#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*>;
+