3 import pymeshio.common
\r
7 class Loader(pymeshio.common.BinaryLoader):
\r
10 def __init__(self, io,
\r
15 material_index_size,
\r
18 rigidbody_index_size
\r
20 super(Loader, self).__init__(io)
\r
21 self.read_text=self.get_read_text(text_encoding)
\r
23 raise ParseException("extended uv is not supported", extended_uv)
\r
24 self.read_vertex_index=lambda : self.read_uint(vertex_index_size)
\r
25 self.read_texture_index=lambda : self.read_uint(texture_index_size)
\r
26 self.read_material_index=lambda : self.read_uint(material_index_size)
\r
27 self.read_bone_index=lambda : self.read_uint(bone_index_size)
\r
28 self.read_morph_index=lambda : self.read_uint(morph_index_size)
\r
29 self.read_rigidbody_index=lambda : self.read_uint(rigidbody_index_size)
\r
31 def __str__(self) -> str:
\r
32 return '<pymeshio.pmx.Loader>'
\r
34 def get_read_text(self, text_encoding) -> "text process function":
\r
35 if text_encoding==0:
\r
37 size=self.read_uint(4)
\r
38 return self.unpack("{0}s".format(size), size).decode("UTF16")
\r
40 elif text_encoding==1:
\r
42 size=self.read_uint(4)
\r
43 return self.unpack("{0}s".format(size), size).decode("UTF8")
\r
46 print("unknown text encoding", text_encoding)
\r
48 def read_vertex(self):
\r
49 return pymeshio.pmx.Vertex(
\r
50 self.read_vector3(), # pos
\r
51 self.read_vector3(), # normal
\r
52 self.read_vector2(), # uv
\r
53 self.read_deform(), # deform(bone weight)
\r
54 self.read_float() # edge factor
\r
57 def read_deform(self):
\r
58 deform_type=self.read_uint(1)
\r
60 return pymeshio.pmx.Bdef1(self.read_bone_index())
\r
62 return pymeshio.pmx.Bdef2(
\r
63 self.read_bone_index(),
\r
64 self.read_bone_index(),
\r
69 return pymeshio.pmx.Bdef4(
\r
70 self.read_bone_index(),
\r
71 self.read_bone_index(),
\r
72 self.read_bone_index(),
\r
73 self.read_bone_index(),
\r
74 self.read_float(), self.read_float(),
\r
75 self.read_float(), self.read_float()
\r
78 raise ParseException("unknown deform type: {0}".format(deform_type))
\r
80 def read_material(self):
\r
81 material=pymeshio.pmx.Material(
\r
82 name=self.read_text(),
\r
83 english_name=self.read_text(),
\r
84 diffuse_color=self.read_rgb(),
\r
85 diffuse_alpha=self.read_float(),
\r
86 specular_color=self.read_rgb(),
\r
87 specular_factor=self.read_float(),
\r
88 ambient_color=self.read_rgb(),
\r
89 flag=self.read_uint(1),
\r
90 edge_color=self.read_rgba(),
\r
91 edge_size=self.read_float(),
\r
92 texture_index=self.read_texture_index(),
\r
93 sphia_texture_index=self.read_texture_index(),
\r
94 sphia_mode=self.read_uint(1),
\r
95 toon_sharing_flag=self.read_uint(1),
\r
97 if material.toon_sharing_flag==0:
\r
98 material.toon_texture_index=self.read_texture_index()
\r
99 elif material.toon_sharing_flag==1:
\r
100 material.toon_texture_index=self.read_uint(1)
\r
102 raise ParseException("unknown toon_sharing_flag {0}".format(material.toon_sharing_flag))
\r
103 material.comment=self.read_text()
\r
104 material.index_count=self.read_uint(4)
\r
107 def read_bone(self):
\r
108 bone=pymeshio.pmx.Bone(
\r
109 name=self.read_text(),
\r
110 english_name=self.read_text(),
\r
111 position=self.read_vector3(),
\r
112 parent_index=self.read_bone_index(),
\r
113 layer=self.read_uint(4),
\r
114 flag=self.read_uint(2)
\r
116 if bone.getConnectionFlag()==0:
\r
117 bone.tail_positoin=self.read_vector3()
\r
118 elif bone.getConnectionFlag()==1:
\r
119 bone.tail_index=self.read_bone_index()
\r
121 raise ParseException("unknown bone conenction flag: {0}".format(
\r
122 bone.getConnectionFlag()))
\r
124 if bone.getRotationFlag()==1 or bone.getTranslationFlag()==1:
\r
125 bone.effect_index=self.read_bone_index()
\r
126 bone.effect_factor=self.read_float()
\r
128 if bone.getFixedAxisFlag()==1:
\r
129 bone.fixed_axis=self.read_vector3()
\r
131 if bone.getLocalCoordinateFlag()==1:
\r
132 bone.local_x_vector=self.read_vector3()
\r
133 bone.local_z_vector=self.read_vector3()
\r
135 if bone.getExternalParentDeformFlag()==1:
\r
136 bone.external_key=self.read_uint(4)
\r
138 if bone.getIkFlag()==1:
\r
139 bone.ik=self.read_ik()
\r
144 ik=pymeshio.pmx.Ik(
\r
145 target_index=self.read_bone_index(),
\r
146 loop=self.read_uint(4),
\r
147 limit_radian=self.read_float())
\r
148 link_size=self.read_uint(4)
\r
149 ik.link=[self.read_ik_link() for i in range(link_size)]
\r
151 def read_ik_link(self):
\r
152 link=pymeshio.pmx.IkLink(
\r
153 self.read_bone_index(),
\r
155 if link.limit_angle==0:
\r
157 elif link.limit_angle==1:
\r
158 link.limit_min=self.read_vector3()
\r
159 link.limit_max=self.read_vector3()
\r
161 raise ParseException("invalid ik link limit_angle: {0}".format(
\r
166 def load(path: str) -> pymeshio.pmx.Model:
\r
167 # general binary loader
\r
168 loader=pymeshio.common.BinaryLoader(
\r
170 pymeshio.common.readall(path)))
\r
173 signature=loader.unpack("4s", 4)
\r
174 if signature!=b"PMX ":
\r
175 raise ParseException("invalid signature", loader.signature)
\r
177 version=loader.read_float()
\r
179 print("unknown version", version)
\r
180 model=pymeshio.pmx.Model(version)
\r
183 flag_bytes=loader.read_uint(1)
\r
185 raise ParseException("invalid flag length", loader.flag_bytes)
\r
186 text_encoding=loader.read_uint(1)
\r
187 extended_uv=loader.read_uint(1)
\r
188 vertex_index_size=loader.read_uint(1)
\r
189 texture_index_size=loader.read_uint(1)
\r
190 material_index_size=loader.read_uint(1)
\r
191 bone_index_size=loader.read_uint(1)
\r
192 morph_index_size=loader.read_uint(1)
\r
193 rigidbody_index_size=loader.read_uint(1)
\r
195 # pmx custom loader
\r
196 loader=Loader(loader.io,
\r
200 texture_index_size,
\r
201 material_index_size,
\r
204 rigidbody_index_size
\r
208 model.name = loader.read_text()
\r
209 model.english_name = loader.read_text()
\r
210 model.comment = loader.read_text()
\r
211 model.english_comment = loader.read_text()
\r
214 vertex_count=loader.read_uint(4)
\r
215 model.vertices=[loader.read_vertex() for i in range(vertex_count)]
\r
218 index_count=loader.read_uint(4)
\r
219 model.indices=[loader.read_vertex_index() for i in range(index_count)]
\r
222 texture_count=loader.read_uint(4)
\r
223 model.textures=[loader.read_text() for i in range(texture_count)]
\r
226 material_count=loader.read_uint(4)
\r
227 model.materials=[loader.read_material() for i in range(material_count)]
\r
230 bone_count=loader.read_uint(4)
\r
231 model.bones=[loader.read_bone() for i in range(bone_count)]
\r