--- /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 Node(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]=Node(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
+ root=object_node_map[scene.objects.active]\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