#"T:/Blender/1340_Release/Release/.blender/scripts/io",
"T:/Blender/bf-blender/build2.5git/bin/Release/2.53/scripts/addons",
"T:/Blender/blender-2.53-beta-windows32/2.53/scripts/addons",
- "io",
+ "addons",
]
def copy24(src):
+++ /dev/null
-#!BPY\r
-# coding: utf-8\r
-\r
-"""\r
-Name: 'Metasequoia (.mqo)...'\r
-Blender: 245\r
-Group: 'Export'\r
-Tooltip: 'Save as Metasequoia MQO File'\r
-"""\r
-__author__= 'ousttrue'\r
-__url__ = ["http://gunload.web.fc2.com/blender/"]\r
-__version__= '1.0 2008/01/28'\r
-__bpydoc__ = """\\r
-This script is an exporter to MQO file format.\r
-\r
-Usage:\r
-\r
-Run this script from "File->Export" menu.\r
-\r
-0.1 20080128:\r
-0.2 20100518: refactoring.\r
-"""\r
-\r
-import Blender\r
-import os\r
-import sys\r
-\r
-\r
-EXTENSION = u'.mqo'\r
-\r
-\r
-# ファイルシステムの文字コード\r
-# 改造版との共用のため\r
-FS_ENCODING=sys.getfilesystemencoding()\r
-if os.path.exists(os.path.dirname(sys.argv[0])+"/utf8"):\r
- INTERNAL_ENCODING='utf-8'\r
-else:\r
- INTERNAL_ENCODING=FS_ENCODING\r
-\r
-\r
-class OutlineNode(object):\r
- __slots__=['o', 'children']\r
- def __init__(self, o):\r
- self.o=o\r
- self.children=[]\r
-\r
-\r
-class ObjectInfo(object):\r
- __slots__=['object', 'depth', 'material_map']\r
- def __init__(self, o, depth):\r
- self.object=o\r
- self.depth=depth\r
- self.material_map={}\r
-\r
-\r
-class MqoExporter(object):\r
- __slots__=["materials", "objects"]\r
- def setup(self, scene):\r
- # 木構造を構築する\r
- object_node_map={}\r
- for o in scene.objects:\r
- object_node_map[o]=OutlineNode(o)\r
- for node in object_node_map.values():\r
- if node.o.parent:\r
- object_node_map[node.o.parent].children.append(node)\r
-\r
- # ルートを得る\r
- root=object_node_map[scene.objects.active]\r
-\r
- # 情報を集める\r
- self.objects=[]\r
- self.materials=[]\r
- if root.o.getType()=='Empty':\r
- for child in root.children:\r
- self.__setup(child)\r
- else:\r
- self.__setup(root)\r
-\r
- def __setup(self, parent, depth=0):\r
- if parent.o.getType()=='Mesh':\r
- info=ObjectInfo(parent.o, depth)\r
- self.objects.append(info)\r
- # set material index\r
- for i, m in enumerate(parent.o.data.materials):\r
- info.material_map[i]=self.__getOrAddMaterial(m)\r
- # recursive\r
- for child in parent.children:\r
- __setup(child, depth+1)\r
- \r
- def __getOrAddMaterial(self, material):\r
- for i, m in enumerate(self.materials):\r
- if m==material:\r
- return i\r
- index=len(self.materials)\r
- self.materials.append(material)\r
- return index\r
-\r
- def write(self, path):\r
- io=open(path, "wb")\r
- self.__write_header(io)\r
- self.__write_scene(io)\r
- print "Writing MaterialChunk"\r
- self.__write_materials(io, os.path.dirname(path))\r
- print "Writing ObjectChunk"\r
- for info in self.objects:\r
- self.__write_object(io, info)\r
- io.write("Eof\r\n")\r
- io.flush()\r
- io.close()\r
-\r
- def __write_header(self, io):\r
- io.write("Metasequoia Document\r\n")\r
- io.write("Format Text Ver 1.0\r\n")\r
- io.write("\r\n")\r
-\r
- def __write_scene(self, io):\r
- print "Writing SceneChunk"\r
- io.write("Scene {\r\n")\r
- io.write("}\r\n")\r
-\r
- def __write_materials(self, io, dirname):\r
- # each material \r
- io.write("Material %d {\r\n" % (len(self.materials)))\r
- for m in self.materials:\r
- texture=""\r
- aplane=""\r
- # texture\r
- for mtex in m.getTextures():\r
- if mtex and mtex.tex and mtex.tex.getImage():\r
- image=mtex.tex.getImage()\r
- if not image:\r
- continue\r
- imagePath=Blender.sys.expandpath(image.getFilename())\r
- if len(dirname) and imagePath.startswith(dirname):\r
- # 相対パスに変換する\r
- imagePath=imagePath[len(dirname)+1:len(imagePath)]\r
- #imagePath=Blender.sys.expandpath(\r
- # imagePath).replace("\\", '/')\r
- if mtex.mtCol:\r
- texture=" tex(\"%s\")" % imagePath\r
- elif mtex.mtAlpha:\r
- aplane=" aplane(\"%s\")" % imagePath\r
- if len(texture):\r
- # textureがある場合は下地を白に\r
- io.write("\"%s\" shader(3) col(1 1 1 1)" % m.name)\r
- else:\r
- # 無い場合はそのまま\r
- io.write("\"%s\" shader(3) col(%f %f %f %f)" % (\r
- m.name, \r
- m.rgbCol[0], m.rgbCol[1], m.rgbCol[2], m.alpha))\r
- io.write(texture)\r
- io.write(aplane)\r
- io.write("\r\n") \r
- # end of chunk\r
- io.write("}\r\n") \r
-\r
- def __write_object(self, io, info, depth=0):\r
- obj=info.object\r
- if obj.getType() != 'Mesh':\r
- return\r
- mesh=Blender.Mesh.New()\r
- dumy = Blender.Object.New("Mesh", "dumy")\r
- # not apply modifiers\r
- mesh.getFromObject(obj.name, 1)\r
- dumy.link(mesh)\r
- # apply matrix\r
- dumy.setMatrix(obj.matrixWorld)\r
- # link\r
- scene=Blender.Scene.GetCurrent()\r
- scene.objects.link(dumy)\r
-\r
- ############################################################\r
- # write\r
- ############################################################\r
- io.write("Object \""+obj.name+"\" {\r\n")\r
-\r
- # 座標系をmqo(right-handed y-up)に変換する\r
- # global matrix\r
- matrix=obj.matrixWorld\r
- # rotate to y-up\r
- matrix*=Blender.Mathutils.RotationMatrix(-90, 4, 'x')\r
- # scale\r
- #matrix*=Blender.Mathutils.ScaleMatrix(SCALING_FACOR, 4)\r
-\r
- # depth\r
- io.write("\tdepth %d\r\n" % depth)\r
-\r
- # mirroring \r
- isMirrorring=False\r
- for mod in obj.modifiers:\r
- if mod.name=="Mirror":\r
- isMirrorring=True\r
- break\r
- if isMirrorring:\r
- io.write("\tmirror 1\r\n")\r
- io.write("\tmirror_axis 1\r\n")\r
-\r
- mesh=Blender.Mesh.New()\r
- ############################################################\r
- # not applied modifiers\r
- ############################################################\r
- mesh.getFromObject(obj.name, 1)\r
-\r
- # vertices\r
- io.write("\tvertex %d {\r\n" % len(mesh.verts))\r
- for vert in mesh.verts:\r
- x, y, z = apply_transform(vert.co, matrix)\r
- io.write("\t\t%f %f %f\r\n" % (x, y, z)) # rotate to y-up\r
- io.write("\t}\r\n")\r
-\r
- # faces\r
- io.write("\tface %d {\r\n" % len(mesh.faces))\r
- for face in mesh.faces:\r
- poly_cnt = len(face.v)\r
- # V\r
- verts =list(face.v)\r
- io.write("\t\t%d V(" % poly_cnt)\r
- for i in reversed(range(poly_cnt)): # reverse normal\r
- io.write("%d " % verts[i].index)\r
- io.write(")")\r
- # mat\r
- if len(mesh.materials):\r
- try:\r
- io.write(" M(%d)" % info.material_map[face.mat])\r
- except:\r
- #print(info.material_map, face.mat)\r
- pass\r
- # UV\r
- if mesh.faceUV:\r
- uv = list(face.uv)\r
- if len(uv)>0:\r
- io.write(" UV(")\r
- # reverse normal\r
- for i in reversed(range(poly_cnt)): \r
- # reverse V\r
- io.write("%f %f " % (uv[i][0], 1.0-uv[i][1])) \r
- io.write(")")\r
- io.write("\r\n")\r
- io.write("\t}\r\n") # end of faces\r
- io.write("}\r\n") # end of object\r
- ############################################################\r
-\r
- # 削除する\r
- scene.objects.unlink(dumy)\r
-\r
-\r
-def export_mqo(fileName):\r
- """\r
- export mqo.\r
- """\r
- fileName=fileName.decode(INTERNAL_ENCODING)\r
-\r
- Blender.Window.WaitCursor(1) \r
- t = Blender.sys.time() \r
-\r
- if not fileName.lower().endswith(EXTENSION):\r
- fileName += EXTENSION\r
- print "mqo exporter: %s" % fileName\r
-\r
- exporter=MqoExporter()\r
-\r
- # 情報収集\r
- exporter.setup(Blender.Scene.GetCurrent())\r
-\r
- # 出力\r
- exporter.write(fileName)\r
-\r
- print 'finished in %.2f seconds' % (Blender.sys.time()-t) \r
- Blender.Redraw()\r
- Blender.Window.WaitCursor(0) \r
- \r
-def apply_transform(vec, matrix):\r
- x, y, z = vec\r
- xloc, yloc, zloc = matrix[3][0], matrix[3][1], matrix[3][2]\r
- return x*matrix[0][0] + y*matrix[1][0] + z*matrix[2][0] + xloc,\\r
- x*matrix[0][1] + y*matrix[1][1] + z*matrix[2][1] + yloc,\\r
- x*matrix[0][2] + y*matrix[1][2] + z*matrix[2][2] + zloc\r
-\r
-\r
-Blender.Window.FileSelector(\r
- export_mqo, \r
- 'Export Metasequoia MQO', \r
- Blender.sys.makename(ext=EXTENSION))\r
-\r
+++ /dev/null
-#!BPY\r
-# coding: utf-8\r
-""" \r
-Name: 'Metasequoia(.mqo)...'\r
-Blender: 245\r
-Group: 'Import'\r
-Tooltip: 'Import from Metasequoia file format (.mqo)'\r
-"""\r
-__author__= 'ousttrue'\r
-__url__ = ["http://gunload.web.fc2.com/blender/"]\r
-__version__= '0.6 2010/05/05'\r
-__bpydoc__= '''\\r
-\r
-MQO Importer\r
-\r
-This script imports a mqo file.\r
-\r
-0.2 20080123: update.\r
-0.3 20091125: modify for linux.\r
-0.4 20100310: rewrite.\r
-0.5 20100311: create armature from mikoto bone.\r
-0.6 20100505: C extension.\r
-'''\r
-\r
-import Blender\r
-from Blender import Mathutils\r
-import bpy\r
-\r
-import os\r
-import sys\r
-import math\r
-\r
-# extension\r
-import meshio.mqo\r
-\r
-\r
-# ファイルシステムの文字コード\r
-# 改造版との共用のため\r
-FS_ENCODING=sys.getfilesystemencoding()\r
-if os.path.exists(os.path.dirname(sys.argv[0])+"/utf8"):\r
- INTERNAL_ENCODING='utf-8'\r
-else:\r
- INTERNAL_ENCODING=FS_ENCODING\r
-\r
-\r
-def has_mikoto(mqo):\r
- return False\r
-\r
-\r
-def create_materials(scene, mqo, directory):\r
- """\r
- create blender materials and renturn material list.\r
- """\r
- materials = []\r
- images = []\r
- for m in mqo.materials:\r
- material = Blender.Material.New(m.getName().encode(INTERNAL_ENCODING))\r
- materials.append(material)\r
-\r
- material.mode |= Blender.Material.Modes.SHADELESS\r
- material.rgbCol = [m.color.r, m.color.g, m.color.b]\r
- material.alpha = m.color.a\r
- material.amb = m.ambient\r
- material.spec = m.specular\r
- material.hard = int(255 * m.power)\r
- if m.texture!="":\r
- texture_path=m.getTexture()\r
-\r
- # load texture image\r
- if os.path.isabs(texture_path):\r
- # absolute\r
- path = texture_path\r
- else:\r
- # relative\r
- path = os.path.join(directory, texture_path)\r
-\r
- # backslash to slash\r
- #path = path.replace('\\', '/')\r
-\r
- # texture\r
- if os.path.exists(path):\r
- image = Blender.Image.Load(path.encode(INTERNAL_ENCODING))\r
- images.append(image)\r
- material.mode = material.mode | Blender.Material.Modes.TEXFACE\r
- tex = Blender.Texture.New(path.encode(INTERNAL_ENCODING))\r
- tex.type = Blender.Texture.Types.IMAGE\r
- tex.image = image\r
- material.setTexture(0, tex, Blender.Texture.TexCo.UV)\r
- else:\r
- print("%s not exits" % path)\r
- \r
- return materials\r
-\r
-\r
-def create_objects(scene, root, mqo, materials):\r
- """\r
- create blender mesh objects.\r
- """\r
- # store hierarchy\r
- stack=[root] \r
-\r
- objects=[]\r
- for o in mqo.objects:\r
- #print "%s:v(%d),f(%d)" % (o.name, len(o.vertices), len(o.faces))\r
- # create mesh\r
- mesh = Blender.Mesh.New()\r
- mesh_object=scene.objects.new(mesh, o.name.encode('utf-8'))\r
-\r
- # add hierarchy\r
- stack_depth=len(stack)-1\r
- print(o.depth, stack_depth)\r
- if o.depth<stack_depth:\r
- for i in range(stack_depth-o.depth):\r
- stack.pop()\r
- stack[-1].makeParent([mesh_object])\r
- stack.append(mesh_object)\r
-\r
- if o.name.startswith('sdef'):\r
- # add sdef object\r
- objects.append(mesh_object)\r
- elif o.name.startswith('anchor'):\r
- #print("hide %s" % o.name)\r
- #mesh_object.restrictDisplay=False\r
- mesh_object.layers=[2]\r
- elif o.name.startswith('bone'):\r
- mesh_object.layers=[2]\r
-\r
- # add vertices\r
- mesh.verts.extend(Mathutils.Vector(0, 0, 0)) # dummy\r
- mesh.verts.extend([(v.x, -v.z, v.y) for v in o.vertices])\r
- # add faces\r
- mesh_faces=[]\r
- for face in o.faces:\r
- face_indices=[]\r
- for i in xrange(face.index_count):\r
- face_indices.append(face.getIndex(i)+1)\r
- mesh_faces.append(face_indices)\r
- #new_faces=mesh.faces.extend([face.indices for face in o.faces], \r
- new_faces=mesh.faces.extend(mesh_faces,\r
- #ignoreDups=True, \r
- indexList=True)\r
- mesh.update()\r
- \r
- # gather used materials\r
- usedMaterials = {}\r
- if new_faces:\r
- for i in new_faces:\r
- if type(i) is int:\r
- usedMaterials[o.faces[i].material_index]=True\r
-\r
- # blender limits 16 materials per mesh\r
- # separate mesh ?\r
- for i, material_index in enumerate(usedMaterials.keys()):\r
- if i>=16:\r
- print("over 16 materials!")\r
- break\r
- mesh.materials+=[materials[material_index]]\r
- usedMaterials[material_index]=i\r
- \r
- # set face params\r
- for i, f in enumerate(o.faces): \r
- if not type(new_faces[i]) is int:\r
- continue\r
-\r
- face=mesh.faces[new_faces[i]]\r
-\r
- uv_array=[]\r
- for i in xrange(f.index_count):\r
- uv_array.append(Blender.Mathutils.Vector(\r
- f.getUV(i).x, \r
- 1.0-f.getUV(i).y)\r
- )\r
- try:\r
- face.uv=uv_array\r
- except Exception, msg:\r
- #print msg\r
- #print face.index, uv_array\r
- pass\r
- \r
- if f.material_index in usedMaterials:\r
- face.mat = usedMaterials[f.material_index]\r
-\r
- face.smooth = 1\r
-\r
- # rmeove dummy 0 vertex\r
- mesh.verts.delete(0)\r
- \r
- mesh.mode |= Blender.Mesh.Modes.AUTOSMOOTH\r
- mesh.maxSmoothAngle = int(o.smoothing)\r
- mesh.smooth()\r
- mesh.calcNormals()\r
- mesh.flipNormals()\r
- mesh.update()\r
-\r
- # mirror modifier\r
- if o.mirror:\r
- mod=mesh_object.modifiers.append(Blender.Modifier.Types.MIRROR)\r
-\r
- return objects\r
-\r
-\r
-class MikotoBone(object):\r
- __slots__=[\r
- 'name',\r
- 'iHead', 'iTail', 'iUp',\r
- 'vHead', 'vTail', 'vUp',\r
- 'parent', 'isFloating',\r
- 'children',\r
- ]\r
- def __init__(self, face=None, vertices=None, materials=None):\r
- self.parent=None\r
- self.isFloating=False\r
- self.children=[]\r
- if not face:\r
- self.name='root'\r
- return\r
-\r
- self.name=materials[face.material_index].name.encode('utf-8')\r
-\r
- i0=face.indices[0]\r
- i1=face.indices[1]\r
- i2=face.indices[2]\r
- v0=vertices[i0]\r
- v1=vertices[i1]\r
- v2=vertices[i2]\r
- e01=v1-v0\r
- e12=v2-v1\r
- e20=v0-v2\r
- sqNorm0=e01.getSqNorm()\r
- sqNorm1=e12.getSqNorm()\r
- sqNorm2=e20.getSqNorm()\r
- if sqNorm0>sqNorm1:\r
- if sqNorm1>sqNorm2:\r
- # e01 > e12 > e20\r
- self.iHead=i2\r
- self.iTail=i1\r
- self.iUp=i0\r
- else:\r
- if sqNorm0>sqNorm2:\r
- # e01 > e20 > e12\r
- self.iHead=i2\r
- self.iTail=i0\r
- self.iUp=i1\r
- else:\r
- # e20 > e01 > e12\r
- self.iHead=i1\r
- self.iTail=i0\r
- self.iUp=i2\r
- else:\r
- # 0 < 1\r
- if sqNorm1<sqNorm2:\r
- # e20 > e12 > e01\r
- self.iHead=i1\r
- self.iTail=i2\r
- self.iUp=i0\r
- else:\r
- if sqNorm0<sqNorm2:\r
- # e12 > e20 > e01\r
- self.iHead=i0\r
- self.iTail=i2\r
- self.iUp=i1\r
- else:\r
- # e12 > e01 > e20\r
- self.iHead=i0\r
- self.iTail=i1\r
- self.iUp=i2\r
- self.vHead=vertices[self.iHead]\r
- self.vTail=vertices[self.iTail]\r
- self.vUp=vertices[self.iUp]\r
-\r
- if self.name.endswith('[]'):\r
- basename=self.name[0:-2]\r
- # expand LR name\r
- if self.vTail.x>0:\r
- self.name="%s_L" % basename\r
- else:\r
- self.name="%s_R" % basename\r
-\r
-\r
- def setParent(self, parent, floating=False):\r
- if floating:\r
- self.isFloating=True\r
- self.parent=parent\r
- parent.children.append(self)\r
-\r
- def printTree(self, indent=''):\r
- print("%s%s" % (indent, self.name))\r
- for child in self.children:\r
- child.printTree(indent+' ')\r
-\r
-\r
-def build_armature(armature, mikotoBone, parent=None):\r
- """\r
- create a armature bone.\r
- """\r
- bone = Armature.Editbone()\r
- bone.name = mikotoBone.name.encode('utf-8')\r
- armature.bones[bone.name] = bone\r
-\r
- bone.head = Mathutils.Vector(*mikotoBone.vHead.to_a())\r
- bone.tail = Mathutils.Vector(*mikotoBone.vTail.to_a())\r
- if parent:\r
- bone.parent=parent\r
- if mikotoBone.isFloating:\r
- pass\r
- else:\r
- bone.options=[Armature.CONNECTED]\r
-\r
- for child in mikotoBone.children:\r
- build_armature(armature, child, bone)\r
-\r
-\r
-def create_armature(scene, mqo):\r
- """\r
- create armature\r
- """\r
- boneObject=None\r
- for o in mqo.objects:\r
- if o.name.startswith('bone'):\r
- boneObject=o\r
- break\r
- if not boneObject:\r
- return\r
-\r
- tailMap={}\r
- for f in boneObject.faces:\r
- if f.index_count!=3:\r
- print("invalid index_count: %d" % f.index_count)\r
- continue\r
- b=MikotoBone(f, boneObject.vertices, mqo.materials)\r
- tailMap[b.iTail]=b\r
-\r
- #################### \r
- # build mikoto bone tree\r
- #################### \r
- mikotoRoot=MikotoBone()\r
-\r
- for b in tailMap.values():\r
- # each bone has unique parent or is root bone.\r
- if b.iHead in tailMap:\r
- b.setParent(tailMap[b.iHead])\r
- else: \r
- isFloating=False\r
- for e in boneObject.edges:\r
- if b.iHead==e.indices[0]:\r
- # floating bone\r
- if e.indices[1] in tailMap:\r
- b.setParent(tailMap[e.indices[1]], True)\r
- isFloating=True\r
- break\r
- elif b.iHead==e.indices[1]:\r
- # floating bone\r
- if e.indices[0] in tailMap:\r
- b.setParent(tailMap[e.indices[0]], True)\r
- isFloating=True\r
- break\r
- if isFloating:\r
- continue\r
-\r
- # no parent bone\r
- b.setParent(mikotoRoot, True)\r
-\r
- if len(mikotoRoot.children)==0:\r
- print("no root bone")\r
- return\r
-\r
- if len(mikotoRoot.children)==1:\r
- # single root\r
- mikotoRoot=mikotoRoot.children[0]\r
- mikotoRoot.parent=None\r
- else:\r
- mikotoRoot.vHead=Vector3(0, 10, 0)\r
- mikotoRoot.vTail=Vector3(0, 0, 0)\r
-\r
- #################### \r
- # create armature\r
- #################### \r
- armature = Armature.New()\r
- # link to object\r
- armature_object = scene.objects.new(armature)\r
- # create action\r
- act = Armature.NLA.NewAction()\r
- act.setActive(armature_object)\r
- # set XRAY\r
- armature_object.drawMode |= Object.DrawModes.XRAY\r
- # armature settings\r
- armature.drawType = Armature.OCTAHEDRON\r
- armature.envelopes = False\r
- armature.vertexGroups = True\r
- armature.mirrorEdit = True\r
- armature.drawNames=True\r
-\r
- # edit bones\r
- armature.makeEditable()\r
- build_armature(armature, mikotoRoot)\r
- armature.update()\r
-\r
- return armature_object\r
- \r
-\r
-class TrianglePlane(object):\r
- """\r
- mikoto方式ボーンのアンカーウェイト計算用。\r
- (不完全)\r
- """\r
- __slots__=['normal', \r
- 'v0', 'v1', 'v2',\r
- ]\r
- def __init__(self, v0, v1, v2):\r
- self.v0=v0\r
- self.v1=v1\r
- self.v2=v2\r
-\r
- def isInsideXY(self, p):\r
- v0=Vector2(self.v0.x, self.v0.y)\r
- v1=Vector2(self.v1.x, self.v1.y)\r
- v2=Vector2(self.v2.x, self.v2.y)\r
- e01=v1-v0\r
- e12=v2-v1\r
- e20=v0-v2\r
- c0=Vector2.cross(e01, p-v0)\r
- c1=Vector2.cross(e12, p-v1)\r
- c2=Vector2.cross(e20, p-v2)\r
- if c0>=0 and c1>=0 and c2>=0:\r
- return True\r
- if c0<=0 and c1<=0 and c2<=0:\r
- return True\r
-\r
- def isInsideYZ(self, p):\r
- v0=Vector2(self.v0.y, self.v0.z)\r
- v1=Vector2(self.v1.y, self.v1.z)\r
- v2=Vector2(self.v2.y, self.v2.z)\r
- e01=v1-v0\r
- e12=v2-v1\r
- e20=v0-v2\r
- c0=Vector2.cross(e01, p-v0)\r
- c1=Vector2.cross(e12, p-v1)\r
- c2=Vector2.cross(e20, p-v2)\r
- if c0>=0 and c1>=0 and c2>=0:\r
- return True\r
- if c0<=0 and c1<=0 and c2<=0:\r
- return True\r
-\r
- def isInsideZX(self, p):\r
- v0=Vector2(self.v0.z, self.v0.x)\r
- v1=Vector2(self.v1.z, self.v1.x)\r
- v2=Vector2(self.v2.z, self.v2.x)\r
- e01=v1-v0\r
- e12=v2-v1\r
- e20=v0-v2\r
- c0=Vector2.cross(e01, p-v0)\r
- c1=Vector2.cross(e12, p-v1)\r
- c2=Vector2.cross(e20, p-v2)\r
- if c0>=0 and c1>=0 and c2>=0:\r
- return True\r
- if c0<=0 and c1<=0 and c2<=0:\r
- return True\r
-\r
-\r
-class MikotoAnchor(object):\r
- """\r
- mikoto方式スケルトンのアンカー。\r
- """\r
- __slots__=[\r
- "triangles", "bbox",\r
- ]\r
- def __init__(self):\r
- self.triangles=[]\r
- self.bbox=None\r
-\r
- def push(self, face, vertices):\r
- if face.index_count==3:\r
- self.triangles.append(TrianglePlane(\r
- vertices[face.indices[0]],\r
- vertices[face.indices[1]],\r
- vertices[face.indices[2]]\r
- ))\r
- elif face.index_count==4:\r
- self.triangles.append(TrianglePlane(\r
- vertices[face.indices[0]],\r
- vertices[face.indices[1]],\r
- vertices[face.indices[2]]\r
- ))\r
- self.triangles.append(TrianglePlane(\r
- vertices[face.indices[2]],\r
- vertices[face.indices[3]],\r
- vertices[face.indices[0]]\r
- ))\r
- # bounding box\r
- if not self.bbox:\r
- self.bbox=BoundingBox(vertices[face.indices[0]])\r
- for i in face.indices:\r
- self.bbox.expand(vertices[i])\r
-\r
-\r
- def calcWeight(self, v):\r
- if not self.bbox.isInside(v):\r
- return 0\r
-\r
- if self.anyXY(v.x, v.y) and self.anyYZ(v.y, v.z) and self.anyZX(v.z, v.x):\r
- return 1.0\r
- else:\r
- return 0\r
- \r
- def anyXY(self, x, y):\r
- for t in self.triangles:\r
- if t.isInsideXY(Vector2(x, y)):\r
- return True\r
- return False\r
-\r
- def anyYZ(self, y, z):\r
- for t in self.triangles:\r
- if t.isInsideYZ(Vector2(y, z)):\r
- return True\r
- return False\r
-\r
- def anyZX(self, z, x):\r
- for t in self.triangles:\r
- if t.isInsideZX(Vector2(z, x)):\r
- return True\r
- return False\r
-\r
-\r
-def create_bone_weight(scene, mqo, armature_object, objects):\r
- """\r
- create mikoto bone weight.\r
- """\r
- anchorMap={}\r
- # setup mikoto anchors\r
- for o in mqo.objects:\r
- if o.name.startswith("anchor"):\r
- for f in o.faces:\r
- name=mqo.materials[f.material_index].name\r
- if name.endswith('[]'):\r
- basename=name[0:-2]\r
- v=o.vertices[f.indices[0]]\r
- if(v.x>0):\r
- # L\r
- name_L=basename+'_L'\r
- if not name_L in anchorMap:\r
- anchorMap[name_L]=MikotoAnchor()\r
- anchorMap[name_L].push(f, o.vertices)\r
- elif(v.x<0):\r
- # R\r
- name_R=basename+'_R'\r
- if not name_R in anchorMap:\r
- anchorMap[name_R]=MikotoAnchor()\r
- anchorMap[name_R].push(f, o.vertices)\r
- else:\r
- print("no side", v)\r
- else:\r
- if not name in anchorMap:\r
- anchorMap[name]=MikotoAnchor()\r
- anchorMap[name].push(f, o.vertices)\r
-\r
- for o in objects:\r
- # add armature modifier\r
- mod=o.modifiers.append(Modifier.Types.ARMATURE)\r
- mod[Modifier.Settings.OBJECT] = armature_object\r
- mod[Modifier.Settings.ENVELOPES] = False\r
- o.makeDisplayList()\r
- # create vertex group\r
- mesh=o.getData(mesh=True)\r
- for name in anchorMap.keys():\r
- mesh.addVertGroup(name)\r
- mesh.update()\r
- \r
- # assing vertices to vertex group\r
- for o in objects:\r
- mesh=o.getData(mesh=True)\r
- for i, mvert in enumerate(mesh.verts):\r
- hasWeight=False\r
- for name, anchor in anchorMap.items():\r
- weight=anchor.calcWeight(mvert.co)\r
- if weight>0:\r
- mesh.assignVertsToGroup(\r
- name, [i], weight, Mesh.AssignModes.ADD)\r
- hasWeight=True\r
- if not hasWeight:\r
- # debug orphan vertex\r
- print('orphan', mvert)\r
- mesh.update()\r
- \r
-\r
-def import_mqo(filename):\r
- """\r
- import a mqo file.\r
- """\r
- filename=filename.decode(INTERNAL_ENCODING)\r
- print "##start mqo_import.py##"\r
- print INTERNAL_ENCODING, FS_ENCODING\r
- print "parse mqo file: %s" % (filename)\r
-\r
- Blender.Window.WaitCursor(1) \r
- t = Blender.sys.time() \r
-\r
- # parse file\r
- mqo=meshio.mqo.IO()\r
- \r
- if not mqo.read(filename):\r
- return\r
-\r
- # get active scene\r
- scene = Blender.Scene.GetCurrent()\r
-\r
- # create materials\r
- materials=create_materials(scene, mqo, os.path.dirname(filename))\r
- \r
- # create objects\r
- root=scene.objects.new("Empty")\r
- root.setName(os.path.basename(filename))\r
- objects=create_objects(scene, root, mqo, materials)\r
-\r
- if has_mikoto(mqo):\r
- # create mikoto bone\r
- armature_object=create_armature(scene, mqo)\r
- if armature_object:\r
- root.makeParent([armature_object])\r
-\r
- # create bone weight\r
- create_bone_weight(scene, mqo, armature_object, objects)\r
-\r
-\r
- print('finished in %.2f seconds' % (Blender.sys.time()-t))\r
- print('')\r
- Blender.Redraw()\r
- Blender.Window.WaitCursor(0) \r
-\r
-\r
-Blender.Window.FileSelector(import_mqo, 'Import MQO', '*.mqo')\r
-\r
+++ /dev/null
-#!BPY
-# coding: utf-8
-"""
- Name: 'MikuMikuDance model (.pmd)...'
- Blender: 248
- Group: 'Export'
- Tooltip: 'Export PMD file for MikuMikuDance.'
-"""
-__author__= ["ousttrue"]
-__version__= "1.0"
-__url__=()
-__bpydoc__="""
-0.1 20100318 first implementation.
-0.2 20100519 refactoring. use C extension.
-1.0 20100530 implement, basic features.
-"""
-import Blender
-import os
-import sys
-
-from meshio import pmd, englishmap
-
-
-# ファイルシステムの文字コード
-# 改造版との共用のため
-FS_ENCODING=sys.getfilesystemencoding()
-if os.path.exists(os.path.dirname(sys.argv[0])+"/utf8"):
- INTERNAL_ENCODING='utf-8'
-else:
- INTERNAL_ENCODING=FS_ENCODING
-
-
-MMD_SHAPE_GROUP_NAME='_MMD_SHAPE'
-EXTENSION = u'.pmd'
-
-
-class Node(object):
- __slots__=['o', 'children']
- def __init__(self, o):
- self.o=o
- self.children=[]
-
-
-###############################################################################
-# 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 __str__(self):
- return "<vkey: %f, %f, %f, %f, %f, %f, %f, %f>" % (
- self.x, self.y, self.z, self.nx, self.ny, self.nz, self.u, self.v)
-
- def __hash__(self):
- #return int((self.x+self.y+self.z+self.nx+self.ny+self.nz+self.u+self.v)*100)
- return int((self.x+self.y+self.z)*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)
- #return near(self.x, rhs.x) and near(self.y, rhs.y) and near(self.z, rhs.z)
- return self.x==rhs.x and self.y==rhs.y and self.z==rhs.z
-
-
-class VertexArray(object):
- """
- 頂点配列
- """
- def __init__(self):
- # マテリアル毎に分割したインデックス配列
- self.indexArrays={}
- # 頂点属性
- self.vertices=[]
- self.normals=[]
- self.uvs=[]
- # skinning属性
- self.b0=[]
- self.b1=[]
- self.weight=[]
-
- self.vertexMap={}
- self.indexMap={}
-
- def __str__(self):
- return "<VertexArray %d vertices, %d indexArrays>" % (
- len(self.vertices), len(self.indexArrays))
-
- def zip(self):
- return zip(
- self.vertices, self.normals, self.uvs,
- self.b0, self.b1, self.weight)
-
- def __getIndex(self, base_index, 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 key in self.vertexMap:
- # 同じ頂点を登録済み
- index=self.vertexMap[key]
- else:
- index=len(self.vertices)
- # 新規頂点
- self.vertexMap[key]=index
- # append...
- 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))
- self.b0.append(b0)
- self.b1.append(b1)
- self.weight.append(weight0)
-
- # indexのマッピングを保存する
- if not base_index in self.indexMap:
- self.indexMap[base_index]=set()
- self.indexMap[base_index].add(index)
-
- assert(index<=65535)
- return index
-
- def getMappedIndices(self, base_index):
- return self.indexMap[base_index]
-
- def addTriangle(self,
- material,
- base_index0, base_index1, base_index2,
- 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(base_index0, pos0, n0, uv0, b0_0, b1_0, weight0)
- index1=self.__getIndex(base_index1, pos1, n1, uv1, b0_1, b1_1, weight1)
- index2=self.__getIndex(base_index2, pos2, n2, uv2, b0_2, b1_2, weight2)
-
- self.indexArrays[material]+=[index0, index1, index2]
-
-
-class Morph(object):
- __slots__=['name', 'type', 'offsets']
- def __init__(self, name, type):
- self.name=name
- self.type=type
- self.offsets=[]
-
- def add(self, index, offset):
- self.offsets.append((index, offset))
-
- def sort(self):
- self.offsets.sort(lambda l, r: l[0]-r[0])
-
- def __str__(self):
- return "<Morph %s>" % self.name
-
-class IKSolver(object):
- __slots__=['target', 'effector', 'length', 'iterations', 'weight']
- def __init__(self, target, effector, length, iterations, weight):
- self.target=target
- self.effector=effector
- self.length=length
- self.iterations=iterations
- self.weight=weight
-
-
-class OneSkinMesh(object):
- __slots__=['vertexArray', 'morphList']
- def __init__(self):
- self.vertexArray=VertexArray()
- self.morphList=[]
-
- def __str__(self):
- return "<OneSkinMesh %s, morph:%d>" % (
- self.vertexArray,
- len(self.morphList))
-
- def addMesh(self, obj):
- if obj.restrictDisplay:
- # 非表示
- return
-
- print("export", obj.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.index, v1.index, v2.index,
- v0.co, v1.co, v2.co,
- # ToDo vertex normal
- #v0.no, v1.no, v2.no,
- face.no, face.no, face.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.index, v1.index, v2.index,
- v0.co, v1.co, v2.co,
- #v0.no, v1.no, v2.no,
- face.no, face.no, face.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.index, v3.index, v0.index,
- v2.co, v3.co, v0.co,
- #v2.no, v3.no, v0.no,
- face.no, face.no, face.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]
- )
-
- ############################################################
- # skin
- ############################################################
- # base
- indexRelativeMap={}
- blenderMesh=obj.getData(mesh=True)
- baseMorph=None
- if blenderMesh.key:
- for b in blenderMesh.key.blocks:
- if b.name=='Basis':
- print(b.name)
- baseMorph=self.__getOrCreateMorph('base', 0)
- relativeIndex=0
- basis=b
- for index in blenderMesh.getVertsFromGroup(
- MMD_SHAPE_GROUP_NAME):
- v=b.data[index]
- pos=[v[0], v[1], v[2]]
- indices=self.vertexArray.getMappedIndices(index)
- for i in indices:
- baseMorph.add(i, pos)
- indexRelativeMap[relativeIndex]=i
- relativeIndex+=1
- break
- print(len(baseMorph.offsets))
- baseMorph.sort()
- assert(basis)
-
- # shape keys
- vg=obj.getData(mesh=True).getVertsFromGroup(
- MMD_SHAPE_GROUP_NAME)
- for b in obj.getData(mesh=True).key.blocks:
- if b.name=='Basis':
- continue
-
- print(b.name)
- morph=self.__getOrCreateMorph(b.name, 4)
- for index, src, dst in zip(
- xrange(len(blenderMesh.verts)),
- basis.data,
- b.data):
- offset=[dst[0]-src[0], dst[1]-src[1], dst[2]-src[2]]
- if index in vg:
- indices=self.vertexArray.getMappedIndices(index)
- for i in indices:
- morph.add(indexRelativeMap[i], offset)
- assert(len(morph.offsets)==len(baseMorph.offsets))
-
- # sort skinmap
- if len(self.morphList)>1:
- original=self.morphList[:]
- def getIndex(morph):
- for i, v in enumerate(englishmap.skinMap):
- if v[0]==morph.name:
- return i
- #print(morph)
- return 0
- self.morphList.sort(lambda l, r: getIndex(l)-getIndex(r))
-
- def __getOrCreateMorph(self, name, type):
- for m in self.morphList:
- if m.name==name:
- return m
- m=Morph(name, type)
- self.morphList.append(m)
- return m
-
- def getVertexCount(self):
- return len(self.vertexArray.vertices)
-
-
-class Bone(object):
- __slots__=['index', 'name', 'ik_index',
- 'pos', 'tail', 'parent_index', 'tail_index', 'type', 'isConnect']
- def __init__(self, name, pos, tail):
- self.index=-1
- self.name=name
- self.pos=pos
- self.tail=tail
- self.parent_index=None
- self.tail_index=None
- self.type=0
- self.isConnect=False
- self.ik_index=0
-
- def __eq__(self, rhs):
- return self.index==rhs.index
-
- def __str__(self):
- return "<Bone %s %d>" % (self.name, self.type)
-
-class BoneBuilder(object):
- __slots__=['bones', 'boneMap', 'ik_list']
- def __init__(self):
- self.bones=[]
- self.boneMap={}
- self.ik_list=[]
-
- def build(self, armatureObj):
- if not armatureObj:
- return
-
- print("gather bones")
- armature=armatureObj.getData()
- for b in armature.bones.values():
- if b.name=='center':
- # root bone
- bone=Bone(b.name,
- b.head['ARMATURESPACE'][0:3],
- b.tail['ARMATURESPACE'][0:3])
- self.__addBone(bone)
- self.__getBone(bone, b)
-
- for b in armature.bones.values():
- if not b.parent and b.name!='center':
- # root bone
- bone=Bone(b.name,
- b.head['ARMATURESPACE'][0:3],
- b.tail['ARMATURESPACE'][0:3])
- self.__addBone(bone)
- self.__getBone(bone, b)
-
- print("check connection")
- for b in armature.bones.values():
- if not b.parent:
- self.__checkConnection(b, None)
-
- print("gather ik")
- pose = armatureObj.getPose()
- cSetting=Blender.Constraint.Settings
- for b in pose.bones.values():
- for c in b.constraints:
- if c.type==Blender.Constraint.Type.IKSOLVER:
- ####################
- # IK target
- ####################
- assert(c[cSetting.TARGET]==armatureObj)
- target=self.__boneByName(
- c[Blender.Constraint.Settings.BONE])
- target.type=2
-
- ####################
- # IK effector
- ####################
- # IK 接続先
- link=self.__boneByName(b.name)
- link.type=6
-
- # IK chain
- e=b.parent
- chainLength=c[cSetting.CHAINLEN]
- for i in range(chainLength):
- # IK影響下
- chainBone=self.__boneByName(e.name)
- chainBone.type=4
- chainBone.ik_index=target.index
- e=e.parent
- self.ik_list.append(
- IKSolver(target, link, chainLength,
- int(c[cSetting.ITERATIONS] * 0.1),
- c[cSetting.ROTWEIGHT]
- ))
-
- def __checkConnection(self, b, p):
- if Blender.Armature.CONNECTED in b.options:
- parent=self.__boneByName(p.name)
- parent.isConnect=True
-
- for c in b.children:
- self.__checkConnection(c, b)
-
- def sortBy(self, boneMap):
- """
- boneMap順に並べ替える
- """
- original=self.bones[:]
- def getIndex(bone):
- for i, k_v in enumerate(boneMap):
- if k_v[0]==bone.name:
- return i
- print(bone)
-
- self.bones.sort(lambda l, r: getIndex(l)-getIndex(r))
- sortMap={}
- for i, b in enumerate(self.bones):
- src=original.index(b)
- sortMap[src]=i
- for b in self.bones:
- b.index=sortMap[b.index]
- if b.parent_index:
- b.parent_index=sortMap[b.parent_index]
- if b.tail_index:
- b.tail_index=sortMap[b.tail_index]
- if b.ik_index>0:
- b.ik_index=sortMap[b.ik_index]
-
- def getIndex(self, bone):
- for i, b in enumerate(self.bones):
- if b==bone:
- return i
- assert(false)
-
- def indexByName(self, name):
- return self.getIndex(self.__boneByName(name))
-
- def __boneByName(self, name):
- return self.bones[self.boneMap[name]]
-
- def __getBone(self, parent, b):
- if len(b.children)==0:
- parent.type=7
- return
-
- for i, c in enumerate(b.children):
- bone=Bone(c.name,
- c.head['ARMATURESPACE'][0:3],
- c.tail['ARMATURESPACE'][0:3])
- self.__addBone(bone)
- if parent:
- bone.parent_index=parent.index
- if i==0:
- parent.tail_index=bone.index
- self.__getBone(bone, c)
-
- def __addBone(self, bone):
- bone.index=len(self.bones)
- self.bones.append(bone)
- self.boneMap[bone.name]=bone.index
-
-
-class PmdExporter(object):
-
- def __init__(self):
- self.armatureObj=None
-
- def setup(self, scene):
- # 木構造を構築する
- object_node_map={}
- for o in scene.objects:
- object_node_map[o]=Node(o)
- for node in object_node_map.values():
- if node.o.parent:
- object_node_map[node.o.parent].children.append(node)
- # ルートを得る
- root=object_node_map[scene.objects.active]
-
- # ワンスキンメッシュを作る
- self.oneSkinMesh=OneSkinMesh()
- self.__createOneSkinMesh(root)
- print(self.oneSkinMesh)
- self.name=root.o.name
-
- # skeleton
- self.builder=BoneBuilder()
- self.builder.build(self.armatureObj)
- self.builder.sortBy(englishmap.boneMap)
- def getIndex(ik):
- for i, v in enumerate(englishmap.boneMap):
- if v[0]==ik.target.name:
- return i
- return len(englishmap.boneMap)
- self.builder.ik_list.sort(lambda l, r: getIndex(l)-getIndex(r))
-
- def __createOneSkinMesh(self, node):
- ############################################################
- # search armature modifier
- ############################################################
- for m in node.o.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
-
- if node.o.getType()=='Mesh':
- self.oneSkinMesh.addMesh(node.o)
-
- for child in node.children:
- self.__createOneSkinMesh(child)
-
- def write(self, path):
- print('write')
- io=pmd.IO()
- io.name=self.name
- io.comment="blender export"
- io.version=1.0
-
- # 頂点
- print('vertices')
- for pos, normal, uv, b0, b1, weight in self.oneSkinMesh.vertexArray.zip():
- # convert right-handed z-up to left-handed y-up
- v=io.addVertex()
- v.pos.x=pos[0]
- v.pos.y=pos[2]
- v.pos.z=pos[1]
- v.normal.x=normal[0]
- v.normal.y=normal[2]
- v.normal.z=normal[1]
- v.uv.x=uv[0]
- v.uv.y=uv[1]
- v.bone0=self.builder.boneMap[b0] if b0 in self.builder.boneMap else 0
- v.bone1=self.builder.boneMap[b1] if b1 in self.builder.boneMap else 0
- v.weight0=int(100*weight)
- v.edge_flag=0 # edge flag, 0: enable edge, 1: not edge
-
- # 面とマテリアル
- print('faces and materials')
- vertexCount=self.oneSkinMesh.getVertexCount()
- for m, indices in self.oneSkinMesh.vertexArray.indexArrays.items():
- m=Blender.Material.Get(m)
- # マテリアル
- material=io.addMaterial()
- material.diffuse.r=m.R
- material.diffuse.g=m.G
- material.diffuse.b=m.B
- material.diffuse.a=m.alpha
- material.sinness=0 if m.spec<1e-5 else m.spec*10
- material.specular.r=m.specR
- material.specular.g=m.specG
- material.specular.b=m.specB
- material.ambient.r=m.mirR
- material.ambient.g=m.mirG
- material.ambient.b=m.mirB
- material.vertex_count=len(indices)
- material.toon_index=0
- material.flag=1 if m.enableSSS else 0
- # ToDo
- material.texture=""
- # 面
- for i in indices:
- assert(i<vertexCount)
- for i in xrange(0, len(indices), 3):
- # reverse triangle
- io.indices.append(indices[i+2])
- io.indices.append(indices[i+1])
- io.indices.append(indices[i])
-
- #io.indices.append(indices[i])
- #io.indices.append(indices[i+1])
- #io.indices.append(indices[i+2])
-
- # bones
- print('bones')
- for b in self.builder.bones:
- if b.name.endswith("_t"):
- if b.name.startswith("arm twist1_") or b.name.startswith("arm twist2_"):
- # skip
- print "skip %s" % b.name
- continue
-
- bone=io.addBone()
-
- v=englishmap.getUnicodeBoneName(b.name)
- assert(v)
- cp932=v[1].encode('cp932')
- bone_name="%s" % cp932
- assert(len(bone_name)<20)
- bone.name=bone_name
-
- bone_english_name="%s" % b.name
- assert(len(bone_english_name)<20)
- bone.english_name=bone_english_name
-
- if len(v)>=3:
- # has type
- if v[2]==5:
- b.ik_index=self.builder.indexByName('eyes')
- bone.type=v[2]
- else:
- bone.type=b.type
-
- # parent index
- bone.parent_index=b.parent_index if b.parent_index!=None else 0xFFFF
-
- # tail index
- if b.tail_index!=None:
- if bone.type==9:
- bone.tail_index=0
- else:
- bone.tail_index=b.tail_index
- else:
- bone.tail_index=0
-
- bone.ik_index=b.ik_index
-
- # convert right-handed z-up to left-handed y-up
- bone.pos.x=b.pos[0] if not near(b.pos[0], 0) else 0
- bone.pos.y=b.pos[2] if not near(b.pos[2], 0) else 0
- bone.pos.z=b.pos[1] if not near(b.pos[1], 0) else 0
-
- # IK
- print('ik')
- for ik in self.builder.ik_list:
- solver=io.addIK()
- solver.index=self.builder.getIndex(ik.target)
- solver.target=self.builder.getIndex(ik.effector)
- solver.length=ik.length
- b=self.builder.bones[ik.effector.parent_index]
- for i in xrange(solver.length):
- solver.children.append(self.builder.getIndex(b))
- b=self.builder.bones[b.parent_index]
- solver.iterations=ik.iterations
- solver.weight=ik.weight
-
- # 表情
- print('shape keys')
- for i, m in enumerate(self.oneSkinMesh.morphList):
- # morph
- morph=io.addMorph()
-
- v=englishmap.getUnicodeSkinName(m.name)
- assert(v)
- cp932=v[1].encode('cp932')
- morph.name="%s\n" % cp932
-
- morph.english_name="%s\n" % m.name
- m.type=v[2]
- morph.type=v[2]
- for index, offset in m.offsets:
- # convert right-handed z-up to left-handed y-up
- morph.append(index, offset[0], offset[2], offset[1])
- morph.vertex_count=len(m.offsets)
-
- # 表情枠
- print('display list')
- # type==0はbase
- for i, m in enumerate(self.oneSkinMesh.morphList):
- if m.type==3:
- io.face_list.append(i)
- for i, m in enumerate(self.oneSkinMesh.morphList):
- if m.type==2:
- io.face_list.append(i)
- for i, m in enumerate(self.oneSkinMesh.morphList):
- if m.type==1:
- io.face_list.append(i)
- for i, m in enumerate(self.oneSkinMesh.morphList):
- if m.type==4:
- io.face_list.append(i)
-
- # ボーン表示枠
- print('bone display list')
- def createBoneDisplayName(name, english):
- boneDisplayName=io.addBoneDisplayName()
- boneDisplayName.name=name.decode('utf-8').encode('cp932')
- boneDisplayName.english_name=english
- boneDisplayName=createBoneDisplayName("IK\n", "IK\n")
- boneDisplayName=createBoneDisplayName("体(上)\n", "Body[u]\n")
- boneDisplayName=createBoneDisplayName("髪\n", "Hair\n")
- boneDisplayName=createBoneDisplayName("腕\n", "Arms\n")
- boneDisplayName=createBoneDisplayName("指\n", "Fingers\n")
- boneDisplayName=createBoneDisplayName("体(下)\n", "Body[l]\n")
- boneDisplayName=createBoneDisplayName("足\n", "Legs\n")
- for i, b in enumerate(self.builder.bones):
- if i==0:
- continue
- if b.type in [6, 7]:
- continue
- io.addBoneDisplay(i, getBoneDisplayGroup(b))
-
- # English
- print('english')
- io.english_name="blender export"
- io.english_coment="blender export"
-
- for i in range(10):
- io.getToonTexture(i).name="toon%02d.bmp\n" % i
-
- # 書き込み
- return io.write(path)
-
-
-def getBoneDisplayGroup(bone):
- boneGroups=[
- [ # IK
- "necktie IK", "hair IK_L", "hair IK_R", "leg IK_L", "leg IK_R",
- "toe IK_L", "toe IK_R",
- ],
- [ # 体(上)
- "upper body", "neck", "head", "eye_L", "eye_R",
- "necktie1", "necktie2", "necktie3", "eyes",
- "eyelight_L", "eyelight_R",
- ],
- [ # 髪
- "front hair1", "front hair2", "front hair3",
- "hair1_L", "hair2_L", "hair3_L",
- "hair4_L", "hair5_L", "hair6_L",
- "hair1_R", "hair2_R", "hair3_R",
- "hair4_R", "hair5_R", "hair6_R",
- ],
- [ # 腕
- "shoulder_L", "arm_L", "arm twist_L", "elbow_L",
- "wrist twist_L", "wrist_L", "sleeve_L",
- "shoulder_R", "arm_R", "arm twist_R", "elbow_R",
- "wrist twist_R", "wrist_R", "sleeve_R",
- ],
- [ # 指
- "thumb1_L", "thumb2_L", "fore1_L", "fore2_L", "fore3_L",
- "middle1_L", "middle2_L", "middle3_L",
- "third1_L", "third2_L", "third3_L",
- "little1_L", "little2_L", "little3_L",
- "thumb1_R", "thumb2_R", "fore1_R", "fore2_R", "fore3_R",
- "middle1_R", "middle2_R", "middle3_R",
- "third1_R", "third2_R", "third3_R",
- "little1_R", "little2_R", "little3_R",
- ],
- [ # 体(下)
- "lower body", "waist accessory",
- "front skirt_L", "back skirt_L",
- "front skirt_R", "back skirt_R",
- ],
- [ # 足
- "leg_L", "knee_L", "ankle_L",
- "leg_R", "knee_R", "ankle_R",
- ],
- ]
- index=1
- for g in boneGroups:
- if bone.name in g:
- return index
- index+=1
- print(bone)
- return -1
-
-def export_pmd(filename):
- filename=filename.decode(INTERNAL_ENCODING)
-
- Blender.Window.WaitCursor(1)
- t = Blender.sys.time()
-
- if not filename.lower().endswith(EXTENSION):
- filename += EXTENSION
- print "pmd exporter: %s" % filename
-
- exporter=PmdExporter()
-
- # 情報収集
- exporter.setup(Blender.Scene.GetCurrent())
-
- # 出力
- exporter.write(filename)
-
- print 'finished in %.2f seconds' % (Blender.sys.time()-t)
- Blender.Redraw()
- Blender.Window.WaitCursor(0)
-
-
-Blender.Window.FileSelector(
- export_pmd,
- 'Export Metasequoia PMD',
- Blender.sys.makename(ext=EXTENSION))
-
+++ /dev/null
-#!BPY
-# coding:utf-8
-"""
- Name: 'MikuMikuDance model (.pmd)...'
- Blender: 248
- Group: 'Import'
- Tooltip: 'Import PMD file for MikuMikuDance.'
-"""
-__author__= ["ousttrue"]
-__version__= "1.0"
-__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.
-0.8: 20100521 add shape_key group.
-1.0: 20100530 add invisilbe bone tail(armature layer 2).
-"""
-import Blender
-from Blender import Mathutils
-import bpy
-
-import os
-import sys
-import re
-
-# extension
-from meshio import pmd, englishmap
-
-
-FS_ENCODING=sys.getfilesystemencoding()
-if os.path.exists(os.path.dirname(sys.argv[0])+"/utf8"):
- INTERNAL_ENCODING='utf-8'
-else:
- INTERNAL_ENCODING=FS_ENCODING
-
-
-MMD_SHAPE_GROUP_NAME='_MMD_SHAPE'
-
-
-###############################################################################
-# ProgressBar
-###############################################################################
-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(FS_ENCODING)
- 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)
-
-
-###############################################################################
-# functions
-###############################################################################
-def convert_coord(pos):
- """
- Left handed y-up to Right handed z-up
- """
- return (pos.x, pos.z, pos.y)
-
-
-def convert_uv(uv):
- return (uv.x, 1.0 - uv.y)
-
-
-def get_bone_name(l, index):
- name=englishmap.getEnglishBoneName(l.bones[index].getName())
- return name if name else l.bones[index].getName().encode(INTERNAL_ENCODING)
-
-
-def createMaterial():
- """
- create default materil
- """
- material=Blender.Material.New()
- material.setDiffuseShader(Blender.Material.Shaders.DIFFUSE_TOON)
- material.setRef(1)
- material.diffuseSize = 3.14/2
- material.setDiffuseSmooth(0)
- material.setSpecShader(Blender.Material.Shaders.SPEC_TOON)
- material.setSpecSize(0)
- material.setSpec(0)
- 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
-
- # list化
- material_order=list(shape_key_materials)
-
- # shapeキーに使われていないマテリアルを後ろに追加
- for i in range(len(l.materials)):
- if not i in material_order:
- material_order.append(i)
-
- # マテリアル16個ごとに分割したメッシュを作成する
- material_offset=0
- mesh_objects=[]
- while material_offset<len(l.materials):
- # create mesh
- mesh = Blender.Mesh.New()
- mesh.vertexUV = 1
- # create object
- obj = scene.objects.new(mesh)
- obj.layers = [1]
- mesh_objects.append(obj)
-
- # shapeキーで使われる順に並べなおしたマテリアル16個分の
- # メッシュを作成する
- vertex_map=import16MaerialAndMesh(
- mesh, l,
- material_order[material_offset:material_offset+16],
- face_map, tex_dir)
-
- # crete shape key
- importShape(obj, l, vertex_map)
-
- mesh.update()
- material_offset+=16
-
- return mesh_objects
-
-
-def import16MaerialAndMesh(mesh, l, material_order, face_map, tex_dir):
- ############################################################
- # material
- ############################################################
- progress_print('create materials')
- mesh_material_map={}
- materials=[]
- index=0
- for material_index in material_order:
- try:
- m=l.materials[material_index]
- mesh_material_map[material_index]=index
- except KeyError:
- break
-
- material=createMaterial()
- material.setRGBCol([m.diffuse.r, m.diffuse.g, m.diffuse.b])
- material.setAlpha(m.diffuse.a)
- material.setSpec(m.shinness*0.1)
- material.setSpecCol([m.specular.r, m.specular.g, m.specular.b])
- material.setMirCol([m.ambient.r, m.ambient.g, m.ambient.b])
- material.enableSSS=True if m.flag==1 else False
- # set texture
- if m.getTexture()!='':
- tex_file=re.compile('\*.*.spa$').sub('', m.getTexture())
- tex_path = os.path.join(tex_dir, tex_file).encode(
- INTERNAL_ENCODING)
- tex = Blender.Texture.New()
- tex.setType("Image")
- try:
- tex.image = Blender.Image.Load(tex_path)
- material.setTexture(0, tex)
- material.getTextures()[0].texco = Blender.Texture.TexCo.UV
- except IOError:
- print material.name, "fail to load", tex_path
- materials.append(material)
- # lookup table for assign
- index+=1
- mesh.materials=materials
-
- ############################################################
- # vertex
- ############################################################
- progress_print('create vertices')
- # create vertices
- vertex_groups={}
- vertices=[]
- for v in l.each_vertex():
- vertices.append(convert_coord(v.pos))
- vertex_groups[v.bone0]=True
- vertex_groups[v.bone1]=True
- mesh.verts.extend(vertices)
-
- # create vertex group
- for i in vertex_groups.keys():
- mesh.addVertGroup(get_bone_name(l, i))
-
- # vertex params
- for i, v, mvert in zip(xrange(len(l.vertices)), l.each_vertex(), mesh.verts):
- mvert.no=Mathutils.Vector(*convert_coord(v.normal))
- mvert.uvco=convert_uv(v.uv)
- w1=float(v.weight0)/100.0
- w2=1.0-w1
- mesh.assignVertsToGroup(get_bone_name(l, v.bone0), [i], w1,
- Blender.Mesh.AssignModes.ADD)
- mesh.assignVertsToGroup(get_bone_name(l, v.bone1), [i], w2,
- Blender.Mesh.AssignModes.ADD)
-
- ############################################################
- # face
- ############################################################
- progress_print('create faces')
- # create faces
- mesh_face_indices=[]
- mesh_face_materials=[]
- used_vertices=set()
-
- def degenerate(i0, i1, i2):
- return i0==i1 or i1==i2 or i2==i0
-
- for material_index in material_order:
- face_offset=face_map[material_index]
- m=l.materials[material_index]
- material_faces=l.indices[face_offset:face_offset+m.vertex_count]
- for j in xrange(0, len(material_faces), 3):
- i0=material_faces[j]
- i1=material_faces[j+1]
- i2=material_faces[j+2]
- triangle=[i0, i1, i2]
- if degenerate(*triangle):
- continue
- mesh_face_indices.append(triangle)
- mesh_face_materials.append(material_index)
- used_vertices.add(i0)
- used_vertices.add(i1)
- used_vertices.add(i2)
-
- mesh.faces.extend(mesh_face_indices, ignoreDups=True)
-
- # face params
- used_map={}
- mesh.addUVLayer('NewUV')
- for face, material_index in zip(mesh.faces, mesh_face_materials):
- try:
- index=mesh_material_map[material_index]
- except KeyError, 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
-
-
-class Builder(object):
- def __init__(self):
- self.boneMap={}
-
- def build(self, armature, bones):
- for b in bones:
- if not b.parent:
- self.__build(armature, b, None, None)
- armature.update()
-
- def __build(self, armature, b, p, parent):
- name=englishmap.getEnglishBoneName(b.getName())
- if not name:
- name=b.getName().encode(INTERNAL_ENCODING)
- self.boneMap[name]=b
-
- bone=Blender.Armature.Editbone()
- bone.name=name
- armature.bones[name]=bone
-
- if b.tail_index==0:
- # 先端
- assert(b.type==6 or b.type==7)
- bone.head = Mathutils.Vector(*convert_coord(b.pos))
- bone.tail=bone.head+Mathutils.Vector(0, 1, 0)
- assert(parent)
- bone.parent=parent
- if bone.name=="center_t":
- # センターボーンは(0, 1, 0)の方向を向いていないと具合が悪い
- parent.tail=parent.head+Mathutils.Vector(0, 1, 0)
- bone.head=parent.tail
- bone.tail=bone.head+Mathutils.Vector(0, 1, 0)
- else:
- assert(parent.tail==bone.head)
- bone.options=[Blender.Armature.CONNECTED]
- # armature layer 2
- bone.layerMask = (1<<1)
- else:
- bone.head = Mathutils.Vector(*convert_coord(b.pos))
- bone.tail = Mathutils.Vector(*convert_coord(b.tail))
- if parent:
- bone.parent=parent
- if parent.tail==bone.head:
- bone.options=[Blender.Armature.CONNECTED]
-
- if bone.head==bone.tail:
- bone.tail=bone.head+Mathutils.Vector(0, 1, 0)
-
- for c in b.children:
- self.__build(armature, c, b, bone)
-
-
-def importArmature(scene, l):
- # create armature
- armature = Blender.Armature.New()
- # link to object
- armature_object = scene.objects.new(armature)
- # create action
- act = Blender.Armature.NLA.NewAction()
- act.setActive(armature_object)
- # set XRAY
- armature_object.drawMode = (
- armature_object.drawMode | Blender.Object.DrawModes.XRAY)
- # armature settings
- armature.drawType = Blender.Armature.OCTAHEDRON
- armature.drawNames=True
- armature.envelopes = False
- armature.vertexGroups = True
- armature.mirrorEdit = True
-
- # create armature
- armature.makeEditable()
-
- ############################################################
- # build bone
- ############################################################
- builder=Builder()
- builder.build(armature, l.bones)
-
- ############################################################
- # IK
- ############################################################
- pose = armature_object.getPose()
- cSetting = Blender.Constraint.Settings
- for ik in l.ik_list:
- # IKtarget->parent(=IK).name
- target=l.bones[ik.target]
- name = englishmap.getEnglishBoneName(target.getName())
- p_bone = pose.bones[name]
- if not p_bone:
- print 'not found', name
- continue
- if len(ik.children) >= 16:
- print 'over MAX_CHAINLEN', ik, len(ik.children)
- continue
- # IK solver
- ik_solver = p_bone.constraints.append(Blender.Constraint.Type.IKSOLVER)
- ik_solver[cSetting.CHAINLEN]=len(ik.children)
- ik_solver[cSetting.TARGET]=armature_object
- ik_solver[cSetting.USETIP]=False
-
- effector_name=englishmap.getEnglishBoneName(
- l.bones[ik.index].getName())
- if not effector_name:
- effector_name=l.bones[ik.index].getName()
-
- ik_solver[cSetting.BONE]=effector_name
- #ik_solver.influence=ik.weight
- # not used. place folder when export.
- ik_solver[cSetting.ROTWEIGHT]=ik.weight
- ik_solver[cSetting.ITERATIONS]=ik.iterations * 10
-
- armature.makeEditable()
- armature.update()
-
- return armature_object
-
-
-def importShape(obj, l, vertex_map):
- if len(l.morph_list)==0:
- return
- obj.pinShape=True
- mesh=obj.getData(mesh=True)
-
- # find base
- base=None
- for s in l.morph_list:
- if s.type==0:
- base=s
-
- # create vertex group
- mesh.addVertGroup(MMD_SHAPE_GROUP_NAME)
- indices=[]
- hasShape=False
- for i in s.indices:
- if i in vertex_map:
- hasShape=True
- indices.append(vertex_map[i])
- mesh.assignVertsToGroup(MMD_SHAPE_GROUP_NAME, indices, 0,
- Blender.Mesh.AssignModes.ADD)
- if not hasShape:
- return
-
- # create base key
- mesh.insertKey()
- assert(len(mesh.key.blocks)==1)
- baseShapeIndex=0
- baseShapeBlock=mesh.key.blocks[baseShapeIndex]
- baseShapeBlock.name='Basis'
- obj.activeShape=baseShapeIndex
- mesh.update()
- break
-
- assert(base)
-
- # each skin
- for s in l.morph_list:
- if s.name==base.name:
- continue
-
- 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 msg
- print index, len(base.indices), len(vertex_map)
- print len(mesh.verts)
- print base.indices[index]
- print vertex_index
- break
- except KeyError:
- #print 'this mesh not has shape vertices'
- break
-
- # get skin name
- name=englishmap.getEnglishSkinName(s.getName())
- if not name:
- name=s.getName().encode(INTERNAL_ENCODING)
- print(name)
-
- # create shapekey block
- mesh.insertKey()
- shapeIndex=len(mesh.key.blocks)-1
- keyBlock=mesh.key.blocks[shapeIndex]
- keyBlock.name=name
-
- # copy vertex to shape key
- mesh.update()
-
- # restore
- for mv, v in zip(mesh.verts, baseShapeBlock.getData()):
- mv.co[0] = v[0]
- mv.co[1] = v[1]
- mv.co[2] = v[2]
- mesh.update()
-
- # select base shape
- obj.activeShape=baseShapeIndex
-
-def run(filename):
- """
- @param filename
- """
- filename=filename.decode(INTERNAL_ENCODING)
- tex_dir=os.path.dirname(filename)
-
- # progress
- progress_start('pmd_import')
- print(INTERNAL_ENCODING, FS_ENCODING)
-
- # load pmd
- progress_set('load %s' % filename, 0.0)
-
- l=pmd.IO()
- if not l.read(filename):
- 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_name if len(l.english_name)>0 else l.getName().encode(INTERNAL_ENCODING))
-
- # 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()
- 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()
-
- ############################################################
- # Limitation
- ############################################################
- for n, b in armature_object.getPose().bones.items():
- if n.endswith("_t"):
- continue
-
- if n.startswith("knee_"):
- b.lockYRot=True
- b.lockZRot=True
- b.limitX=True
- b.limitMin=[0, 0, 0]
- b.limitMax=[180, 0, 0]
- elif n.startswith("ankle_"):
- b.lockYRot=True
-
- # 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.6 2010/05/06'
-__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
-0.6 2010/05/06 C extension.
-0.7 2010/05/16 modify C extension interface.
-'''
-import Blender
-import os
-import sys
-import math
-
-# extension
-from meshio import vmd, englishmap
-
-
-FS_ENCODING=sys.getfilesystemencoding()
-if os.path.exists(os.path.dirname(sys.argv[0])+"/utf8"):
- INTERNAL_ENCODING='utf-8'
-else:
- INTERNAL_ENCODING=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(INTERNAL_ENCODING)
- try:
- # ?
- Blender.Window.DrawProgressBar(self.progress, message)
- except AttributeError, error:
- #print error
- #print type(self.progress), self.progress, type(message), message
- pass
-
- 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
- last_frame=0
- for n in l.boneKeys:
- keyFrames=l.getBoneKeyFrameList(n)
- try:
- boneName=englishmap.getEnglishBoneName(n).encode(INTERNAL_ENCODING)
- except:
- print(n)
- assert(False)
- try:
- poseBone=pose.bones[boneName]
- bone=armature.bones[boneName]
- # rot
- armRotate=bone.matrix['ARMATURESPACE'].rotationPart()
- # quat
- armRotateQuaternion=armRotate.toQuat()
-
- # inv
- armRotateInv=Blender.Mathutils.Matrix(armRotate).transpose()
- # quat
- armRotateInvQuaternion=armRotateInv.toQuat()
-
- reverseFlag=False
- lastQ=None
-
- for i in xrange(len(keyFrames.list)):
- key=keyFrames.getKey(i)
- ####################
- # rotation
- ####################
- if lastQ and lastQ.dot(key.q)<0:
- reverseFlag=not reverseFlag
- lastQ=key.q
-
- # convert left-handed y-up to right-handed z-up
- if reverseFlag:
- # reverse quaternion for slerp
- q=Blender.Mathutils.Quaternion(-key.q.w, 0, 0, 0)
- q.x=key.q.x
- q.y=key.q.z
- q.z=key.q.y
- else:
- q=Blender.Mathutils.Quaternion(key.q.w, 0, 0, 0)
- q.x=-key.q.x
- q.y=-key.q.z
- q.z=-key.q.y
-
- poseBone.quat=(
- multQuat(armRotateInvQuaternion,
- multQuat(q, armRotateQuaternion)))
-
- ####################
- # location
- ####################
- poseBone.loc = Blender.Mathutils.Vector(
- float(key.pos.x), float(key.pos.z), float(key.pos.y))
-
- # insert
- poseBone.insertKey(o, keyFrames.getFrame(i),
- [Blender.Object.Pose.LOC, Blender.Object.Pose.ROT],
- 1)
- last_frame=max(last_frame, keyFrames.getFrame(i))
-
- 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
-
- return last_frame
-
-
-def IPO_CURVE_get_or_create(ipo, name):
- for c in ipo:
- if c.name == name:
- return c
- 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:
- Blender.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
- last_frame=0
- for n in l.morphKeys:
- keyFrames=l.getMorphKeyFrameList(n)
- if n=='base':
- continue
- name=englishmap.getEnglishSkinName(n).encode(INTERNAL_ENCODING)
- try:
- curve=IPO_CURVE_get_or_create(ipo, name)
- except NameError, msg:
- print NameError, msg
- print n, name
- continue
- curve.interpolation = Blender.IpoCurve.InterpTypes.LINEAR
- for i in xrange(len(keyFrames.list)):
- key=keyFrames.getKey(i)
- frame=keyFrames.getFrame(i)
- curve[frame]=key.weight
- last_frame=max(last_frame, frame)
-
- counter+=1
- if counter % progressCount==0:
- progress_print("")
-
- return last_frame
-
-
-def run(filename):
- filename=filename.decode(INTERNAL_ENCODING)
-
- # progress
- progress_start('vmd_import')
- print(INTERNAL_ENCODING, FS_ENCODING)
-
- # load vmd
- progress_set('load %s' % filename, 0.0)
- l=vmd.IO()
- if not l.read(filename.encode(FS_ENCODING)):
- 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.boneMap.Size()+shapeCount*l.morphMap.size()
- #progressCount=int(keyCount/100)
- progressCount=1000
-
- # import
- last_frame=0
- for o in scene.objects.selected:
- if o.type=='Armature':
- last_frame=max(last_frame, import_motion_key(l, o, progressCount))
- elif o.type=='Mesh':
- last_frame=max(last_frame, import_shape_key(l, o, progressCount))
-
- # set end frame
- scene.getRenderingContext().eFrame = last_frame
- print 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.')
-
+++ /dev/null
-# coding: utf-8
-
-__author__= ['ousttrue']
-__url__ = ("")
-__version__= '20100515 0.2:'
-__bpydoc__= '''\
-vmd Importer
-
-This script imports a vmd into Blender for editing.
-0.1 2010/05/15 first implement.
-0.2 2010/05/16 implement bone animation.
-0.3 2010/05/16 implement shape key animation.
-'''
-
-import bpy
-from bpy.props import *
-import mathutils
-import sys
-import os
-import math
-from meshio import vmd, englishmap
-
-
-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=mathutils.Quaternion()
- q.w=l.w*r.w-(l.x*r.x+l.y*r.y+l.z*r.z)
- 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):
- print('import_motion_key: %s' % o.name)
-
-
- armature = o.data
- pose = o.pose
- not_in_map={}
- not_found={}
- counter=0
- last_frame=0
- for n in l.boneKeys:
- keyFrames=l.getBoneKeyFrameList(n)
- boneName=englishmap.getEnglishBoneName(n)
- try:
- bone=armature.bones[boneName]
- # rot
- armRotate=bone.matrix_local.rotation_part()
- # quat
- armRotateQuaternion=armRotate.to_quat()
-
- # inv
- armRotateInv=mathutils.Matrix(armRotate).transpose()
- # quat
- armRotateInvQuaternion=armRotateInv.to_quat()
-
- reverseFlag=False
- lastQ=None
-
- poseBone=pose.bones[boneName]
- for i in range(len(keyFrames.list)):
- key=keyFrames.getKey(i)
- ####################
- # rotation
- ####################
- if lastQ and lastQ.dot(key.q)<0:
- reverseFlag=not reverseFlag
- lastQ=key.q
-
- # convert left-handed y-up to right-handed z-up
- if reverseFlag:
- # reverse quaternion for slerp
- q=mathutils.Quaternion()
- q.w=-key.q.w
- q.x=key.q.x
- q.y=key.q.z
- q.z=key.q.y
- else:
- q=mathutils.Quaternion()
- q.w=key.q.w
- q.x=-key.q.x
- q.y=-key.q.z
- q.z=-key.q.y
-
- poseBone.rotation_quaternion=multQuat(
- armRotateInvQuaternion,
- multQuat(q, armRotateQuaternion))
-
- ####################
- # location
- ####################
- poseBone.location = mathutils.Vector(
- (float(key.pos.x), float(key.pos.z), float(key.pos.y)))
-
- # insert
- poseBone.keyframe_insert(
- 'location', -1, keyFrames.getFrame(i))
- poseBone.keyframe_insert(
- 'rotation_quaternion', -1, keyFrames.getFrame(i))
-
- last_frame=max(last_frame, keyFrames.getFrame(i))
- counter+=1
-
- except KeyError as msg:
- not_found[boneName]=True
- continue
-
- print("bone not exists")
- for name in not_found.keys():
- print(name)
-
- return last_frame
-
-
-def IPO_CURVE_get_or_create(ipo, name):
- for c in ipo:
- if c.name == name:
- return c
- return ipo.addCurve(name)
-
-
-def getKey(mesh, name):
- for shapeKey in mesh.shape_keys.keys:
- if shapeKey.name==name:
- return shapeKey
-
-
-def import_shape_key(l, meshObject):
- print('import_shape_key: %s' % meshObject.name)
-
- # insert shape keys
- counter=0
- last_frame=0
-
- for n in l.morphKeys:
- keyFrames=l.getMorphKeyFrameList(n)
- if n=='base':
- continue
- name=englishmap.getEnglishSkinName(n)
- if not name:
- name=n
-
- shapeKey=getKey(meshObject.data, name)
-
- if not shapeKey:
- print("not found shapeKey: %s" % name)
- continue
-
- for i in range(len(keyFrames.list)):
- key=keyFrames.getKey(i)
- shapeKey.value=key.weight
- frame=keyFrames.getFrame(i)
- shapeKey.keyframe_insert("value", -1, frame)
-
- last_frame=max(last_frame, frame)
-
- counter+=1
-
- return last_frame
-
-
-def load(filename, context):
- """
- load vmd file to context.
- """
- io=vmd.IO()
- if not io.read(filename):
- print("fail to read", filename)
- return
-
- scene=context.scene
-
- # import
- last_frame=0
- for o in scene.objects:
- if o.selected:
- if o.data.__class__ is bpy.types.Armature:
- last_frame=max(
- last_frame, import_motion_key(io, o))
- elif o.data.__class__ is bpy.types.Mesh:
- last_frame=max(
- last_frame, import_shape_key(io, o))
-
- # set end frame
- scene.frame_end = last_frame
- print("last frame: %d" % last_frame)
-
- # redraw
- scene.update()
-
- print("finised")
-
-
-###############################################################################
-# import operator
-###############################################################################
-class IMPORT_OT_vmd(bpy.types.Operator):
- bl_idname = "import_anim.vmd"
- bl_label = 'Import VMD'
-
- # List of operator properties, the attributes will be assigned
- # to the class instance from the operator settings before calling.
- path = StringProperty(
- name="File Path",
- description="File path used for importing the VMD file",
- maxlen= 1024, default= "")
- filename = StringProperty(
- name="File Name",
- description="Name of the file.")
- directory = StringProperty(
- name="Directory",
- description="Directory of the file.")
-
- def execute(self, context):
- load(self.properties.path, context)
- return {'FINISHED'}
-
- def invoke(self, context, event):
- wm = context.manager
- wm.add_fileselect(self)
- return {'RUNNING_MODAL'}
-
-
-###############################################################################
-# register menu
-###############################################################################
-def menu_func(self, context):
- self.layout.operator(IMPORT_OT_vmd.bl_idname,
- text="MikuMikuDance motion (.vmd)")
-
-def register():
- bpy.types.register(IMPORT_OT_vmd)
- bpy.types.INFO_MT_file_import.append(menu_func)
-
-def unregister():
- bpy.types.unregister(IMPORT_OT_vmd)
- bpy.types.INFO_MT_file_import.remove(menu_func)
-
-
-if __name__=="__main__":
- register()
-
+++ /dev/null
-# coding: utf-8
-
-__author__= ['ousttrue']
-__url__ = ("")
-__version__= '20100508 0.1:'
-__bpydoc__= '''\
-mqo Importer
-
-This script imports a mqo into Blender for editing.
-'''
-
-import bpy
-from bpy.props import *
-import sys
-import os
-from meshio import mqo
-
-
-SCALING=1.0
-
-
-def create_texture(directory, texture_name):
- texture=bpy.data.textures.new(texture_name)
- texture.type='IMAGE'
- texture=texture.recast_type()
- #texturePath="%s/%s" % (directory, texture_name)
- texturePath=os.path.join(directory, texture_name)
- print('create_texture', texturePath)
- image=bpy.data.images.load(texturePath)
- texture.image=image
- texture.mipmap = True
- texture.interpolation = True
- texture.use_alpha = True
- return texture
-
-def create_materials(mqo, scene, directory):
- materials = []
- textureMap={}
- imageMap={}
- if len(mqo.materials)>0:
- for material_index, m in enumerate(mqo.materials):
- material = bpy.data.materials.new(m.getName())
- materials.append(material)
- # mqo material
- material.diffuse_color=[m.color.r, m.color.g, m.color.b]
- material.alpha=m.color.a
- material.diffuse_intensity=m.diffuse
- texture_name=m.getTexture()
- if texture_name!='':
- if texture_name in textureMap:
- texture=textureMap[texture_name]
- else:
- texture=create_texture(directory, texture_name)
- textureMap[texture_name]=texture
- imageMap[material_index]=texture.image
- #material.add_texture(texture, "UV", {"COLOR", "ALPHA"})
- material.add_texture(texture, "UV", "COLOR")
- # temporary
- material.emit=1.0
- else:
- material = bpy.data.materials.new('Default')
- materials.append(material)
- return materials, imageMap
-
-def create_objects(mqo, scene, parent, materials, imageMap):
- for o in mqo.objects:
-
- # create mesh
- mesh=bpy.data.meshes.new("Mesh")
- meshObject= bpy.data.objects.new(o.getName(), mesh)
- scene.objects.link(meshObject)
- meshObject.parent=parent
-
- # count triangle and quadrangle
- faceCount=0
- for f in o.faces:
- if f.index_count==3 or f.index_count==4:
- faceCount+=1
- mesh.add_geometry(len(o.vertices), 0, faceCount)
-
- # add vertex
- unpackedVertices=[]
- for v in o.vertices:
- # convert right-handed y-up to right-handed z-up
- unpackedVertices.extend(
- (SCALING*v.x, SCALING*-v.z, SCALING*v.y))
- mesh.verts.foreach_set("co", unpackedVertices)
-
- # add face
- unpackedFaces = []
- usedMaterial=set()
-
- def getFace(f):
- face = []
- for i in range(f.index_count):
- face.append(f.getIndex(i))
- return face
-
- for f in o.faces:
- face=getFace(f)
- if len(face) != 3 and len(face) != 4:
- print("{0} vertices in face.".format(len(face)))
- continue
-
- if len(face) == 4:
- if face[3] == 0:
- # rotate indices if the 4th is 0
- face = [face[3], face[0], face[1], face[2]]
- elif len(face) == 3:
- if face[2] == 0:
- # rotate indices if the 3rd is 0
- face = [face[2], face[0], face[1], 0]
- else:
- face.append(0)
-
- unpackedFaces.extend(face)
- usedMaterial.add(f.material_index)
- try:
- mesh.faces.foreach_set("verts_raw", unpackedFaces)
- except:
- #print([getFace(f) for f in o.faces])
- print("fail to mesh.faces.foreach_set")
- return
-
- # add material
- meshMaterialMap={}
- materialIndex=0
- for i in usedMaterial:
- mesh.add_material(materials[i])
- meshMaterialMap[i]=materialIndex
- materialIndex+=1
-
- # each face
- mesh.add_uv_texture()
- for mqo_face, blender_face, uv_face in zip(
- o.faces, mesh.faces, mesh.uv_textures[0].data):
- if mqo_face.index_count<3:
- continue
- blender_face.material_index=meshMaterialMap[mqo_face.material_index]
- if mqo_face.index_count>=3:
- uv_face.uv1=[mqo_face.getUV(0).x, 1.0-mqo_face.getUV(0).y]
- uv_face.uv2=[mqo_face.getUV(1).x, 1.0-mqo_face.getUV(1).y]
- uv_face.uv3=[mqo_face.getUV(2).x, 1.0-mqo_face.getUV(2).y]
- if mqo_face.index_count==4:
- uv_face.uv4=[
- mqo_face.getUV(3).x, 1.0-mqo_face.getUV(3).y]
- if materials[mqo_face.material_index] in imageMap:
- uv_face.image=imageMap[mqo_face.material_index]
- uv_face.tex=True
-
- mesh.update()
-
-def load(filename, context):
- """
- load mqo file to context.
- """
- io=mqo.IO()
- if not io.read(filename):
- print("fail to load",filename)
- return
-
- scene=context.scene
-
- # create material
- materials, imageMap=create_materials(
- io, scene, os.path.dirname(filename))
-
- # create group
- empty=bpy.data.objects.new(os.path.basename(filename), None)
- scene.objects.link(empty)
-
- # create mesh
- create_objects(io, scene, empty, materials, imageMap)
-
-
-###############################################################################
-# import operator
-###############################################################################
-class IMPORT_OT_mqo(bpy.types.Operator):
- '''Import from Metasequoia file format (.mqo)'''
- bl_idname = "import_scene.mqo"
- bl_label = 'Import MQO'
-
- # List of operator properties, the attributes will be assigned
- # to the class instance from the operator settings before calling.
-
- path = StringProperty(
- name="File Path",
- description="File path used for importing the MQO file",
- maxlen= 1024, default= "")
- filename = StringProperty(
- name="File Name",
- description="Name of the file.")
- directory = StringProperty(
- name="Directory",
- description="Directory of the file.")
-
- def execute(self, context):
- load(self.properties.path, context)
- return {'FINISHED'}
-
- def invoke(self, context, event):
- wm = context.manager
- wm.add_fileselect(self)
- return {'RUNNING_MODAL'}
-
-
-###############################################################################
-# register menu
-###############################################################################
-def menu_func(self, context):
- self.layout.operator(IMPORT_OT_mqo.bl_idname,
- text="Metasequoia (.mqo)")
-
-def register():
- bpy.types.register(IMPORT_OT_mqo)
- bpy.types.INFO_MT_file_import.append(menu_func)
-
-def unregister():
- bpy.types.unregister(IMPORT_OT_mqo)
- bpy.types.INFO_MT_file_import.remove(menu_func)
-
-
-if __name__=="__main__":
- register()
-
+++ /dev/null
-# coding: utf-8
-
-__author__= ['ousttrue']
-__url__ = ("")
-__version__= '20100508 0.1:'
-__bpydoc__= '''\
-pmd Importer
-
-This script imports a pmd into Blender for editing.
-'''
-
-import bpy
-from bpy.props import *
-import mathutils
-import sys
-import os
-import math
-from meshio import pmd, englishmap
-
-
-def to_radian(degree):
- return math.pi * degree / 180
-
-
-def convert_coord(pos):
- """
- Left handed y-up to Right handed z-up
- """
- return (pos.x, pos.z, pos.y)
-
-
-def convert_uv(uv):
- return (uv.x, 1.0 - uv.y)
-
-
-def getBoneName(bone):
- name = englishmap.getEnglishBoneName(bone.getName())
- return name if name else bone.getName()
-
-
-def create_texture(directory, texture_name):
- texture=bpy.data.textures.new(texture_name)
- texture.type='IMAGE'
- texture=texture.recast_type()
- texturePath=os.path.join(directory, texture_name)
- print('create_texture', texturePath)
- image=bpy.data.images.load(texturePath)
- texture.image=image
- texture.mipmap = True
- texture.interpolation = True
- texture.use_alpha = True
- return texture
-
-
-def createMaterial():
- """
- create default materil
- """
- material = bpy.data.materials.new("Material")
- material.diffuse_shader='TOON'
- material.specular_shader='TOON'
- # temporary
- material.emit=1.0
- return material
-
-
-def importMesh(scene, l, tex_dir):
- """
- @param l[in] mmd.PMDLoader
- @param filename[in]
- """
-
- ############################################################
- # shpae\e$B%-!<$G;H$o$l$k%^%F%j%"%kM%@hE*$KA0$KJB$Y$k\e(B
- ############################################################
- # shape\e$B%-!<$G;H$o$l$kD:E@%$%s%G%C%/%9$r=8$a$k\e(B
- 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)
-
- # \e$B%^%F%j%"%k$K4^$^$l$kD:E@$,\e(Bshape_key\e$B$K4^$^$l$k$+H]$+!)\e(B
- def isMaterialUsedInShape(offset, m):
- for i in range(offset, offset+m.vertex_count):
- if l.indices[i] in shape_key_used_vertices:
- return True
-
- # shape\e$B%-!<$G;H$o$l$k%^%F%j%"%k$r5-O?$9$k\e(B
- shape_key_materials=set()
- # \e$B3F%^%F%j%"%k$N3+;OD:E@%$%s%G%C%/%9$r5-O?$9$k\e(B
- 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\e$B%-!<$G;H$o$l$k%^%F%j%"%k$rA0$KJB$Y$k%$%s%G%C%/%9%^%C%W$r:n$k\e(B
- 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
-
- # \e$B%^%F%j%"%k\e(B16\e$B8D$4$H$KJ,3d$7$?%a%C%7%e$r:n@.$9$k\e(B
- material_index=0
- mesh_objects=[]
- while material_index<len(l.materials):
- # shape\e$B%-!<$G;H$o$l$k=g$KJB$Y$J$*$7$?%^%F%j%"%k\e(B16\e$B8DJ,$N\e(B
- # \e$B%a%C%7%e$r:n@.$9$k\e(B
- meshObject, used_vertices=import16MaerialAndMesh(l,
- material_index, material_map, face_map, tex_dir)
- scene.objects.link(meshObject)
- scene.update()
- mesh_objects.append(meshObject)
-
- # enter Edit Mode
- bpy.ops.object.select_all(action='DESELECT')
- meshObject.selected=True
- scene.objects.active=meshObject
- bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
-
- # crete shape key
- importShape(meshObject, l)
-
- ############################################################
- # clean up not used vertices
- ############################################################
- #progress_print('clean up vertices not used')
- vertex_map={}
- mesh=meshObject.data
- for i, v in enumerate(mesh.verts):
- if i in used_vertices:
- vertex_map[i]=len(vertex_map)
- v.selected=False
- else:
- v.selected=True
- assert(mesh.verts[i].selected)
- bpy.ops.object.mode_set(mode='EDIT', toggle=False)
- print("%d vertices selected" % mesh.total_vert_sel)
- print("used %d/%d" % (len(vertex_map), len(mesh.verts)))
- bpy.ops.mesh.delete(type='VERT')
-
- ############################################################
- # flip face
- ############################################################
- bpy.ops.mesh.select_all(action='SELECT')
- bpy.ops.mesh.flip_normals()
- bpy.ops.mesh.select_all(action='DESELECT')
-
- # exit Edit Mode
- bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
-
- mesh.update()
- material_index+=16
-
- return mesh_objects
-
-
-def import16MaerialAndMesh(l,
- material_offset, material_map, face_map, tex_dir):
- # create mesh
- mesh=bpy.data.meshes.new("Mesh")
-
- # create object
- meshObject= bpy.data.objects.new("Mesh", mesh)
- meshObject.layers[0]=True
-
- ############################################################
- # material
- ############################################################
- #progress_print('create materials')
- mesh_material_map={}
- materials=[]
- textureMap={}
- imageMap={}
- index=0
- for i in range(material_offset, material_offset+16):
- try:
- material_index=material_map[i]
- m=l.materials[material_index]
- mesh_material_map[material_index]=index
- except KeyError:
- break
-
- material=createMaterial()
- material.diffuse_color=([m.diffuse.r, m.diffuse.g, m.diffuse.b])
- material.alpha=m.diffuse.a
- material.specular_hardness=int(m.shinness)
- material.specular_color=([m.specular.r, m.specular.g, m.specular.b])
- material.mirror_color=([m.ambient.r, m.ambient.g, m.ambient.b])
- texture_name=m.getTexture()
- if texture_name!='':
- if texture_name in textureMap:
- texture=textureMap[texture_name]
- else:
- texture=create_texture(tex_dir, texture_name)
- textureMap[texture_name]=texture
- imageMap[material_index]=texture.image
- #material.add_texture(texture, "UV", {"COLOR", "ALPHA"})
- material.add_texture(texture, "UV", "COLOR")
-
- materials.append(material)
- mesh.add_material(material)
- # lookup table for assign
- index+=1
-
- ############################################################
- # vertex
- ############################################################
- #progress_print('create vertices')
- # create vertices
- vertex_groups={}
- unpackedVertices=[]
- for v in l.each_vertex():
- unpackedVertices.extend(
- convert_coord(v.pos))
- vertex_groups[v.bone0]=True
- vertex_groups[v.bone1]=True
-
- ############################################################
- # face
- ############################################################
- #progress_print('create faces')
- # create faces
- mesh_face_indices=[]
- mesh_face_materials=[]
- used_vertices=set()
- for i in range(material_offset, material_offset+16):
- try:
- material_index=material_map[i]
- except KeyError:
- break
- face_offset=face_map[material_index]
- m=l.materials[material_index]
- material_faces=l.indices[face_offset:face_offset+m.vertex_count]
- for j in range(0, len(material_faces), 3):
- i0=material_faces[j]
- i1=material_faces[j+1]
- i2=material_faces[j+2]
- if i2==0:
- mesh_face_indices.extend([i2, i0, i1, 0])
- else:
- mesh_face_indices.extend([i0, i1, i2, 0])
- mesh_face_materials.append(material_index)
- used_vertices.add(i0)
- used_vertices.add(i1)
- used_vertices.add(i2)
-
- ############################################################
- # create vertices & faces
- ############################################################
- mesh.add_geometry(
- int(len(unpackedVertices)/3), 0, int(len(mesh_face_indices)/4))
- mesh.verts.foreach_set("co", unpackedVertices)
- mesh.faces.foreach_set("verts_raw", mesh_face_indices)
- assert(len(l.vertices)==len(mesh.verts))
-
- ############################################################
- # face params
- ############################################################
- used_map={}
- mesh.add_uv_texture()
-
- for face, uv_face, material_index in zip(mesh.faces,
- mesh.uv_textures[0].data,
- mesh_face_materials,
- ):
- try:
- index=mesh_material_map[material_index]
- except KeyError as message:
- print(message, mesh_material_map, m)
- assert(False)
- face.material_index=index
- material=mesh.materials[index]
- used_map[index]=True
- if material.texture_slots[0]:
- #texture=material.texture_slots[0].texture
- #face.image=texture.image
- #texture.imageFlags|=Blender.Texture.ImageFlags.USEALPHA
- uv=l.getUV(face.verts[0])
- uv_face.uv1=[uv.x, 1.0-uv.y]
-
- uv=l.getUV(face.verts[1])
- uv_face.uv2=[uv.x, 1.0-uv.y]
-
- uv=l.getUV(face.verts[2])
- uv_face.uv3=[uv.x, 1.0-uv.y]
- if face.material_index in imageMap:
- uv_face.image=imageMap[face.material_index]
- uv_face.tex=True
-
- # set smooth
- face.smooth = 1
-
- ############################################################
- # vertex weight
- ############################################################
- # create vertex group
- for i in vertex_groups.keys():
- meshObject.add_vertex_group(getBoneName(l.bones[i]))
-
- # vertex params
- for i, v, mvert in zip(range(len(l.vertices)),
- l.each_vertex(), mesh.verts):
- mvert.normal=mathutils.Vector(convert_coord(v.normal))
- #mvert.uvco=convert_uv(v.uv)
- w1=float(v.weight0)/100.0
- w2=1.0-w1
-
- meshObject.add_vertex_to_group(i,
- meshObject.vertex_groups[getBoneName(l.bones[v.bone0])], w1, 'ADD')
- meshObject.add_vertex_to_group(i,
- meshObject.vertex_groups[getBoneName(l.bones[v.bone1])], w2, 'ADD')
- mesh.update()
-
- #progress_print('%s created' % mesh.name)
- return meshObject, used_vertices
-
-
-def build_bone(armature, b, parent=None):
- if b.tail_index==0:
- return
-
- name=getBoneName(b)
- bone = armature.edit_bones.new(name if name else b.getName())
- if parent:
- bone.head = mathutils.Vector(convert_coord(b.pos))
- bone.parent=parent
- bone.connected=True if parent.tail==bone.head else False
- bone.tail = mathutils.Vector(convert_coord(b.tail))
- if bone.head==bone.tail:
- bone.tail=bone.head-mathutils.Vector((0, 1, 0))
- elif b.__class__ is pmd.BONE_IK:
- bone.head = mathutils.Vector(convert_coord(b.pos))
- bone.tail = mathutils.Vector(convert_coord(b.tail))
- else:
- # center
- tail=mathutils.Vector(convert_coord(b.pos))
- bone.tail = tail
- bone.head = tail-mathutils.Vector((0, 1, 0))
-
- for child in b.children:
- build_bone(armature, child, bone)
-
-
-def importArmature(scene, l):
- # create armature
- armature = bpy.data.armatures.new('Armature')
- # link to object
- armature_object=bpy.data.objects.new('Armature', armature)
- scene.objects.link(armature_object)
- armature_object.x_ray=True
-
- # armature settings
- armature.drawtype='OCTAHEDRAL'
- armature.deform_envelope=False
- armature.deform_vertexgroups=True
- armature.x_axis_mirror=True
-
- # create action
- #act = Blender.Armature.NLA.NewAction()
- #act.setActive(armature_object)
-
- # select only armature object and set edit mode
- scene.objects.active=armature_object
- bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
- bpy.ops.object.mode_set(mode='EDIT', toggle=False)
-
- # create armature
- for b in l.bones:
- if not b.parent:
- build_bone(armature, b)
-
- bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
- bpy.ops.object.select_all(action='DESELECT')
-
- ############################################################
- # IK
- ############################################################
- pose = armature_object.pose
- for ik in l.ik_list:
- effector=l.bones[ik.target]
- parent=l.bones[effector.parent_index]
- name=getBoneName(parent)
- p_bone = pose.bones[name]
- if not p_bone:
- print('not found', name)
- continue
- if len(ik.children) >= 16:
- print('over MAX_CHAINLEN', ik, len(ik.children))
- continue
- # IK
- ik_const = p_bone.constraints.new('IK')
- ik_const.chain_length=len(ik.children)
- ik_const.target=armature_object
- ik_const.subtarget=getBoneName(l.bones[ik.index])
- # ROT
- rot_const = p_bone.constraints.new('LIMIT_ROTATION')
- rot_const.influence = ik.weight
- rot_const.owner_space = 'LOCAL'
- rot_const.use_limit_x=True
- rot_const.use_limit_z=True
- rot_const.minimum_x=to_radian(ik.iterations)
- rot_const.maximum_x=to_radian(180)
- rot_const.minimum_z=to_radian(180 - ik.iterations)
- rot_const.maximum_z=to_radian(0)
-
- return armature_object
-
-
-def importShape(meshObject, l):
- 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)
-
- # create base key
- baseblock=meshObject.add_shape_key("Basis")
-
- # mesh
- mesh=meshObject.data
-
- # each skin
- for s in l.morph_list:
- if s.getName()==base.name:
- # skip base
- continue
-
- # restore
- #for v, base_pos in zip(mesh.verts, baseblock.data):
- # v.co=base_pos.co
- #mesh.update()
-
- # name
- name=englishmap.getEnglishSkinName(s.getName())
- if not name:
- name=s.getName()
- new_shape_key=meshObject.add_shape_key(name)
- #new_shape_key.value=1.0
-
- # morph
- for i, offset in zip(s.indices, s.pos_list):
- try:
- vertex_index=base.indices[i]
- new_shape_key.data[vertex_index].co=[p+o for p, o in zip(
- mesh.verts[vertex_index].co, convert_coord(offset))]
- except IndexError as msg:
- print(IndexError, msg)
- print(i, len(base.indices))
- print(vertex_index, len(mesh.verts))
- print(base.indices[i])
- break
- except KeyError:
- #print 'this mesh not has shape vertices'
- break
-
- # set ipo curve
- #icu=ipo.addCurve(name)
- #icu.interpolation = Blender.IpoCurve.InterpTypes.LINEAR
- #icu.append( (0.0, 0.0) )
-
-
-def load(filename, context):
- """
- load pmd file to context.
- """
- io=pmd.IO()
- if not io.read(filename):
- print("fail to read", filename)
- return
-
- scene=context.scene
-
- # create root object
- root=bpy.data.objects.new(os.path.basename(filename), None)
- scene.objects.link(root)
-
- # import mesh
- mesh_objects=importMesh(scene, io, os.path.dirname(filename))
- for o in mesh_objects:
- o.parent=root
-
- # import armature
- armature_object=importArmature(scene, io)
- if armature_object:
- armature_object.parent=root
- armature = armature_object.data
- armature.draw_names=True
-
- # add armature modifier
- for o in mesh_objects:
- mod=o.modifiers.new("Modifier", "ARMATURE")
- mod.object = armature_object
- mod.use_bone_envelopes=False
- #o.makeDisplayList()
-
-
- # select objects
- root.selected=True
- for o in mesh_objects:
- o.selected=True
- armature_object.selected=True
-
- # redraw
- scene.update()
-
- print("finised")
-
-
-###############################################################################
-# import operator
-###############################################################################
-class IMPORT_OT_pmd(bpy.types.Operator):
- bl_idname = "import_scene.pmd"
- bl_label = 'Import PMD'
-
- # List of operator properties, the attributes will be assigned
- # to the class instance from the operator settings before calling.
-
- path = StringProperty(
- name="File Path",
- description="File path used for importing the PMD file",
- maxlen= 1024, default= "")
- filename = StringProperty(
- name="File Name",
- description="Name of the file.")
- directory = StringProperty(
- name="Directory",
- description="Directory of the file.")
-
- def execute(self, context):
- load(self.properties.path, context)
- return {'FINISHED'}
-
- def invoke(self, context, event):
- wm = context.manager
- wm.add_fileselect(self)
- return {'RUNNING_MODAL'}
-
-
-###############################################################################
-# register menu
-###############################################################################
-def menu_func(self, context):
- self.layout.operator(IMPORT_OT_pmd.bl_idname,
- text="MikuMikuDance model (.pmd)")
-
-def register():
- bpy.types.register(IMPORT_OT_pmd)
- bpy.types.INFO_MT_file_import.append(menu_func)
-
-def unregister():
- bpy.types.unregister(IMPORT_OT_pmd)
- bpy.types.INFO_MT_file_import.remove(menu_func)
-
-
-if __name__=="__main__":
- register()
-
('blender25', [
'blender25/README',
]),
- ('blender25/io', [
- 'blender/io/bl25.py',
- 'blender/io/import_scene_mqo.py',
- 'blender/io/export_scene_mqo.py',
- 'blender/io/import_scene_pmd.py',
- 'blender/io/export_scene_pmd.py',
+ ('blender25/addons', [
+ 'blender/addons/bl25.py',
+ 'blender/addons/io_import_scene_mqo.py',
+ 'blender/addons/io_export_scene_mqo.py',
+ 'blender/addons/io_import_scene_pmd.py',
+ 'blender/addons/io_export_scene_pmd.py',
]),
]
for i in range(len(ext_modules)+1):
try:
setup(name="meshio",
- version='1.00',
+ version='1.01',
description='polygon mesh io utilities',
author='ousttrue',
author_email='ousttrue@gmail.com',