3 import pymeshio.common
\r
7 class Loader(pymeshio.common.BinaryLoader):
\r
10 def __init__(self, io, version):
\r
11 super(Loader, self).__init__(io)
\r
12 self.version=version
\r
14 def read_text(self, size):
\r
17 src=self.unpack("%ds" % size, size)
\r
18 assert(type(src)==bytes)
\r
19 pos = src.find(b"\x00")
\r
25 def read_vertex(self):
\r
26 return pymeshio.pmd.Vertex(
\r
27 self.read_vector3(),
\r
28 self.read_vector3(),
\r
29 self.read_vector2(),
\r
35 def read_material(self):
\r
36 return pymeshio.pmd.Material(
\r
37 diffuse_color=self.read_rgb(),
\r
38 alpha=self.read_float(),
\r
39 specular_factor=self.read_float(),
\r
40 specular_color=self.read_rgb(),
\r
41 ambient_color=self.read_rgb(),
\r
42 toon_index=self.read_uint(1),
\r
43 edge_flag=self.read_uint(1),
\r
44 vertex_count=self.read_uint(4),
\r
45 texture_file=self.read_text(20)
\r
48 def read_bone(self):
\r
49 name=self.read_text(20)
\r
50 parent_index=self.read_uint(2)
\r
51 tail_index=self.read_uint(2)
\r
52 bone=pymeshio.pmd.createBone(name, self.read_uint(1))
\r
53 bone.parent_index=parent_index
\r
54 bone.tail_index=tail_index
\r
55 bone.ik_index = self.read_uint(2)
\r
56 bone.pos = self.read_vector3()
\r
60 ik=pymeshio.pmd.IK(self.read_uint(2), self.read_uint(2))
\r
61 ik.length = self.read_uint(1)
\r
62 ik.iterations = self.read_uint(2)
\r
63 ik.weight = self.read_float()
\r
64 ik.children=[self.read_uint(2) for _ in range(ik.length)]
\r
67 def read_morph(self):
\r
68 skin=pymeshio.pmd.Skin(self.read_text(20))
\r
69 skin_size = self.read_uint(4)
\r
70 skin.type = self.read_uint(1)
\r
71 for j in range(skin_size):
\r
72 skin.indices.append(self.read_uint(4))
\r
73 skin.pos_list.append(self.read_vector3())
\r
76 def read_rigidbody(self):
\r
77 return pymeshio.pmd.RigidBody(
\r
78 name=self.read_text(20),
\r
79 bone_index=self.read_uint(2),
\r
80 collision_group=self.read_uint(1),
\r
81 no_collision_group=self.read_uint(2),
\r
82 shape_type=self.read_uint(1),
\r
83 shape_size=self.read_vector3(),
\r
84 shape_position=self.read_vector3(),
\r
85 shape_rotation=self.read_vector3(),
\r
86 mass=self.read_float(),
\r
87 linear_damping=self.read_float(),
\r
88 angular_damping=self.read_float(),
\r
89 restitution=self.read_float(),
\r
90 friction=self.read_float(),
\r
91 mode=self.read_uint(1)
\r
94 def read_joint(self):
\r
95 return pymeshio.pmd.Joint(
\r
96 name=self.read_text(20),
\r
97 rigidbody_index_a=self.read_uint(4),
\r
98 rigidbody_index_b=self.read_uint(4),
\r
99 position=self.read_vector3(),
\r
100 rotation=self.read_vector3(),
\r
101 translation_limit_min=self.read_vector3(),
\r
102 translation_limit_max=self.read_vector3(),
\r
103 rotation_limit_min=self.read_vector3(),
\r
104 rotation_limit_max=self.read_vector3(),
\r
105 spring_constant_translation=self.read_vector3(),
\r
106 spring_constant_rotation=self.read_vector3())
\r
110 def __load(loader, model):
\r
112 model.name=loader.read_text(20)
\r
113 model.comment=loader.read_text(256)
\r
116 model.vertices=[loader.read_vertex()
\r
117 for _ in range(loader.read_uint(4))]
\r
118 model.indices=[loader.read_uint(2)
\r
119 for _ in range(loader.read_uint(4))]
\r
120 model.materials=[loader.read_material()
\r
121 for _ in range(loader.read_uint(4))]
\r
122 model.bones=[loader.read_bone()
\r
123 for _ in range(loader.read_uint(2))]
\r
124 model.ik_list=[loader.read_ik()
\r
125 for _ in range(loader.read_uint(2))]
\r
126 model.morphs=[loader.read_morph()
\r
127 for _ in range(loader.read_uint(2))]
\r
128 model.morph_indices=[loader.read_uint(2)
\r
129 for _ in range(loader.read_uint(1))]
\r
130 model.bone_group_list=[loader.read_text(50)
\r
131 for _ in range(loader.read_uint(1))]
\r
132 model.bone_display_list=[(loader.read_uint(2), loader.read_uint(1))
\r
133 for _i in range(loader.read_uint(4))]
\r
135 if loader.is_end():
\r
139 ############################################################
\r
140 # extend1: english name
\r
141 ############################################################
\r
142 if loader.read_uint(1)==0:
\r
143 print("no extend flag")
\r
145 model.english_name=loader.read_text(20)
\r
146 model.english_comment=loader.read_text(256)
\r
147 for bone in model.bones:
\r
148 bone.english_name=loader.read_text(20)
\r
149 for morph in model.morphs:
\r
150 if morph.name==b'base':
\r
152 morph.english_name=loader.read_text(20)
\r
153 for bone_group in model.bone_group_list:
\r
154 bone_group=loader.read_text(50)
\r
156 ############################################################
\r
157 # extend2: toon_textures
\r
158 ############################################################
\r
159 if loader.is_end():
\r
162 model.toon_textures=[loader.read_text(100)
\r
163 for _ in range(10)]
\r
165 ############################################################
\r
166 # extend2: rigidbodies and joints
\r
167 ############################################################
\r
168 if loader.is_end():
\r
171 model.rigidbodies=[loader.read_rigidbody()
\r
172 for _ in range(loader.read_uint(4))]
\r
173 model.joints=[loader.read_joint()
\r
174 for _ in range(loader.read_uint(4))]
\r
180 # general binary loader
\r
181 #loader=pymeshio.common.BinaryLoader(open(path, 'rb'))
\r
182 loader=pymeshio.common.BinaryLoader(io.BytesIO(pymeshio.common.readall(path)))
\r
185 signature=loader.unpack("3s", 3)
\r
186 if signature!=b"Pmd":
\r
187 raise pymeshio.common.ParseException(
\r
188 "invalid signature: {0}".format(signature))
\r
189 version=loader.read_float()
\r
191 model=pymeshio.pmd.Model(version)
\r
192 loader=Loader(loader.io, version)
\r
193 if(__load(loader, model)):
\r
195 if not loader.is_end():
\r
196 print("can not reach eof.")
\r
199 for i, child in enumerate(model.bones):
\r
200 if child.parent_index==0xFFFF:
\r
202 model.no_parent_bones.append(child)
\r
206 parent=model.bones[child.parent_index]
\r
207 child.parent=parent
\r
208 parent.children.append(child)
\r
210 if child.hasChild():
\r
211 child.tail=model.bones[child.tail_index].pos
\r
216 def save(self, path):
\r
217 io=open(path, 'wb')
\r
222 io.write(struct.pack("f", self.version))
\r
223 io.write(struct.pack("20s", self.name))
\r
224 io.write(struct.pack("256s", self.comment))
\r
227 io.write(struct.pack("I", len(self.vertices)))
\r
228 sVertex=struct.Struct("=8f2H2B") # 38byte
\r
229 assert(sVertex.size==38)
\r
230 for v in self.vertices:
\r
231 data=sVertex.pack(
\r
232 v.pos[0], v.pos[1], v.pos[2],
\r
233 v.normal[0], v.normal[1], v.normal[2],
\r
235 v.bone0, v.bone1, v.weight0, v.edge_flag)
\r
239 io.write(struct.pack("I", len(self.indices)))
\r
240 io.write(struct.pack("=%dH" % len(self.indices), *self.indices))
\r
243 io.write(struct.pack("I", len(self.materials)))
\r
244 sMaterial=struct.Struct("=3fff3f3fBBI20s") # 70byte
\r
245 assert(sMaterial.size==70)
\r
246 for m in self.materials:
\r
247 io.write(sMaterial.pack(
\r
248 m.diffuse[0], m.diffuse[1], m.diffuse[2], m.diffuse[3],
\r
250 m.specular[0], m.specular[1], m.specular[2],
\r
251 m.ambient[0], m.ambient[1], m.ambient[2],
\r
252 m.toon_index, m.flag,
\r
258 io.write(struct.pack("H", len(self.bones)))
\r
259 sBone=struct.Struct("=20sHHBH3f")
\r
260 assert(sBone.size==39)
\r
261 for b in self.bones:
\r
262 io.write(sBone.pack(
\r
264 b.parent_index, b.tail_index, b.type, b.ik_index,
\r
265 b.pos[0], b.pos[1], b.pos[2]))
\r
268 io.write(struct.pack("H", len(self.ik_list)))
\r
269 for ik in self.ik_list:
\r
270 io.write(struct.pack("=2HBHf",
\r
271 ik.index, ik.target, ik.length, ik.iterations, ik.weight
\r
273 for c in ik.children:
\r
274 io.write(struct.pack("H", c))
\r
277 io.write(struct.pack("H", len(self.morph_list)))
\r
278 for s in self.morph_list:
\r
279 io.write(struct.pack("20sIB",
\r
280 s.name, len(s.indices), s.type))
\r
281 for i, v in zip(s.indices, s.pos_list):
\r
282 io.write(struct.pack("I3f", i, v[0], v[1], v[2]))
\r
285 io.write(struct.pack("B", len(self.face_list)))
\r
286 for i in self.face_list:
\r
287 io.write(struct.pack("H", i))
\r
290 io.write(struct.pack("B", len(self.bone_group_list)))
\r
291 for g in self.bone_group_list:
\r
292 io.write(struct.pack("50s", g.name))
\r
294 io.write(struct.pack("I", len(self.bone_display_list)))
\r
295 for l in self.bone_display_list:
\r
296 io.write(struct.pack("=HB", *l))
\r
298 ############################################################
\r
300 ############################################################
\r
301 io.write(struct.pack("B", 1))
\r
303 io.write(struct.pack("=20s", self.english_name))
\r
304 io.write(struct.pack("=256s", self.english_comment))
\r
305 # english bone name
\r
306 for bone in self.bones:
\r
307 io.write(struct.pack("=20s", bone.english_name))
\r
308 # english skin list
\r
309 for skin in self.morph_list:
\r
311 if skin.name==b'base':
\r
313 io.write(struct.pack("=20s", skin.english_name))
\r
314 # english bone list
\r
315 for bone_group in self.bone_group_list:
\r
316 io.write(struct.pack("50s", bone_group.english_name))
\r
318 for toon_texture in self.toon_textures:
\r
319 io.write(struct.pack("=100s", toon_texture))
\r
321 io.write(struct.pack("I", len(self.rigidbodies)))
\r
322 for r in self.rigidbodies:
\r
323 io.write(struct.pack("=20sHBHB14fB",
\r
324 r.name, r.boneIndex, r.group, r.target, r.shapeType,
\r
326 r.position.x, r.position.y, r.position.z,
\r
327 r.rotation.x, r.rotation.y, r.rotation.z,
\r
329 r.linearDamping, r.angularDamping, r.restitution,
\r
330 r.friction, r.processType))
\r
333 io.write(struct.pack("I", len(self.constraints)))
\r
334 for c in self.constraints:
\r
335 io.write(struct.pack("=20sII24f",
\r
336 c.name, c.rigidA, c.rigidB,
\r
337 c.pos.x, c.pos.y, c.pos.z,
\r
338 c.rot.x, c.rot.y, c.rot.z,
\r
339 c.constraintPosMin.x, c.constraintPosMin.y, c.constraintPosMin.z,
\r
340 c.constraintPosMax.x, c.constraintPosMax.y, c.constraintPosMax.z,
\r
341 c.constraintRotMin.x, c.constraintRotMin.y, c.constraintRotMin.z,
\r
342 c.constraintRotMax.x, c.constraintRotMax.y, c.constraintRotMax.z,
\r
343 c.springPos.x, c.springPos.y, c.springPos.z,
\r
344 c.springRot.x, c.springRot.y, c.springRot.z
\r