OSDN Git Service

refactoring
authorousttrue <ousttrue@gmail.com>
Fri, 30 Sep 2011 13:38:21 +0000 (22:38 +0900)
committerousttrue <ousttrue@gmail.com>
Fri, 30 Sep 2011 13:38:21 +0000 (22:38 +0900)
pymeshio/common.py
pymeshio/pmx.py [deleted file]
pymeshio/pmx/__init__.py [new file with mode: 0644]
pymeshio/pmx/loader.py [new file with mode: 0644]
test/pmx_test.py

index 7dadc16..8ec017d 100644 (file)
@@ -13,6 +13,10 @@ def radian_to_degree(x):
 """\r
 common structures.\r
 """\r
+class ParseException(Exception):\r
+    pass\r
+\r
+\r
 class Vector2(object):\r
     """\r
     2D coordinate for uv value\r
diff --git a/pymeshio/pmx.py b/pymeshio/pmx.py
deleted file mode 100644 (file)
index 22b0d8b..0000000
+++ /dev/null
@@ -1,552 +0,0 @@
-#!/usr/bin/env python\r
-# coding: utf-8\r
-"""\r
-pmx file io library.\r
-\r
-pmx file format:\r
-    PMDEditor's Lib/PMX仕様/PMX仕様.txt\r
-"""\r
-__author__="ousttrue"\r
-__license__="zlib"\r
-__versioon__="1.0.0"\r
-\r
-\r
-import io\r
-import os\r
-import struct\r
-from . import common\r
-\r
-\r
-class ParseException(Exception):\r
-    pass\r
-\r
-\r
-class Ik(object):\r
-    """ik info\r
-    """\r
-    __slots__=[\r
-            'target_index',\r
-            'loop',\r
-            'limit_radian',\r
-            'link',\r
-            ]\r
-    def __init__(self, target_index, loop, limit_radian):\r
-        self.target_index=target_index\r
-        self.loop=loop\r
-        self.limit_radian=limit_radian\r
-        self.link=[]\r
-\r
-\r
-class IkLink(object):\r
-    """ik link info\r
-    """\r
-    __slots__=[\r
-            'bone_index',\r
-            'limit_angle',\r
-            'limit_min',\r
-            'limit_max',\r
-            ]\r
-    def __init__(self, bone_index, limit_angle):\r
-        self.bone_index=bone_index\r
-        self.limit_angle=limit_angle\r
-        self.limit_min=None\r
-        self.limit_max=None\r
-\r
-\r
-class Bone(object):\r
-    """material\r
-\r
-    Bone: see __init__\r
-    """\r
-    __slots__=[\r
-            'name',\r
-            'english_name',\r
-            'position',\r
-            'parent_index',\r
-            'layer',\r
-            'flag',\r
-\r
-            'tail_positoin',\r
-            'tail_index',\r
-            'effect_index',\r
-            'effect_factor',\r
-            'fixed_axis',\r
-            'local_x_vector',\r
-            'local_z_vector',\r
-            'external_key',\r
-            'ik',\r
-            ]\r
-    def __init__(self,\r
-            name: str,\r
-            english_name: str,\r
-            position: common.Vector3,\r
-            parent_index: int,\r
-            layer: int,\r
-            flag: int\r
-            ):\r
-        self.name=name,\r
-        self.english_name=english_name\r
-        self.position=position\r
-        self.parent_index=parent_index\r
-        self.layer=layer\r
-        self.flag=flag\r
-\r
-    def getConnectionFlag(self) -> int:\r
-        return self.flag & 0x0001\r
-\r
-    def getIkFlag(self) -> int:\r
-        return (self.flag & 0x0020) >> 5\r
-\r
-    def getRotationFlag(self) -> int:\r
-        return (self.flag & 0x0100) >> 8\r
-\r
-    def getTranslationFlag(self) -> int:\r
-        return (self.flag & 0x0200) >> 9\r
-\r
-    def getFixedAxisFlag(self) -> int:\r
-        return (self.flag & 0x0400) >> 10\r
-\r
-    def getLocalCoordinateFlag(self) -> int:\r
-        return (self.flag &  0x0800) >> 11\r
-    \r
-    def getExternalParentDeformFlag(self) -> int:\r
-        return (self.flag &  0x2000) >> 13\r
-\r
\r
-class Material(object):\r
-    """material\r
-\r
-    Attributes: see __init__\r
-    """\r
-    __slots__=[\r
-            'name',\r
-            'english_name',\r
-            'diffuse_color',\r
-            'diffuse_alpha',\r
-            'specular_color',\r
-            'specular_factor',\r
-            'ambient_color',\r
-            'flag',\r
-            'edge_color',\r
-            'edge_size',\r
-            'texture_index',\r
-            'sphia_texture_index',\r
-            'sphia_mode',\r
-            'toon_sharing_flag',\r
-            'toon_texture_index',\r
-            'comment',\r
-            'index_count',\r
-            ]\r
-    def __init__(self,\r
-            name: str,\r
-            english_name: str,\r
-            diffuse_color: common.RGB,\r
-            diffuse_alpha: float,\r
-            specular_color: common.RGB,\r
-            specular_factor: float,\r
-            ambient_color: common.RGB,\r
-            flag: int,\r
-            edge_color: common.RGBA,\r
-            edge_size: float,\r
-            texture_index: int,\r
-            sphia_texture_index: int,\r
-            sphia_mode: int,\r
-            toon_sharing_flag: int\r
-            ):\r
-        self.name=name\r
-        self.english_name=english_name\r
-        self.diffuse_color=diffuse_color\r
-        self.diffuse_alpha=diffuse_alpha\r
-        self.specular_color=specular_color\r
-        self.specular_factor=specular_factor\r
-        self.ambient_color=ambient_color\r
-        self.flag=flag\r
-        self.edge_color=edge_color\r
-        self.edge_size=edge_size\r
-        self.texture_index=texture_index\r
-        self.sphia_texture_index=sphia_texture_index\r
-        self.sphia_mode=sphia_mode\r
-        self.toon_sharing_flag=toon_sharing_flag\r
-        #\r
-        self.toon_texture_index=None\r
-        self.comment=''\r
-        self.index_count=0\r
-\r
-\r
-class Deform(object):\r
-    pass\r
-\r
-\r
-class Bdef1(object):\r
-    """bone deform. use a weight\r
-\r
-    Attributes: see __init__\r
-    """\r
-    __slots__=[ 'bone_index']\r
-    def __init__(self, bone_index: int):\r
-        self.bone_index=bone_index\r
-\r
-\r
-class Bdef2(object):\r
-    """bone deform. use two weights\r
-\r
-    Attributes: see __init__\r
-    """\r
-    __slots__=[ 'index0', 'index1', 'weight0']\r
-    def __init__(self, \r
-            index0: int,\r
-            index1: int,\r
-            weight0: float):\r
-        self.index0=index0\r
-        self.index1=index1\r
-        self.weight0=weight0\r
-\r
-\r
-class Vertex(object):\r
-    """pmx vertex\r
-\r
-    Attributes: see __init__\r
-    """\r
-    __slots__=[ 'position', 'normal', 'uv', 'deform', 'edge_factor' ]\r
-    def __init__(self, \r
-            position: common.Vector3, \r
-            normal: common.Vector3, \r
-            uv: common.Vector2, \r
-            deform: Deform, \r
-            edge_factor: float):\r
-        self.position=position \r
-        self.normal=normal\r
-        self.uv=uv\r
-        self.deform=deform\r
-        self.edge_factor=edge_factor\r
-\r
-\r
-class Model(object):\r
-    """pmx data representation\r
-\r
-    Attributes:\r
-        version: pmx version(expected 2.0)\r
-        name: \r
-        english_name: \r
-        comment: \r
-        english_comment: \r
-        vertices:\r
-        textures:\r
-        materials:\r
-        bones:\r
-    """\r
-    __slots__=[\r
-            'version', # pmx version\r
-            'name', # model name\r
-            'english_name', # model name in english\r
-            'comment', # model comment\r
-            'english_comment', # model comment in english\r
-            'vertices',\r
-            'indices',\r
-            'textures',\r
-            'materials',\r
-            'bones',\r
-            ]\r
-    def __init__(self):\r
-        self.version=0.0\r
-        self.name=''\r
-        self.english_name=''\r
-        self.comment=''\r
-        self.english_comment=''\r
-        self.vertices=[]\r
-        self.indices=[]\r
-        self.textures=[]\r
-        self.materials=[]\r
-        self.bones=[]\r
-\r
-\r
-class IO(object):\r
-    """pmx loader\r
-\r
-    Attributes:\r
-        text_encoding: \r
-        extended_uv:\r
-        vertex_index_size:\r
-        texture_index_size:\r
-        material_index_size:\r
-        bone_index_size:\r
-        morph_index_size:\r
-        rigidbody_index_size:\r
-    """\r
-    def __init__(self):\r
-        self.__io=None\r
-        self.__pos=-1\r
-        self.__end=-1\r
-        self.__model=Model()\r
-\r
-    def read(self, path: 'filepath') -> Model:\r
-        size=os.path.getsize(path)\r
-        with open(path, "rb") as f:\r
-            if self.__load(path, f, size):\r
-                return self.__model\r
-\r
-    def __load(self, path: 'filepath', io: io.IOBase, size: int) -> bool: \r
-        self.__io=io\r
-        self.__end=size\r
-        self.__pos=0\r
-\r
-        ####################\r
-        # header\r
-        ####################\r
-        signature=self.__unpack("4s", 4)\r
-        if signature!=b"PMX ":\r
-            print("invalid signature", self.signature)\r
-            return False\r
-        version=self.__read_float()\r
-        if version!=2.0:\r
-            print("unknown version", version)\r
-        self.__model.version=version\r
-        # flags\r
-        flag_bytes=self.__read_uint(1)\r
-        if flag_bytes!=8:\r
-            print("invalid flag length", self.flag_bytes)\r
-            return False\r
-        # text encoding\r
-        self.text_encoding=self.__read_uint(1)\r
-        self.__read_text=self.__get_read_text()\r
-        # uv\r
-        self.extended_uv=self.__read_uint(1)\r
-        if self.extended_uv>0:\r
-            print("extended uv is not supported", self.extended_uv)\r
-            return False\r
-        # index size\r
-        self.vertex_index_size=self.__read_uint(1)\r
-        self.texture_index_size=self.__read_uint(1)\r
-        self.material_index_size=self.__read_uint(1)\r
-        self.bone_index_size=self.__read_uint(1)\r
-        self.morph_index_size=self.__read_uint(1)\r
-        self.rigidbody_index_size=self.__read_uint(1)\r
-\r
-        ####################\r
-        # model info\r
-        ####################\r
-        self.__model.name = self.__read_text()\r
-        self.__model.english_name = self.__read_text()\r
-        self.__model.comment = self.__read_text()\r
-        self.__model.english_comment = self.__read_text()\r
-\r
-        ####################\r
-        # vertices\r
-        ####################\r
-        vertex_count=self.__read_uint(4)\r
-        self.__model.vertices=[self.__read_vertex() \r
-                for i in range(vertex_count)]\r
-\r
-        ####################\r
-        # indices\r
-        ####################\r
-        index_count=self.__read_uint(4)\r
-        self.__model.indices=[self.__read_uint(self.vertex_index_size) \r
-                for i in range(index_count)]\r
-\r
-        ####################\r
-        # textures\r
-        ####################\r
-        texture_count=self.__read_uint(4)\r
-        self.__model.textures=[self.__read_text() \r
-                for i in range(texture_count)]\r
-\r
-        ####################\r
-        # materials\r
-        ####################\r
-        material_count=self.__read_uint(4)\r
-        self.__model.materials=[self.__read_material() \r
-                for i in range(material_count)]\r
-\r
-        ####################\r
-        # bones\r
-        ####################\r
-        bone_count=self.__read_uint(4)\r
-        self.__model.bones=[self.__read_bone() \r
-                for i in range(bone_count)]\r
-\r
-        return True\r
-\r
-    def __str__(self) -> str:\r
-        return '<PmxIO>'\r
-\r
-    def __check_position(self):\r
-        self.__pos=self.__io.tell()\r
-\r
-    def __unpack(self, fmt: str, size: int) -> "read value as format":\r
-        result=struct.unpack(fmt, self.__io.read(size))\r
-        self.__check_position()\r
-        return result[0]\r
-\r
-    def __get_read_text(self) -> "text process function":\r
-        if self.text_encoding==0:\r
-            def read_text():\r
-                size=self.__read_uint(4)\r
-                return self.__unpack("{0}s".format(size), size).decode("UTF16")\r
-            return read_text\r
-        elif self.text_encoding==1:\r
-            def read_text():\r
-                size=self.__read_uint(4)\r
-                return self.__unpack("{0}s".format(size), size).decode("UTF8")\r
-            return read_text\r
-        else:\r
-            print("unknown text encoding", self.text_encoding)\r
-\r
-    def __read_uint(self, size):\r
-        if size==1:\r
-            return self.__unpack("B", size)\r
-        if size==2:\r
-            return self.__unpack("H", size)\r
-        if size==4:\r
-            return self.__unpack("I", size)\r
-        print("not reach here")\r
-        raise ParseException("invalid int size: "+size)\r
-\r
-    def __read_float(self):\r
-        return self.__unpack("f", 4)\r
-\r
-    def __read_vector2(self):\r
-        return common.Vector2(\r
-                self.__read_float(), \r
-                self.__read_float()\r
-                )\r
-\r
-    def __read_vector3(self):\r
-        return common.Vector3(\r
-                self.__read_float(), \r
-                self.__read_float(), \r
-                self.__read_float()\r
-                )\r
-\r
-    def __read_rgba(self):\r
-        return common.RGBA(\r
-                self.__read_float(), \r
-                self.__read_float(), \r
-                self.__read_float(),\r
-                self.__read_float()\r
-                )\r
-\r
-    def __read_rgb(self):\r
-        return common.RGB(\r
-                self.__read_float(), \r
-                self.__read_float(), \r
-                self.__read_float()\r
-                )\r
-\r
-    def __read_vertex(self):\r
-        return Vertex(\r
-                self.__read_vector3(), # pos\r
-                self.__read_vector3(), # normal\r
-                self.__read_vector2(), # uv\r
-                self.__read_deform(), # deform(bone weight)\r
-                self.__read_float() # edge factor\r
-                )\r
-\r
-    def __read_deform(self):\r
-        deform_type=self.__read_uint(1)\r
-        if deform_type==0:\r
-            return Bdef1(self.__read_uint(self.bone_index_size))\r
-        if deform_type==1:\r
-            return Bdef2(\r
-                    self.__read_uint(self.bone_index_size),\r
-                    self.__read_uint(self.bone_index_size),\r
-                    self.__read_float()\r
-                    )\r
-        """\r
-        if deform_type==2:\r
-            return Bdef4(\r
-                    self.__read_uint(self.bone_index_size),\r
-                    self.__read_uint(self.bone_index_size),\r
-                    self.__read_uint(self.bone_index_size),\r
-                    self.__read_uint(self.bone_index_size),\r
-                    self.__read_float(), self.__read_float(),\r
-                    self.__read_float(), self.__read_float()\r
-                    )\r
-        """\r
-        raise ParseException("unknown deform type: {0}".format(deform_type))\r
-\r
-    def __read_material(self):\r
-        material=Material(\r
-                name=self.__read_text(),\r
-                english_name=self.__read_text(),\r
-                diffuse_color=self.__read_rgb(),\r
-                diffuse_alpha=self.__read_float(),\r
-                specular_color=self.__read_rgb(),\r
-                specular_factor=self.__read_float(),\r
-                ambient_color=self.__read_rgb(),\r
-                flag=self.__read_uint(1),\r
-                edge_color=self.__read_rgba(),\r
-                edge_size=self.__read_float(),\r
-                texture_index=self.__read_uint(self.texture_index_size),\r
-                sphia_texture_index=self.__read_uint(self.texture_index_size),\r
-                sphia_mode=self.__read_uint(1),\r
-                toon_sharing_flag=self.__read_uint(1),\r
-                )\r
-        if material.toon_sharing_flag==0:\r
-            material.toon_texture_index=self.__read_uint(self.texture_index_size)\r
-        elif material.toon_sharing_flag==1:\r
-            material.toon_texture_index=self.__read_uint(1)\r
-        else:\r
-            raise ParseException("unknown toon_sharing_flag {0}".format(material.toon_sharing_flag))\r
-        material.comment=self.__read_text()\r
-        material.index_count=self.__read_uint(4)\r
-        return material\r
-\r
-    def __read_bone(self):\r
-        bone=Bone(\r
-                name=self.__read_text(),\r
-                english_name=self.__read_text(),\r
-                position=self.__read_vector3(),\r
-                parent_index=self.__read_uint(self.bone_index_size),\r
-                layer=self.__read_uint(4),\r
-                flag=self.__read_uint(2)                \r
-                )\r
-        if bone.getConnectionFlag()==0:\r
-            bone.tail_positoin=self.__read_vector3()\r
-        elif bone.getConnectionFlag()==1:\r
-            bone.tail_index=self.__read_uint(self.bone_index_size)\r
-        else:\r
-            raise ParseException("unknown bone conenction flag: {0}".format(\r
-                bone.getConnectionFlag()))\r
-\r
-        if bone.getRotationFlag()==1 or bone.getTranslationFlag()==1:\r
-            bone.effect_index=self.__read_uint(self.bone_index_size)\r
-            bone.effect_factor=self.__read_float()\r
-\r
-        if bone.getFixedAxisFlag()==1:\r
-            bone.fixed_axis=self.__read_vector3()\r
-\r
-        if bone.getLocalCoordinateFlag()==1:\r
-            bone.local_x_vector=self.__read_vector3()\r
-            bone.local_z_vector=self.__read_vector3()\r
-\r
-        if bone.getExternalParentDeformFlag()==1:\r
-            bone.external_key=self.__read_uint(4)\r
-\r
-        if bone.getIkFlag()==1:\r
-            bone.ik=self.__read_ik()\r
-\r
-        return bone\r
-\r
-    def __read_ik(self):\r
-        ik=Ik(\r
-                target_index=self.__read_uint(self.bone_index_size),\r
-                loop=self.__read_uint(4),\r
-                limit_radian=self.__read_float())\r
-        link_size=self.__read_uint(4)\r
-        ik.link=[self.__read_ik_link() for i in range(link_size)]\r
-\r
-    def __read_ik_link(self):\r
-        link=IkLink(\r
-                self.__read_uint(self.bone_index_size),\r
-                self.__read_uint(1))\r
-        if link.limit_angle==0:\r
-            pass\r
-        elif link.limit_angle==1:\r
-            link.limit_min=self.__read_vector3()\r
-            link.limit_max=self.__read_vector3()\r
-        else:\r
-            raise ParseException("invalid ik link limit_angle: {0}".format(\r
-                link.limit_angle))\r
-        return link\r
-\r
diff --git a/pymeshio/pmx/__init__.py b/pymeshio/pmx/__init__.py
new file mode 100644 (file)
index 0000000..6d8a831
--- /dev/null
@@ -0,0 +1,258 @@
+#!/usr/bin/env python\r
+# coding: utf-8\r
+"""\r
+pmx file io library.\r
+\r
+pmx file format:\r
+    PMDEditor's Lib/PMX仕様/PMX仕様.txt\r
+"""\r
+__author__="ousttrue"\r
+__license__="zlib"\r
+__versioon__="1.0.0"\r
+\r
+\r
+import io\r
+import os\r
+import struct\r
+from pymeshio import common\r
+\r
+\r
+\r
+class Ik(object):\r
+    """ik info\r
+    """\r
+    __slots__=[\r
+            'target_index',\r
+            'loop',\r
+            'limit_radian',\r
+            'link',\r
+            ]\r
+    def __init__(self, target_index, loop, limit_radian):\r
+        self.target_index=target_index\r
+        self.loop=loop\r
+        self.limit_radian=limit_radian\r
+        self.link=[]\r
+\r
+\r
+class IkLink(object):\r
+    """ik link info\r
+    """\r
+    __slots__=[\r
+            'bone_index',\r
+            'limit_angle',\r
+            'limit_min',\r
+            'limit_max',\r
+            ]\r
+    def __init__(self, bone_index, limit_angle):\r
+        self.bone_index=bone_index\r
+        self.limit_angle=limit_angle\r
+        self.limit_min=None\r
+        self.limit_max=None\r
+\r
+\r
+class Bone(object):\r
+    """material\r
+\r
+    Bone: see __init__\r
+    """\r
+    __slots__=[\r
+            'name',\r
+            'english_name',\r
+            'position',\r
+            'parent_index',\r
+            'layer',\r
+            'flag',\r
+\r
+            'tail_positoin',\r
+            'tail_index',\r
+            'effect_index',\r
+            'effect_factor',\r
+            'fixed_axis',\r
+            'local_x_vector',\r
+            'local_z_vector',\r
+            'external_key',\r
+            'ik',\r
+            ]\r
+    def __init__(self,\r
+            name: str,\r
+            english_name: str,\r
+            position: common.Vector3,\r
+            parent_index: int,\r
+            layer: int,\r
+            flag: int\r
+            ):\r
+        self.name=name,\r
+        self.english_name=english_name\r
+        self.position=position\r
+        self.parent_index=parent_index\r
+        self.layer=layer\r
+        self.flag=flag\r
+\r
+    def getConnectionFlag(self) -> int:\r
+        return self.flag & 0x0001\r
+\r
+    def getIkFlag(self) -> int:\r
+        return (self.flag & 0x0020) >> 5\r
+\r
+    def getRotationFlag(self) -> int:\r
+        return (self.flag & 0x0100) >> 8\r
+\r
+    def getTranslationFlag(self) -> int:\r
+        return (self.flag & 0x0200) >> 9\r
+\r
+    def getFixedAxisFlag(self) -> int:\r
+        return (self.flag & 0x0400) >> 10\r
+\r
+    def getLocalCoordinateFlag(self) -> int:\r
+        return (self.flag &  0x0800) >> 11\r
+    \r
+    def getExternalParentDeformFlag(self) -> int:\r
+        return (self.flag &  0x2000) >> 13\r
+\r
\r
+class Material(object):\r
+    """material\r
+\r
+    Attributes: see __init__\r
+    """\r
+    __slots__=[\r
+            'name',\r
+            'english_name',\r
+            'diffuse_color',\r
+            'diffuse_alpha',\r
+            'specular_color',\r
+            'specular_factor',\r
+            'ambient_color',\r
+            'flag',\r
+            'edge_color',\r
+            'edge_size',\r
+            'texture_index',\r
+            'sphia_texture_index',\r
+            'sphia_mode',\r
+            'toon_sharing_flag',\r
+            'toon_texture_index',\r
+            'comment',\r
+            'index_count',\r
+            ]\r
+    def __init__(self,\r
+            name: str,\r
+            english_name: str,\r
+            diffuse_color: common.RGB,\r
+            diffuse_alpha: float,\r
+            specular_color: common.RGB,\r
+            specular_factor: float,\r
+            ambient_color: common.RGB,\r
+            flag: int,\r
+            edge_color: common.RGBA,\r
+            edge_size: float,\r
+            texture_index: int,\r
+            sphia_texture_index: int,\r
+            sphia_mode: int,\r
+            toon_sharing_flag: int\r
+            ):\r
+        self.name=name\r
+        self.english_name=english_name\r
+        self.diffuse_color=diffuse_color\r
+        self.diffuse_alpha=diffuse_alpha\r
+        self.specular_color=specular_color\r
+        self.specular_factor=specular_factor\r
+        self.ambient_color=ambient_color\r
+        self.flag=flag\r
+        self.edge_color=edge_color\r
+        self.edge_size=edge_size\r
+        self.texture_index=texture_index\r
+        self.sphia_texture_index=sphia_texture_index\r
+        self.sphia_mode=sphia_mode\r
+        self.toon_sharing_flag=toon_sharing_flag\r
+        #\r
+        self.toon_texture_index=None\r
+        self.comment=''\r
+        self.index_count=0\r
+\r
+\r
+class Deform(object):\r
+    pass\r
+\r
+\r
+class Bdef1(object):\r
+    """bone deform. use a weight\r
+\r
+    Attributes: see __init__\r
+    """\r
+    __slots__=[ 'bone_index']\r
+    def __init__(self, bone_index: int):\r
+        self.bone_index=bone_index\r
+\r
+\r
+class Bdef2(object):\r
+    """bone deform. use two weights\r
+\r
+    Attributes: see __init__\r
+    """\r
+    __slots__=[ 'index0', 'index1', 'weight0']\r
+    def __init__(self, \r
+            index0: int,\r
+            index1: int,\r
+            weight0: float):\r
+        self.index0=index0\r
+        self.index1=index1\r
+        self.weight0=weight0\r
+\r
+\r
+class Vertex(object):\r
+    """pmx vertex\r
+\r
+    Attributes: see __init__\r
+    """\r
+    __slots__=[ 'position', 'normal', 'uv', 'deform', 'edge_factor' ]\r
+    def __init__(self, \r
+            position: common.Vector3, \r
+            normal: common.Vector3, \r
+            uv: common.Vector2, \r
+            deform: Deform, \r
+            edge_factor: float):\r
+        self.position=position \r
+        self.normal=normal\r
+        self.uv=uv\r
+        self.deform=deform\r
+        self.edge_factor=edge_factor\r
+\r
+\r
+class Model(object):\r
+    """pmx data representation\r
+\r
+    Attributes:\r
+        version: pmx version(expected 2.0)\r
+        name: \r
+        english_name: \r
+        comment: \r
+        english_comment: \r
+        vertices:\r
+        textures:\r
+        materials:\r
+        bones:\r
+    """\r
+    __slots__=[\r
+            'version', # pmx version\r
+            'name', # model name\r
+            'english_name', # model name in english\r
+            'comment', # model comment\r
+            'english_comment', # model comment in english\r
+            'vertices',\r
+            'indices',\r
+            'textures',\r
+            'materials',\r
+            'bones',\r
+            ]\r
+    def __init__(self):\r
+        self.version=0.0\r
+        self.name=''\r
+        self.english_name=''\r
+        self.comment=''\r
+        self.english_comment=''\r
+        self.vertices=[]\r
+        self.indices=[]\r
+        self.textures=[]\r
+        self.materials=[]\r
+        self.bones=[]\r
+\r
diff --git a/pymeshio/pmx/loader.py b/pymeshio/pmx/loader.py
new file mode 100644 (file)
index 0000000..fbcc0d8
--- /dev/null
@@ -0,0 +1,283 @@
+from pymeshio.pmx import *\r
+#self.__pos=self.__io.tell()\r
+\r
+\r
+\r
+class Loader(object):\r
+    """pmx loader\r
+\r
+    Attributes:\r
+        text_encoding: \r
+        extended_uv:\r
+        vertex_index_size:\r
+        texture_index_size:\r
+        material_index_size:\r
+        bone_index_size:\r
+        morph_index_size:\r
+        rigidbody_index_size:\r
+    """\r
+    def __init__(self, loader):\r
+        self.__io=loader\r
+\r
+    def __str__(self) -> str:\r
+        return '<PmxIO>'\r
+\r
+    def unpack(self, fmt: str, size: int) -> "read value as format":\r
+        result=struct.unpack(fmt, self.__io.read(size))\r
+        return result[0]\r
+\r
+    def get_read_text(self) -> "text process function":\r
+        if self.text_encoding==0:\r
+            def read_text():\r
+                size=self.read_uint(4)\r
+                return self.unpack("{0}s".format(size), size).decode("UTF16")\r
+            return read_text\r
+        elif self.text_encoding==1:\r
+            def read_text():\r
+                size=self.read_uint(4)\r
+                return self.unpack("{0}s".format(size), size).decode("UTF8")\r
+            return read_text\r
+        else:\r
+            print("unknown text encoding", self.text_encoding)\r
+\r
+    def read_uint(self, size):\r
+        if size==1:\r
+            return self.unpack("B", size)\r
+        if size==2:\r
+            return self.unpack("H", size)\r
+        if size==4:\r
+            return self.unpack("I", size)\r
+        print("not reach here")\r
+        raise ParseException("invalid int size: "+size)\r
+\r
+    def read_float(self):\r
+        return self.unpack("f", 4)\r
+\r
+    def read_vector2(self):\r
+        return common.Vector2(\r
+                self.read_float(), \r
+                self.read_float()\r
+                )\r
+\r
+    def read_vector3(self):\r
+        return common.Vector3(\r
+                self.read_float(), \r
+                self.read_float(), \r
+                self.read_float()\r
+                )\r
+\r
+    def read_rgba(self):\r
+        return common.RGBA(\r
+                self.read_float(), \r
+                self.read_float(), \r
+                self.read_float(),\r
+                self.read_float()\r
+                )\r
+\r
+    def read_rgb(self):\r
+        return common.RGB(\r
+                self.read_float(), \r
+                self.read_float(), \r
+                self.read_float()\r
+                )\r
+\r
+    def read_vertex(self):\r
+        return Vertex(\r
+                self.read_vector3(), # pos\r
+                self.read_vector3(), # normal\r
+                self.read_vector2(), # uv\r
+                self.read_deform(), # deform(bone weight)\r
+                self.read_float() # edge factor\r
+                )\r
+\r
+    def read_deform(self):\r
+        deform_type=self.read_uint(1)\r
+        if deform_type==0:\r
+            return Bdef1(self.read_uint(self.bone_index_size))\r
+        if deform_type==1:\r
+            return Bdef2(\r
+                    self.read_uint(self.bone_index_size),\r
+                    self.read_uint(self.bone_index_size),\r
+                    self.read_float()\r
+                    )\r
+        """\r
+        if deform_type==2:\r
+            return Bdef4(\r
+                    self.read_uint(self.bone_index_size),\r
+                    self.read_uint(self.bone_index_size),\r
+                    self.read_uint(self.bone_index_size),\r
+                    self.read_uint(self.bone_index_size),\r
+                    self.read_float(), self.read_float(),\r
+                    self.read_float(), self.read_float()\r
+                    )\r
+        """\r
+        raise ParseException("unknown deform type: {0}".format(deform_type))\r
+\r
+    def read_material(self):\r
+        material=Material(\r
+                name=self.read_text(),\r
+                english_name=self.read_text(),\r
+                diffuse_color=self.read_rgb(),\r
+                diffuse_alpha=self.read_float(),\r
+                specular_color=self.read_rgb(),\r
+                specular_factor=self.read_float(),\r
+                ambient_color=self.read_rgb(),\r
+                flag=self.read_uint(1),\r
+                edge_color=self.read_rgba(),\r
+                edge_size=self.read_float(),\r
+                texture_index=self.read_uint(self.texture_index_size),\r
+                sphia_texture_index=self.read_uint(self.texture_index_size),\r
+                sphia_mode=self.read_uint(1),\r
+                toon_sharing_flag=self.read_uint(1),\r
+                )\r
+        if material.toon_sharing_flag==0:\r
+            material.toon_texture_index=self.read_uint(self.texture_index_size)\r
+        elif material.toon_sharing_flag==1:\r
+            material.toon_texture_index=self.read_uint(1)\r
+        else:\r
+            raise ParseException("unknown toon_sharing_flag {0}".format(material.toon_sharing_flag))\r
+        material.comment=self.read_text()\r
+        material.index_count=self.read_uint(4)\r
+        return material\r
+\r
+    def read_bone(self):\r
+        bone=Bone(\r
+                name=self.read_text(),\r
+                english_name=self.read_text(),\r
+                position=self.read_vector3(),\r
+                parent_index=self.read_uint(self.bone_index_size),\r
+                layer=self.read_uint(4),\r
+                flag=self.read_uint(2)                \r
+                )\r
+        if bone.getConnectionFlag()==0:\r
+            bone.tail_positoin=self.read_vector3()\r
+        elif bone.getConnectionFlag()==1:\r
+            bone.tail_index=self.read_uint(self.bone_index_size)\r
+        else:\r
+            raise ParseException("unknown bone conenction flag: {0}".format(\r
+                bone.getConnectionFlag()))\r
+\r
+        if bone.getRotationFlag()==1 or bone.getTranslationFlag()==1:\r
+            bone.effect_index=self.read_uint(self.bone_index_size)\r
+            bone.effect_factor=self.read_float()\r
+\r
+        if bone.getFixedAxisFlag()==1:\r
+            bone.fixed_axis=self.read_vector3()\r
+\r
+        if bone.getLocalCoordinateFlag()==1:\r
+            bone.local_x_vector=self.read_vector3()\r
+            bone.local_z_vector=self.read_vector3()\r
+\r
+        if bone.getExternalParentDeformFlag()==1:\r
+            bone.external_key=self.read_uint(4)\r
+\r
+        if bone.getIkFlag()==1:\r
+            bone.ik=self.read_ik()\r
+\r
+        return bone\r
+\r
+    def read_ik(self):\r
+        ik=Ik(\r
+                target_index=self.read_uint(self.bone_index_size),\r
+                loop=self.read_uint(4),\r
+                limit_radian=self.read_float())\r
+        link_size=self.read_uint(4)\r
+        ik.link=[self.read_ik_link() for i in range(link_size)]\r
+\r
+    def read_ik_link(self):\r
+        link=IkLink(\r
+                self.read_uint(self.bone_index_size),\r
+                self.read_uint(1))\r
+        if link.limit_angle==0:\r
+            pass\r
+        elif link.limit_angle==1:\r
+            link.limit_min=self.read_vector3()\r
+            link.limit_max=self.read_vector3()\r
+        else:\r
+            raise ParseException("invalid ik link limit_angle: {0}".format(\r
+                link.limit_angle))\r
+        return link\r
+\r
+\r
+def load(path: str) -> Model:\r
+    with open(path, "rb") as f:\r
+        model=Model()\r
+        loader=Loader(f)\r
+\r
+        ####################\r
+        # header\r
+        ####################\r
+        signature=loader.unpack("4s", 4)\r
+        if signature!=b"PMX ":\r
+            raise ParseException("invalid signature", loader.signature)\r
+\r
+        version=loader.read_float()\r
+        if version!=2.0:\r
+            print("unknown version", version)\r
+\r
+        model.version=version\r
+        # flags\r
+        flag_bytes=loader.read_uint(1)\r
+        if flag_bytes!=8:\r
+            raise ParseException("invalid flag length", loader.flag_bytes)\r
+\r
+        # text encoding\r
+        loader.text_encoding=loader.read_uint(1)\r
+        loader.read_text=loader.get_read_text()\r
+        # uv\r
+        loader.extended_uv=loader.read_uint(1)\r
+        if loader.extended_uv>0:\r
+            raise ParseException("extended uv is not supported", loader.extended_uv)\r
+\r
+        # index size\r
+        loader.vertex_index_size=loader.read_uint(1)\r
+        loader.texture_index_size=loader.read_uint(1)\r
+        loader.material_index_size=loader.read_uint(1)\r
+        loader.bone_index_size=loader.read_uint(1)\r
+        loader.morph_index_size=loader.read_uint(1)\r
+        loader.rigidbody_index_size=loader.read_uint(1)\r
+\r
+        ####################\r
+        # model info\r
+        ####################\r
+        model.name = loader.read_text()\r
+        model.english_name = loader.read_text()\r
+        model.comment = loader.read_text()\r
+        model.english_comment = loader.read_text()\r
+\r
+        ####################\r
+        # vertices\r
+        ####################\r
+        vertex_count=loader.read_uint(4)\r
+        model.vertices=[loader.read_vertex() \r
+                for i in range(vertex_count)]\r
+\r
+        ####################\r
+        # indices\r
+        ####################\r
+        index_count=loader.read_uint(4)\r
+        model.indices=[loader.read_uint(loader.vertex_index_size) \r
+                for i in range(index_count)]\r
+\r
+        ####################\r
+        # textures\r
+        ####################\r
+        texture_count=loader.read_uint(4)\r
+        model.textures=[loader.read_text() \r
+                for i in range(texture_count)]\r
+\r
+        ####################\r
+        # materials\r
+        ####################\r
+        material_count=loader.read_uint(4)\r
+        model.materials=[loader.read_material() \r
+                for i in range(material_count)]\r
+\r
+        ####################\r
+        # bones\r
+        ####################\r
+        bone_count=loader.read_uint(4)\r
+        model.bones=[loader.read_bone() \r
+                for i in range(bone_count)]\r
+        return model\r
+\r
index 2d64ae1..1c3beea 100644 (file)
@@ -1,12 +1,11 @@
 # coding: utf-8\r
-import pymeshio.pmx\r
+import pymeshio.pmx.loader\r
 \r
 \r
 PMX_MODEL='resources/初音ミクVer2.pmx'\r
 \r
 def test_read():\r
-    io=pymeshio.pmx.IO()\r
-    model=io.read(PMX_MODEL)\r
+    model=pymeshio.pmx.loader.load(PMX_MODEL)\r
     assert model.__class__==pymeshio.pmx.Model\r
     assert model.name=='初音ミク'\r
     assert model.english_name=='Miku Hatsune'\r