+++ /dev/null
-# coding: utf-8\r
-""" \r
-MQOの読み込み\r
-http://www.metaseq.net/metaseq/format.html\r
-"""\r
-\r
-import os\r
-import sys\r
-import math\r
-\r
-\r
-class RGBA(object):\r
- """mqo color"""\r
- __slots__=['r', 'g', 'b', 'a']\r
- def __init__(self, r=0, g=0, b=0, a=0):\r
- self.r=r\r
- self.g=g\r
- self.b=b\r
- self.a=a\r
-\r
- def __getitem__(self, key):\r
- if key==0:\r
- return self.r\r
- elif key==1:\r
- return self.g\r
- elif key==2:\r
- return self.b\r
- elif key==3:\r
- return self.a\r
- else:\r
- assert(False)\r
-\r
-\r
-class Vector3(object):\r
- """3D coordinate"""\r
- __slots__=['x', 'y', 'z']\r
- def __init__(self, x=0, y=0, z=0):\r
- self.x=x\r
- self.y=y\r
- self.z=z\r
-\r
- def __str__(self):\r
- return "[%f, %f, %f]" % (self.x, self.y, self.z)\r
-\r
- def __sub__(self, rhs):\r
- return Vector3(self.x-rhs.x, self.y-rhs.y, self.z-rhs.z)\r
-\r
- def getSqNorm(self):\r
- return self.x*self.x + self.y*self.y + self.z*self.z\r
-\r
- def getNorm(self):\r
- return math.sqrt(self.getSqNorm())\r
-\r
- def normalize(self):\r
- factor=1.0/self.getNorm()\r
- self.x*=factor\r
- self.y*=factor\r
- self.z*=factor\r
- return self\r
-\r
- def to_a(self):\r
- return [self.x, self.y, self.z]\r
-\r
- @staticmethod\r
- def dot(lhs, rhs):\r
- """dot(inner) product"""\r
- return lhs.x*rhs.x + lhs.y*rhs.y + lhs.z*rhs.z\r
-\r
- @staticmethod\r
- def cross(lhs, rhs):\r
- """cross(outer) product"""\r
- return Vector3(\r
- lhs.y*rhs.z - rhs.y*lhs.z,\r
- lhs.z*rhs.x - rhs.z*lhs.x,\r
- lhs.x*rhs.y - rhs.x*lhs.y,\r
- )\r
-\r
-\r
-class Vector2(object):\r
- """2d coordinate"""\r
- __slots__=['x', 'y']\r
- def __init__(self, x=0, y=0):\r
- self.x=x\r
- self.y=y\r
-\r
- def __str__(self):\r
- return "[%f, %f]" % (self.x, self.y)\r
-\r
- def __sub__(self, rhs):\r
- return Vector3(self.x-rhs.x, self.y-rhs.y)\r
-\r
- @staticmethod\r
- def cross(lhs, rhs):\r
- """cross(outer) product"""\r
- return lhs.x*rhs.y-lhs.y*rhs.x\r
-\r
-\r
-"""\r
-MQO loader\r
-"""\r
-class Material(object):\r
- """mqo material\r
-\r
- Attributes:\r
- name: cp932\r
- shader: \r
- color: rgba\r
- diffuse:\r
- ambient:\r
- emit:\r
- specular:\r
- power:\r
- tex: cp932 windows file path\r
- """\r
- __slots__=[\r
- "name", "shader", "color", "diffuse", \r
- "ambient", "emit", "specular", "power",\r
- "tex",\r
- ]\r
- def __init__(self, name):\r
- self.name=name\r
- self.shader=3\r
- self.color=RGBA(0.5, 0.5, 0.5, 1.0)\r
- self.diffuse=1.0\r
- self.ambient=0.0\r
- self.emit=0.0\r
- self.specular=0.0\r
- self.power=5.0\r
- self.tex=""\r
-\r
- def getName(self): return self.name\r
- def getTexture(self): return self.tex\r
-\r
- def parse(self, line):\r
- offset=0\r
- while True:\r
- leftParenthesis=line.find("(", offset)\r
- if leftParenthesis==-1:\r
- break\r
- key=line[offset:leftParenthesis]\r
- rightParenthesis=line.find(")", leftParenthesis+1)\r
- if rightParenthesis==-1:\r
- raise ValueError("assert")\r
-\r
- param=line[leftParenthesis+1:rightParenthesis]\r
- if key=="shader":\r
- self.shader=int(param)\r
- elif key=="col":\r
- self.color=RGBA(*[float(e) for e in param.split()])\r
- elif key=="dif":\r
- self.diffuse=float(param)\r
- elif key=="amb":\r
- self.ambient=float(param)\r
- elif key=="emi":\r
- self.emit=float(param)\r
- elif key=="spc":\r
- self.specular=float(param)\r
- elif key=="power":\r
- self.power=float(param)\r
- elif key=="tex":\r
- self.tex=param[1:-1]\r
- else:\r
- print(\r
- "%s#parse" % self.name, \r
- "unknown key: %s" % key\r
- )\r
-\r
- offset=rightParenthesis+2\r
-\r
- def __str__(self):\r
- return "<Material %s shader: %d [%f, %f, %f, %f] %f>" % (\r
- self.name, self.shader,\r
- self.color[0], self.color[1], self.color[2], self.color[3],\r
- self.diffuse)\r
-\r
-\r
-class Obj(object):\r
- """mqo object\r
-\r
- Attributes:\r
- name: cp932\r
- depth: object hierarchy \r
- folding: \r
- scale:\r
- rotation:\r
- translation:\r
- visible:\r
- locking:\r
- shading:\r
- facet: smoothing threshold\r
- color:\r
- color_type:\r
- mirror: mirroring\r
- mirror_axis:\r
- vertices:\r
- faces:\r
- edges:\r
- smoothing:\r
- """\r
- __slots__=["name", "depth", "folding", \r
- "scale", "rotation", "translation",\r
- "visible", "locking", "shading", "facet",\r
- "color", "color_type", "mirror", "mirror_axis",\r
- "vertices", "faces", "edges", "smoothing",\r
- ]\r
-\r
- def __init__(self, name):\r
- self.name=name\r
- self.vertices=[]\r
- self.faces=[]\r
- self.edges=[]\r
- self.depth=0\r
- self.folding=0\r
- self.scale=[1, 1, 1]\r
- self.rotation=[0, 0, 0]\r
- self.translation=[0, 0, 0]\r
- self.visible=15\r
- self.locking=0\r
- self.shading=0\r
- self.facet=59.5\r
- self.color=[1, 1, 1]\r
- self.color_type=0\r
- self.mirror=0\r
- self.smoothing=0\r
-\r
- def getName(self): return self.name\r
-\r
- def addVertex(self, x, y, z):\r
- self.vertices.append(Vector3(x, y, z))\r
-\r
- def addFace(self, face):\r
- if face.index_count==2:\r
- self.edges.append(face)\r
- else:\r
- self.faces.append(face)\r
-\r
- def __str__(self):\r
- return "<Object %s, %d vertices, %d faces>" % (\r
- self.name, len(self.vertices), len(self.faces))\r
-\r
-\r
-class Face(object):\r
- """mqo face\r
-\r
- Attributes:\r
- index_count: 2 or 3 or 4\r
- indices: index x index_count\r
- material_index:\r
- col: vertex_color x index_count\r
- uv: Vector2 x index_count\r
- """\r
- __slots__=[\r
- "index_count",\r
- "indices", "material_index", "col", "uv",\r
- ]\r
- def __init__(self, index_count, line):\r
- if index_count<2 or index_count>4:\r
- raise ValueError("invalid vertex count: %d" % index_count)\r
- self.material_index=0\r
- self.col=[]\r
- self.uv=[Vector2(0, 0)]*4\r
- self.index_count=index_count\r
- offset=0\r
- while True:\r
- leftParenthesis=line.find("(", offset)\r
- if leftParenthesis==-1:\r
- break\r
- key=line[offset:leftParenthesis]\r
- rightParenthesis=line.find(")", leftParenthesis+1)\r
- if rightParenthesis==-1:\r
- raise ValueError("assert")\r
- params=line[leftParenthesis+1:rightParenthesis].split()\r
- if key=="V":\r
- self.indices=[int(e) for e in params]\r
- elif key=="M":\r
- self.material_index=int(params[0])\r
- elif key=="UV":\r
- uv_list=[float(e) for e in params]\r
- self.uv=[]\r
- for i in range(0, len(uv_list), 2):\r
- self.uv.append(Vector2(uv_list[i], uv_list[i+1]))\r
- elif key=="COL":\r
- for n in params:\r
- d=int(n)\r
- # R\r
- d, m=divmod(d, 256)\r
- self.col.append(m)\r
- # G\r
- d, m=divmod(d, 256)\r
- self.col.append(m)\r
- # B\r
- d, m=divmod(d, 256)\r
- self.col.append(m)\r
- # A\r
- d, m=divmod(d, 256)\r
- self.col.append(m)\r
- else:\r
- print("Face#__init__:unknown key: %s" % key)\r
-\r
- offset=rightParenthesis+2\r
-\r
- def getIndex(self, i): return self.indices[i]\r
- def getUV(self, i): return self.uv[i] if i<len(self.uv) else Vector2(0, 0)\r
-\r
-\r
-def withio(method):\r
- def new(self, path):\r
- print(sys.version_info[0])\r
- if sys.version_info[0]<3:\r
- self.io=open(path)\r
- else:\r
- self.io=open(path, encoding='cp932')\r
- result=method(self)\r
- self.io.close()\r
- self.io=None\r
- return result\r
- return new\r
-\r
-\r
-class IO(object):\r
- """mqo loader\r
- """\r
- __slots__=[\r
- "has_mikoto",\r
- "eof", "io", "lines",\r
- "materials", "objects",\r
- ]\r
- def __init__(self):\r
- self.has_mikoto=False\r
- self.eof=False\r
- self.io=None\r
- self.lines=0\r
- self.materials=[]\r
- self.objects=[]\r
-\r
- def __str__(self):\r
- return "<MQO %d lines, %d materials, %d objects>" % (\r
- self.lines, len(self.materials), len(self.objects))\r
-\r
- def getline(self):\r
- line=self.io.readline()\r
- self.lines+=1\r
- if line=="":\r
- self.eof=True\r
- return None\r
- return line.strip()\r
-\r
- def printError(self, method, msg):\r
- print("%s:%s:%d" % (method, msg, self.lines))\r
-\r
- @withio\r
- def read(self):\r
- line=self.getline()\r
- if line!="Metasequoia Document":\r
- print("invalid signature")\r
- return False\r
-\r
- line=self.getline()\r
- if line!="Format Text Ver 1.0":\r
- print("unknown version: %s" % line)\r
-\r
- while True:\r
- line=self.getline()\r
- if line==None:\r
- # eof\r
- break;\r
- if line=="":\r
- # empty line\r
- continue\r
-\r
- tokens=line.split()\r
- key=tokens[0]\r
-\r
- if key=="Eof":\r
- return True\r
- elif key=="Scene":\r
- if not self.readChunk():\r
- return False\r
- elif key=="Material":\r
- if not self.readMaterial():\r
- return False\r
- elif key=="Object":\r
- firstQuote=line.find('"')\r
- secondQuote=line.find('"', firstQuote+1)\r
- if not self.readObject(line[firstQuote+1:secondQuote]):\r
- return False\r
- elif key=="BackImage":\r
- if not self.readChunk():\r
- return False\r
- elif key=="IncludeXml":\r
- firstQuote=line.find('"')\r
- secondQuote=line.find('"', firstQuote+1)\r
- print("IncludeXml", line[firstQuote+1:secondQuote])\r
- else:\r
- print("unknown key: %s" % key)\r
- if not self.readChunk():\r
- return False\r
-\r
- self.printError("parse", "invalid eof")\r
- return False\r
-\r
- def readObject(self, name):\r
- obj=Obj(name)\r
- if name.startswith('bone'):\r
- self.has_mikoto=True\r
- self.objects.append(obj)\r
- while(True):\r
- line=self.getline()\r
- if line==None:\r
- # eof\r
- break;\r
- if line=="":\r
- # empty line\r
- continue\r
-\r
- if line=="}":\r
- return True\r
- else:\r
- tokens=line.split()\r
- key=tokens[0]\r
- if key=="vertex":\r
- if not self.readVertex(obj):\r
- return False\r
- elif key=="face":\r
- if not self.readFace(obj):\r
- return False\r
- elif key=="depth":\r
- obj.depth=int(tokens[1])\r
- else:\r
- print(\r
- "%s#readObject" % name,\r
- "unknown key: %s" % key\r
- )\r
-\r
- self.printError("readObject", "invalid eof")\r
- return False\r
-\r
- def readFace(self, obj):\r
- while(True):\r
- line=self.getline()\r
- if line==None:\r
- # eof\r
- break;\r
- if line=="":\r
- # empty line\r
- continue\r
-\r
- if line=="}":\r
- return True\r
- else:\r
- # face\r
- tokens=line.split(' ', 1)\r
- try:\r
- obj.addFace(Face(int(tokens[0]), tokens[1]))\r
- except ValueError as ex:\r
- self.printError("readFace", ex)\r
- #return False\r
-\r
- self.printError("readFace", "invalid eof")\r
- return False\r
-\r
- def readVertex(self, obj):\r
- while(True):\r
- line=self.getline()\r
- if line==None:\r
- # eof\r
- break;\r
- if line=="":\r
- # empty line\r
- continue\r
-\r
- if line=="}":\r
- return True\r
- else:\r
- # vertex\r
- obj.addVertex(*[float(v) for v in line.split()])\r
-\r
- self.printError("readVertex", "invalid eof")\r
- return False\r
-\r
- def readMaterial(self):\r
- while(True):\r
- line=self.getline()\r
- if line==None:\r
- # eof\r
- break;\r
- if line=="":\r
- # empty line\r
- continue\r
-\r
- if line=="}":\r
- return True\r
- else:\r
- # material\r
- secondQuaote=line.find('"', 1) \r
- material=Material(line[1:secondQuaote])\r
- try:\r
- material.parse(line[secondQuaote+2:])\r
- except ValueError as ex:\r
- self.printError("readMaterial", ex)\r
-\r
- self.materials.append(material)\r
-\r
- self.printError("readMaterial", "invalid eof")\r
- return False\r
-\r
- def readChunk(self):\r
- level=1\r
- while(True):\r
- line=self.getline()\r
- if line==None:\r
- # eof\r
- break;\r
- if line=="":\r
- # empty line\r
- continue\r
-\r
- if line=="}":\r
- level-=1\r
- if level==0:\r
- return True\r
- elif line.find("{")!=-1:\r
- level+=1\r
-\r
- self.printError("readChunk", "invalid eof")\r
- return False\r
-\r