OSDN Git Service

implement pmx bone read
authorousttrue <ousttrue@gmail.com>
Fri, 30 Sep 2011 02:38:02 +0000 (11:38 +0900)
committerousttrue <ousttrue@gmail.com>
Fri, 30 Sep 2011 02:38:02 +0000 (11:38 +0900)
pymeshio/pmx.py

index 77db3ac..22b0d8b 100644 (file)
@@ -21,6 +21,98 @@ class ParseException(Exception):
     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
@@ -205,30 +297,30 @@ class IO(object):
         if signature!=b"PMX ":\r
             print("invalid signature", self.signature)\r
             return False\r
-        version=self.__unpack("f", 4)\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.__unpack("B", 1)\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.__unpack("B", 1)\r
+        self.text_encoding=self.__read_uint(1)\r
         self.__read_text=self.__get_read_text()\r
         # uv\r
-        self.extended_uv=self.__unpack("B", 1)\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.__unpack("B", 1)\r
-        self.texture_index_size=self.__unpack("B", 1)\r
-        self.material_index_size=self.__unpack("B", 1)\r
-        self.bone_index_size=self.__unpack("B", 1)\r
-        self.morph_index_size=self.__unpack("B", 1)\r
-        self.rigidbody_index_size=self.__unpack("B", 1)\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
@@ -289,12 +381,12 @@ class IO(object):
     def __get_read_text(self) -> "text process function":\r
         if self.text_encoding==0:\r
             def read_text():\r
-                size=self.__unpack("I", 4)\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.__unpack("I", 4)\r
+                size=self.__read_uint(4)\r
                 return self.__unpack("{0}s".format(size), size).decode("UTF8")\r
             return read_text\r
         else:\r
@@ -310,52 +402,55 @@ class IO(object):
         print("not reach here")\r
         raise ParseException("invalid int size: "+size)\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.__unpack("f", 4) # edge factor\r
-                )\r
+    def __read_float(self):\r
+        return self.__unpack("f", 4)\r
 \r
     def __read_vector2(self):\r
         return common.Vector2(\r
-                self.__unpack("f", 4), \r
-                self.__unpack("f", 4)\r
+                self.__read_float(), \r
+                self.__read_float()\r
                 )\r
 \r
     def __read_vector3(self):\r
         return common.Vector3(\r
-                self.__unpack("f", 4), \r
-                self.__unpack("f", 4), \r
-                self.__unpack("f", 4)\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.__unpack("f", 4), \r
-                self.__unpack("f", 4), \r
-                self.__unpack("f", 4),\r
-                self.__unpack("f", 4)\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.__unpack("f", 4), \r
-                self.__unpack("f", 4), \r
-                self.__unpack("f", 4)\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.__unpack("B", 1)\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.__unpack("f", 4)\r
+                    self.__read_float()\r
                     )\r
         """\r
         if deform_type==2:\r
@@ -364,8 +459,8 @@ class IO(object):
                     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.__unpack("f", 4), self.__unpack("f", 4),\r
-                    self.__unpack("f", 4), self.__unpack("f", 4)\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
@@ -375,13 +470,13 @@ class IO(object):
                 name=self.__read_text(),\r
                 english_name=self.__read_text(),\r
                 diffuse_color=self.__read_rgb(),\r
-                diffuse_alpha=self.__unpack("f", 4),\r
+                diffuse_alpha=self.__read_float(),\r
                 specular_color=self.__read_rgb(),\r
-                specular_factor=self.__unpack("f", 4),\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.__unpack("f", 4),\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
@@ -398,5 +493,60 @@ class IO(object):
         return material\r
 \r
     def __read_bone(self):\r
-        return None\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