3 import pymeshio.common
\r
7 class Reader(pymeshio.common.BinaryReader):
\r
10 def __init__(self, ios,
\r
15 material_index_size,
\r
18 rigidbody_index_size
\r
20 super(Reader, self).__init__(ios)
\r
21 self.read_text=self.get_read_text(text_encoding)
\r
23 raise pymeshio.common.ParseException(
\r
24 "extended uv is not supported", extended_uv)
\r
25 self.read_vertex_index=lambda : self.read_uint(vertex_index_size)
\r
26 self.read_texture_index=lambda : self.read_uint(texture_index_size)
\r
27 self.read_material_index=lambda : self.read_uint(material_index_size)
\r
28 self.read_bone_index=lambda : self.read_uint(bone_index_size)
\r
29 self.read_morph_index=lambda : self.read_uint(morph_index_size)
\r
30 self.read_rigidbody_index=lambda : self.read_uint(rigidbody_index_size)
\r
33 return '<pymeshio.pmx.Reader>'
\r
35 def get_read_text(self, text_encoding):
\r
36 if text_encoding==0:
\r
38 size=self.read_uint(4)
\r
39 return self.unpack("{0}s".format(size), size).decode("UTF16")
\r
41 elif text_encoding==1:
\r
43 size=self.read_uint(4)
\r
44 return self.unpack("{0}s".format(size), size).decode("UTF8")
\r
47 print("unknown text encoding", text_encoding)
\r
49 def read_vertex(self):
\r
50 return pymeshio.pmx.Vertex(
\r
51 self.read_vector3(), # pos
\r
52 self.read_vector3(), # normal
\r
53 self.read_vector2(), # uv
\r
54 self.read_deform(), # deform(bone weight)
\r
55 self.read_float() # edge factor
\r
58 def read_deform(self):
\r
59 deform_type=self.read_uint(1)
\r
61 return pymeshio.pmx.Bdef1(self.read_bone_index())
\r
62 elif deform_type==1:
\r
63 return pymeshio.pmx.Bdef2(
\r
64 self.read_bone_index(),
\r
65 self.read_bone_index(),
\r
68 elif deform_type==2:
\r
70 raise pymeshio.common.ParseException(
\r
71 "not implemented Bdef4")
\r
73 raise pymeshio.common.ParseException(
\r
74 "unknown deform type: {0}".format(deform_type))
\r
76 def read_material(self):
\r
77 material=pymeshio.pmx.Material(
\r
78 name=self.read_text(),
\r
79 english_name=self.read_text(),
\r
80 diffuse_color=self.read_rgb(),
\r
81 diffuse_alpha=self.read_float(),
\r
82 specular_color=self.read_rgb(),
\r
83 specular_factor=self.read_float(),
\r
84 ambient_color=self.read_rgb(),
\r
85 flag=self.read_uint(1),
\r
86 edge_color=self.read_rgba(),
\r
87 edge_size=self.read_float(),
\r
88 texture_index=self.read_texture_index(),
\r
89 sphia_texture_index=self.read_texture_index(),
\r
90 sphia_mode=self.read_uint(1),
\r
91 toon_sharing_flag=self.read_uint(1),
\r
93 if material.toon_sharing_flag==0:
\r
94 material.toon_texture_index=self.read_texture_index()
\r
95 elif material.toon_sharing_flag==1:
\r
96 material.toon_texture_index=self.read_uint(1)
\r
98 raise pymeshio.common.ParseException(
\r
99 "unknown toon_sharing_flag {0}".format(
\r
100 material.toon_sharing_flag))
\r
101 material.comment=self.read_text()
\r
102 material.vertex_count=self.read_uint(4)
\r
105 def read_bone(self):
\r
106 bone=pymeshio.pmx.Bone(
\r
107 name=self.read_text(),
\r
108 english_name=self.read_text(),
\r
109 position=self.read_vector3(),
\r
110 parent_index=self.read_bone_index(),
\r
111 layer=self.read_uint(4),
\r
112 flag=self.read_uint(2)
\r
114 if bone.getConnectionFlag()==0:
\r
115 bone.tail_positoin=self.read_vector3()
\r
116 elif bone.getConnectionFlag()==1:
\r
117 bone.tail_index=self.read_bone_index()
\r
119 raise pymeshio.common.ParseException(
\r
120 "unknown bone conenction flag: {0}".format(
\r
121 bone.getConnectionFlag()))
\r
123 if bone.getRotationFlag()==1 or bone.getTranslationFlag()==1:
\r
124 bone.effect_index=self.read_bone_index()
\r
125 bone.effect_factor=self.read_float()
\r
127 if bone.getFixedAxisFlag()==1:
\r
128 bone.fixed_axis=self.read_vector3()
\r
130 if bone.getLocalCoordinateFlag()==1:
\r
131 bone.local_x_vector=self.read_vector3()
\r
132 bone.local_z_vector=self.read_vector3()
\r
134 if bone.getExternalParentDeformFlag()==1:
\r
135 bone.external_key=self.read_uint(4)
\r
137 if bone.getIkFlag()==1:
\r
138 bone.ik=self.read_ik()
\r
143 ik=pymeshio.pmx.Ik(
\r
144 target_index=self.read_bone_index(),
\r
145 loop=self.read_uint(4),
\r
146 limit_radian=self.read_float())
\r
147 link_size=self.read_uint(4)
\r
148 ik.link=[self.read_ik_link()
\r
149 for _ 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 pymeshio.common.ParseException(
\r
162 "invalid ik link limit_angle: {0}".format(
\r
166 def read_morgh(self):
\r
167 name=self.read_text()
\r
168 english_name=self.read_text()
\r
169 panel=self.read_uint(1)
\r
170 morph_type=self.read_uint(1)
\r
171 offset_size=self.read_uint(4)
\r
174 raise pymeshio.common.ParseException(
\r
175 "not implemented GroupMorph")
\r
176 elif morph_type==1:
\r
177 morph=pymeshio.pmx.Morph(name, english_name,
\r
179 morph.offsets=[self.read_vertex_morph_offset()
\r
180 for _ in range(offset_size)]
\r
182 elif morph_type==2:
\r
184 raise pymeshio.common.ParseException(
\r
185 "not implemented BoneMorph")
\r
186 elif morph_type==3:
\r
188 raise pymeshio.common.ParseException(
\r
189 "not implemented UvMorph")
\r
190 elif morph_type==4:
\r
192 raise pymeshio.common.ParseException(
\r
193 "not implemented extended UvMorph1")
\r
194 elif morph_type==5:
\r
196 raise pymeshio.common.ParseException(
\r
197 "not implemented extended UvMorph2")
\r
198 elif morph_type==6:
\r
200 raise pymeshio.common.ParseException(
\r
201 "not implemented extended UvMorph3")
\r
202 elif morph_type==7:
\r
204 raise pymeshio.common.ParseException(
\r
205 "not implemented extended UvMorph4")
\r
206 elif morph_type==8:
\r
208 raise pymeshio.common.ParseException(
\r
209 "not implemented extended MaterialMorph")
\r
211 raise pymeshio.common.ParseException(
\r
212 "unknown morph type: {0}".format(morph_type))
\r
214 def read_vertex_morph_offset(self):
\r
215 return pymeshio.pmx.VerexMorphOffset(
\r
216 self.read_vertex_index(), self.read_vector3())
\r
218 def read_display_slot(self):
\r
219 display_slot=pymeshio.pmx.DisplaySlot(self.read_text(), self.read_text(),
\r
221 display_count=self.read_uint(4)
\r
222 for _ in range(display_count):
\r
223 display_type=self.read_uint(1)
\r
224 if display_type==0:
\r
225 display_slot.refrences.append(
\r
226 (display_type, self.read_bone_index()))
\r
227 elif display_type==1:
\r
228 display_slot.refrences.append(
\r
229 (display_type, self.read_morph_index()))
\r
231 raise pymeshio.common.ParseException(
\r
232 "unknown display_type: {0}".format(display_type))
\r
234 def read_rigidbody(self):
\r
235 return pymeshio.pmx.RigidBody(
\r
236 name=self.read_text(),
\r
237 english_name=self.read_text(),
\r
238 bone_index=self.read_bone_index(),
\r
239 collision_group=self.read_uint(1),
\r
240 no_collision_group=self.read_uint(2),
\r
241 shape_type=self.read_uint(1),
\r
242 shape_size=self.read_vector3(),
\r
243 shape_position=self.read_vector3(),
\r
244 shape_rotation=self.read_vector3(),
\r
245 mass=self.read_float(),
\r
246 linear_damping=self.read_float(),
\r
247 angular_damping=self.read_float(),
\r
248 restitution=self.read_float(),
\r
249 friction=self.read_float(),
\r
250 mode=self.read_uint(1)
\r
253 def read_joint(self):
\r
254 return pymeshio.pmx.Joint(
\r
255 name=self.read_text(),
\r
256 english_name=self.read_text(),
\r
257 joint_type=self.read_uint(1),
\r
258 rigidbody_index_a=self.read_rigidbody_index(),
\r
259 rigidbody_index_b=self.read_rigidbody_index(),
\r
260 position=self.read_vector3(),
\r
261 rotation=self.read_vector3(),
\r
262 translation_limit_min=self.read_vector3(),
\r
263 translation_limit_max=self.read_vector3(),
\r
264 rotation_limit_min=self.read_vector3(),
\r
265 rotation_limit_max=self.read_vector3(),
\r
266 spring_constant_translation=self.read_vector3(),
\r
267 spring_constant_rotation=self.read_vector3())
\r
270 def read_from_file(path):
\r
271 return read(io.BytesIO(pymeshio.common.readall(path)))
\r
275 assert(isinstance(ios, io.IOBase))
\r
276 reader=pymeshio.common.BinaryReader(ios)
\r
279 signature=reader.unpack("4s", 4)
\r
280 if signature!=b"PMX ":
\r
281 raise pymeshio.common.ParseException(
\r
282 "invalid signature", signature)
\r
284 version=reader.read_float()
\r
286 print("unknown version", version)
\r
287 model=pymeshio.pmx.Model(version)
\r
290 flag_bytes=reader.read_uint(1)
\r
292 raise pymeshio.common.ParseException(
\r
293 "invalid flag length", reader.flag_bytes)
\r
294 text_encoding=reader.read_uint(1)
\r
295 extended_uv=reader.read_uint(1)
\r
296 vertex_index_size=reader.read_uint(1)
\r
297 texture_index_size=reader.read_uint(1)
\r
298 material_index_size=reader.read_uint(1)
\r
299 bone_index_size=reader.read_uint(1)
\r
300 morph_index_size=reader.read_uint(1)
\r
301 rigidbody_index_size=reader.read_uint(1)
\r
303 # pmx custom reader
\r
304 reader=Reader(reader.io,
\r
308 texture_index_size,
\r
309 material_index_size,
\r
312 rigidbody_index_size
\r
316 model.name = reader.read_text()
\r
317 model.english_name = reader.read_text()
\r
318 model.comment = reader.read_text()
\r
319 model.english_comment = reader.read_text()
\r
322 model.vertices=[reader.read_vertex()
\r
323 for _ in range(reader.read_uint(4))]
\r
324 model.indices=[reader.read_vertex_index()
\r
325 for _ in range(reader.read_uint(4))]
\r
326 model.textures=[reader.read_text()
\r
327 for _ in range(reader.read_uint(4))]
\r
328 model.materials=[reader.read_material()
\r
329 for _ in range(reader.read_uint(4))]
\r
330 model.bones=[reader.read_bone()
\r
331 for _ in range(reader.read_uint(4))]
\r
332 model.morphs=[reader.read_morgh()
\r
333 for _ in range(reader.read_uint(4))]
\r
334 model.display_slots=[reader.read_display_slot()
\r
335 for _ in range(reader.read_uint(4))]
\r
336 model.rigidbodies=[reader.read_rigidbody()
\r
337 for _ in range(reader.read_uint(4))]
\r
338 model.joints=[reader.read_joint()
\r
339 for _ in range(reader.read_uint(4))]
\r