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 pymeshio.common.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
61 elif deform_type==1:
\r
62 return pymeshio.pmx.Bdef2(
\r
63 self.read_bone_index(),
\r
64 self.read_bone_index(),
\r
67 elif deform_type==2:
\r
69 raise pymeshio.common.ParseException("not implemented Bdef4")
\r
71 raise pymeshio.common.ParseException("unknown deform type: {0}".format(deform_type))
\r
73 def read_material(self):
\r
74 material=pymeshio.pmx.Material(
\r
75 name=self.read_text(),
\r
76 english_name=self.read_text(),
\r
77 diffuse_color=self.read_rgb(),
\r
78 diffuse_alpha=self.read_float(),
\r
79 specular_color=self.read_rgb(),
\r
80 specular_factor=self.read_float(),
\r
81 ambient_color=self.read_rgb(),
\r
82 flag=self.read_uint(1),
\r
83 edge_color=self.read_rgba(),
\r
84 edge_size=self.read_float(),
\r
85 texture_index=self.read_texture_index(),
\r
86 sphia_texture_index=self.read_texture_index(),
\r
87 sphia_mode=self.read_uint(1),
\r
88 toon_sharing_flag=self.read_uint(1),
\r
90 if material.toon_sharing_flag==0:
\r
91 material.toon_texture_index=self.read_texture_index()
\r
92 elif material.toon_sharing_flag==1:
\r
93 material.toon_texture_index=self.read_uint(1)
\r
95 raise pymeshio.common.ParseException("unknown toon_sharing_flag {0}".format(material.toon_sharing_flag))
\r
96 material.comment=self.read_text()
\r
97 material.index_count=self.read_uint(4)
\r
100 def read_bone(self):
\r
101 bone=pymeshio.pmx.Bone(
\r
102 name=self.read_text(),
\r
103 english_name=self.read_text(),
\r
104 position=self.read_vector3(),
\r
105 parent_index=self.read_bone_index(),
\r
106 layer=self.read_uint(4),
\r
107 flag=self.read_uint(2)
\r
109 if bone.getConnectionFlag()==0:
\r
110 bone.tail_positoin=self.read_vector3()
\r
111 elif bone.getConnectionFlag()==1:
\r
112 bone.tail_index=self.read_bone_index()
\r
114 raise pymeshio.common.ParseException("unknown bone conenction flag: {0}".format(
\r
115 bone.getConnectionFlag()))
\r
117 if bone.getRotationFlag()==1 or bone.getTranslationFlag()==1:
\r
118 bone.effect_index=self.read_bone_index()
\r
119 bone.effect_factor=self.read_float()
\r
121 if bone.getFixedAxisFlag()==1:
\r
122 bone.fixed_axis=self.read_vector3()
\r
124 if bone.getLocalCoordinateFlag()==1:
\r
125 bone.local_x_vector=self.read_vector3()
\r
126 bone.local_z_vector=self.read_vector3()
\r
128 if bone.getExternalParentDeformFlag()==1:
\r
129 bone.external_key=self.read_uint(4)
\r
131 if bone.getIkFlag()==1:
\r
132 bone.ik=self.read_ik()
\r
137 ik=pymeshio.pmx.Ik(
\r
138 target_index=self.read_bone_index(),
\r
139 loop=self.read_uint(4),
\r
140 limit_radian=self.read_float())
\r
141 link_size=self.read_uint(4)
\r
142 ik.link=[self.read_ik_link() for _ in range(link_size)]
\r
144 def read_ik_link(self):
\r
145 link=pymeshio.pmx.IkLink(
\r
146 self.read_bone_index(),
\r
148 if link.limit_angle==0:
\r
150 elif link.limit_angle==1:
\r
151 link.limit_min=self.read_vector3()
\r
152 link.limit_max=self.read_vector3()
\r
154 raise pymeshio.common.ParseException("invalid ik link limit_angle: {0}".format(
\r
158 def read_morgh(self):
\r
159 name=self.read_text()
\r
160 english_name=self.read_text()
\r
161 panel=self.read_uint(1)
\r
162 morph_type=self.read_uint(1)
\r
163 offset_size=self.read_uint(4)
\r
166 raise pymeshio.common.ParseException("not implemented GroupMorph")
\r
167 elif morph_type==1:
\r
168 morph=pymeshio.pmx.Morph(name, english_name, panel, morph_type)
\r
169 morph.offsets=[self.read_vertex_morph_offset() for _ in range(offset_size)]
\r
171 elif morph_type==2:
\r
173 raise pymeshio.common.ParseException("not implemented BoneMorph")
\r
174 elif morph_type==3:
\r
176 raise pymeshio.common.ParseException("not implemented UvMorph")
\r
177 elif morph_type==4:
\r
179 raise pymeshio.common.ParseException("not implemented extended UvMorph1")
\r
180 elif morph_type==5:
\r
182 raise pymeshio.common.ParseException("not implemented extended UvMorph2")
\r
183 elif morph_type==6:
\r
185 raise pymeshio.common.ParseException("not implemented extended UvMorph3")
\r
186 elif morph_type==7:
\r
188 raise pymeshio.common.ParseException("not implemented extended UvMorph4")
\r
189 elif morph_type==8:
\r
191 raise pymeshio.common.ParseException("not implemented extended MaterialMorph")
\r
193 raise pymeshio.common.ParseException("unknown morph type: {0}".format(morph_type))
\r
195 def read_vertex_morph_offset(self):
\r
196 return pymeshio.pmx.VerexMorphOffset(self.read_vertex_index(), self.read_vector3())
\r
198 def read_display_slot(self):
\r
202 def load(path: str) -> pymeshio.pmx.Model:
\r
203 # general binary loader
\r
204 loader=pymeshio.common.BinaryLoader(
\r
206 pymeshio.common.readall(path)))
\r
209 signature=loader.unpack("4s", 4)
\r
210 if signature!=b"PMX ":
\r
211 raise pymeshio.common.ParseException("invalid signature", loader.signature)
\r
213 version=loader.read_float()
\r
215 print("unknown version", version)
\r
216 model=pymeshio.pmx.Model(version)
\r
219 flag_bytes=loader.read_uint(1)
\r
221 raise pymeshio.common.ParseException("invalid flag length", loader.flag_bytes)
\r
222 text_encoding=loader.read_uint(1)
\r
223 extended_uv=loader.read_uint(1)
\r
224 vertex_index_size=loader.read_uint(1)
\r
225 texture_index_size=loader.read_uint(1)
\r
226 material_index_size=loader.read_uint(1)
\r
227 bone_index_size=loader.read_uint(1)
\r
228 morph_index_size=loader.read_uint(1)
\r
229 rigidbody_index_size=loader.read_uint(1)
\r
231 # pmx custom loader
\r
232 loader=Loader(loader.io,
\r
236 texture_index_size,
\r
237 material_index_size,
\r
240 rigidbody_index_size
\r
244 model.name = loader.read_text()
\r
245 model.english_name = loader.read_text()
\r
246 model.comment = loader.read_text()
\r
247 model.english_comment = loader.read_text()
\r
250 vertex_count=loader.read_uint(4)
\r
251 model.vertices=[loader.read_vertex() for _ in range(vertex_count)]
\r
253 index_count=loader.read_uint(4)
\r
254 model.indices=[loader.read_vertex_index() for _ in range(index_count)]
\r
256 texture_count=loader.read_uint(4)
\r
257 model.textures=[loader.read_text() for _ in range(texture_count)]
\r
259 material_count=loader.read_uint(4)
\r
260 model.materials=[loader.read_material() for _ in range(material_count)]
\r
262 bone_count=loader.read_uint(4)
\r
263 model.bones=[loader.read_bone() for _ in range(bone_count)]
\r
265 morph_count=loader.read_uint(4)
\r
266 model.morphs=[loader.read_morgh() for _ in range(morph_count)]
\r
268 display_slot_count=loader.read_uint(4)
\r
269 model.display_slots=[loader.read_display_slot() for _ in range(display_slot_count)]
\r