+++ /dev/null
-#!/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
--- /dev/null
+#!/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
--- /dev/null
+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