OSDN Git Service

refactoring
authorousttrue <ousttrue@gmail.com>
Sat, 1 Oct 2011 05:17:05 +0000 (14:17 +0900)
committerousttrue <ousttrue@gmail.com>
Sat, 1 Oct 2011 05:17:05 +0000 (14:17 +0900)
pymeshio/mqo/__init__.py [new file with mode: 0644]
pymeshio/mqo/loader.py [new file with mode: 0644]
test/mqo_test.py
test/mqo_test.pyc
test/pmx_test.py

diff --git a/pymeshio/mqo/__init__.py b/pymeshio/mqo/__init__.py
new file mode 100644 (file)
index 0000000..e986d42
--- /dev/null
@@ -0,0 +1,240 @@
+# 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
+import pymeshio.common\r
+import pymeshio.mqo.loader\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=pymeshio.common.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=pymeshio.common.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(pymeshio.common.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=[pymeshio.common.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(pymeshio.common.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 pymeshio.common.Vector2(0, 0)\r
+\r
+\r
+class Model(object):\r
+    def __init__(self):\r
+        self.has_mikoto=False\r
+        self.materials=[]\r
+        self.objects=[]\r
+\r
+\r
+class IO(object):\r
+    def __init__(self):\r
+        pass\r
+\r
+    def read(self, path):\r
+        model=pymeshio.mqo.loader.load(path)\r
+        if model:\r
+            self.has_mikoto=model.has_mikoto\r
+            self.materials=model.materials\r
+            self.objects=model.objects\r
+            return True\r
+\r
diff --git a/pymeshio/mqo/loader.py b/pymeshio/mqo/loader.py
new file mode 100644 (file)
index 0000000..561dd67
--- /dev/null
@@ -0,0 +1,226 @@
+# coding: utf-8\r
+import io\r
+import pymeshio.common\r
+import pymeshio.mqo\r
+"""\r
+#print(sys.version_info[0])\r
+        #if sys.version_info[0]<3:\r
+        #    io=open(path, )\r
+        #else:\r
+        #    io=open(path, encoding='cp932')\r
+        #result=method(self)\r
+        #self.io.close()\r
+        #self.io=None\r
+        #return result\r
+"""\r
+\r
+\r
+class Loader(object):\r
+    """mqo loader\r
+    """\r
+    __slots__=[\r
+            "has_mikoto",\r
+            "eof", "io", "lines",\r
+            "materials", "objects",\r
+            ]\r
+    def __init__(self, io):\r
+        self.io=io\r
+        self.eof=False\r
+        self.lines=0\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
+    def readObject(self, name):\r
+        obj=pymeshio.mqo.Obj(name)\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 obj\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(pymeshio.mqo.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
+        materials=[]\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 materials\r
+            else:\r
+                # material\r
+                secondQuaote=line.find('"', 1)                \r
+                material=pymeshio.mqo.Material(line[1:secondQuaote])\r
+                try:\r
+                    material.parse(line[secondQuaote+2:])\r
+                except ValueError as ex:\r
+                    self.printError("readMaterial", ex)\r
+\r
+                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
+\r
+def load(path):\r
+    with open(path, 'rb') as io:\r
+        loader=Loader(io)\r
+        model=pymeshio.mqo.Model()\r
+\r
+        line=loader.getline()\r
+        if line!="Metasequoia Document":\r
+            print("invalid signature")\r
+            return False\r
+\r
+        line=loader.getline()\r
+        if line!="Format Text Ver 1.0":\r
+            print("unknown version: %s" % line)\r
+\r
+        while True:\r
+            line=loader.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
+            if key=="Eof":\r
+                return model\r
+            elif key=="Scene":\r
+                if not loader.readChunk():\r
+                    return\r
+            elif key=="Material":\r
+                materials=loader.readMaterial()\r
+                if not materials:\r
+                    return\r
+                model.materials=materials\r
+            elif key=="Object":\r
+                firstQuote=line.find('"')\r
+                secondQuote=line.find('"', firstQuote+1)\r
+                obj=loader.readObject(line[firstQuote+1:secondQuote])\r
+                if not obj:\r
+                    return\r
+                model.objects.append(obj)\r
+            elif key=="BackImage":\r
+                if not loader.readChunk():\r
+                    return\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 loader.readChunk():\r
+                    return\r
+        # error not reach here\r
+        raise ParseException("invalid eof")\r
+\r
index 12daf50..5b054c8 100644 (file)
@@ -1,9 +1,16 @@
 import pymeshio.mqo
 import sys
 
-MQO_FILE="K:/model/cube.mqo"
+MQO_FILE="resources/cube.mqo"
 
-def test_mqo_load():
+def test_old_mqo_load():
     io=pymeshio.mqo.IO()
     assert io.read(MQO_FILE)
 
+def test_mqo_load():
+    model=pymeshio.mqo.loader.load(MQO_FILE)
+    print(model.materials)
+    assert pymeshio.mqo.Model==model.__class__
+    assert 6==len(model.materials)
+    assert 1==len(model.objects)
+
index b11ce30..3f8c2e3 100644 (file)
Binary files a/test/mqo_test.pyc and b/test/mqo_test.pyc differ
index e78f740..878c251 100644 (file)
@@ -2,10 +2,10 @@
 import pymeshio.pmx.loader\r
 \r
 \r
-PMX_MODEL=u'resources/初音ミクVer2.pmx'\r
+PMX_FILE=u'resources/初音ミクVer2.pmx'\r
 \r
 def test_read():\r
-    model=pymeshio.pmx.loader.load(PMX_MODEL)\r
+    model=pymeshio.pmx.loader.load(PMX_FILE)\r
     assert model.__class__==pymeshio.pmx.Model\r
     assert model.name==u'初音ミク'\r
     assert model.english_name==u'Miku Hatsune'\r