6 ###############################################################################
8 ###############################################################################
10 __slots__=['pos', 'normal', 'uv', 'bone0', 'bone1', 'weight0', 'edge_flag']
11 def __init__(self, x=0, y=0, z=0, nx=0, ny=0, nz=0, u=0, v=0,
12 bone0=0, bone1=0, weight0=0, edge_flag=0):
13 self.pos=Vector3(x, y, z)
14 self.normal=Vector3(nx, ny, nz)
19 self.edge_flag=edge_flag
22 return "<%s %s %s, (%d, %d, %d)>" % (str(self.pos), str(self.normal), str(self.uv), self.bone0, self.bone1, self.weight0)
24 def __getitem__(self, key):
35 class Material(object):
37 'diffuse', 'shinness', 'specular',
38 'ambient', 'vertex_count', 'texture', 'toon_index', 'flag',
41 def __init__(self, dr=0, dg=0, db=0, alpha=1,
42 specular=0, sr=0, sg=0, sb=0, ar=0, ag=0, ab=0):
43 self.diffuse=RGBA(dr, dg, db, alpha)
44 self.specular=RGBA(sr, sg, sb)
45 self.shinness=specular
46 self.ambient=RGBA(ar, ag, ab)
53 return "<Material [%f, %f, %f, %f]>" % (
54 self.diffuse[0], self.diffuse[1],
55 self.diffuse[2], self.diffuse[3],
58 def getTexture(self): return self.texture.decode('cp932')
59 def setTexture(self, u): self.texture=u
62 # @return 各マテリアルについて、そのマテリアルが保持する面の回数だけ
64 def material_per_face(materials):
66 for x in xrange(int(m.vertex_count/3)):
82 __slots__=['name', 'index', 'type', 'parent', 'ik', 'pos',
83 'children', 'english_name', 'ik_index',
84 'parent_index', 'tail_index', 'tail',
86 def __init__(self, name='bone', type=0):
90 self.parent_index=0xFFFF
92 self.tail=Vector3(0, 0, 0)
95 self.pos=Vector3(0, 0, 0)
99 def getName(self): return self.name.decode('cp932')
100 def setName(self, u): self.name=u
101 def setEnglishName(self, u): self.english_name=u
104 return self.parent_index!=0xFFFF
107 return self.tail_index!=0
109 def display(self, indent=[]):
112 for i, is_end in enumerate(indent):
116 prefix+=' ' if is_end else ' |'
117 uni='%s +%s(%s)' % (prefix, unicode(self), self.english_name)
118 print(uni.encode(ENCODING))
120 uni='%s(%s)' % (unicode(self), self.english_name)
121 print(uni.encode(ENCODING))
123 child_count=len(self.children)
124 for i in xrange(child_count):
125 child=self.children[i]
127 child.display(indent+[False])
130 child.display(indent+[True])
133 class Bone_Rotate(Bone):
135 def __init__(self, name):
136 super(Bone_Rotate, self).__init__(name, 0)
138 return '<ROTATE %s>' % (self.name)
140 class Bone_RotateMove(Bone):
142 def __init__(self, name):
143 super(Bone_RotateMove, self).__init__(name, 1)
145 return '<ROTATE_MOVE %s>' % (self.name)
149 def __init__(self, name):
150 super(Bone_IK, self).__init__(name, 2)
152 return '<IK %s>' % (self.name)
154 class Bone_IKRotateInfl(Bone):
156 def __init__(self, name):
157 super(Bone_IKRotateInfl, self).__init__(name, 4)
159 return '<IK_ROTATE_INFL %s>' % (self.name)
161 class Bone_RotateInfl(Bone):
163 def __init__(self, name):
164 super(Bone_RotateInfl, self).__init__(name, 5)
166 return '<ROTATE_INFL %s>' % (self.name)
168 class Bone_IKTarget(Bone):
170 def __init__(self, name):
171 super(Bone_IKTarget, self).__init__(name, 6)
173 return '<IK_TARGET %s>' % (self.name)
175 class Bone_Unvisible(Bone):
177 def __init__(self, name):
178 super(Bone_Unvisible, self).__init__(name, 7)
180 return '<UNVISIBLE %s>' % (self.name)
182 class Bone_Rolling(Bone):
184 def __init__(self, name):
185 super(Bone_Rolling, self).__init__(name, 8)
187 return '<ROLLING %s>' % (self.name)
189 class Bone_Tweak(Bone):
191 def __init__(self, name):
192 super(Bone_Tweak, self).__init__(name, 9)
194 return '<TWEAK %s>' % (self.name)
197 def createBone(name, type):
199 return Bone_Rotate(name)
201 return Bone_RotateMove(name)
205 raise Exception("no used bone type: 3(%s)" % name)
207 return Bone_IKRotateInfl(name)
209 return Bone_RotateInfl(name)
211 return Bone_IKTarget(name)
213 return Bone_Unvisible(name)
215 return Bone_Rolling(name)
217 return Bone_Tweak(name)
219 raise Exception("unknown bone type: %d(%s)", type, name)
223 __slots__=['index', 'target', 'iterations', 'weight', 'length', 'children']
224 def __init__(self, index=0, target=0):
232 return "<IK index: %d, target: %d, iterations: %d, weight: %f, children: %s(%d)>" %(self.index, self.target, self.iterations, self.weight, '-'.join([str(i) for i in self.children]), len(self.children))
236 __slots__=['name', 'type', 'indices', 'pos_list', 'english_name',
238 def __init__(self, name='skin'):
246 def getName(self): return self.name.decode('cp932')
247 def setName(self, u): self.name=u
248 def setEnglishName(self, u): self.english_name=u
250 def append(self, index, x, y, z):
251 self.indices.append(index)
252 self.pos_list.append(Vector3(x, y, z))
255 return '<Skin name: "%s", type: %d, vertex: %d>' % (
256 self.name, self.type, len(self.indices))
259 class BoneGroup(object):
260 __slots__=['name', 'english_name']
261 def __init__(self, name='group'): self.name=name; self.english_name='center'
262 def getName(self): return self.name.decode('cp932')
263 def setName(self, u): self.name=u
264 def getEnglishName(self): return self.english_name.decode('cp932')
265 def setEnglishName(self, u): self.english_name=u
268 class RigidBody(object):
269 __slots__=['name', 'boneIndex', 'group', 'target', 'shapeType',
270 'w', 'h', 'd', 'position', 'rotation', 'weight',
271 'linearDamping', 'angularDamping', 'restitution', 'friction', 'processType'
273 def __init__(self, name):
275 self.position=Vector3()
276 self.rotation=Vector3()
279 class Constraint(object):
280 __slots__=[ 'name', 'rigidA', 'rigidB', 'pos', 'rot',
281 'constraintPosMin', 'constraintPosMax',
282 'constraintRotMin', 'constraintRotMax',
283 'springPos', 'springRot',
285 def __init__(self, name):
289 self.constraintPosMin=Vector3()
290 self.constraintPosMax=Vector3()
291 self.constraintRotMin=Vector3()
292 self.constraintRotMax=Vector3()
293 self.springPos=Vector3()
294 self.springRot=Vector3()
298 __slots__=['io', 'end', 'pos',
299 'version', 'name', 'comment',
300 'english_name', 'english_comment',
301 'vertices', 'indices', 'materials', 'bones',
302 'ik_list', 'morph_list',
303 'face_list', 'bone_group_list', 'bone_display_list',
306 'rigidbodies', 'constraints',
311 self.comment=b"default"
312 self.english_name=b'default'
313 self.english_comment=b'default'
322 self.bone_group_list=[]
323 self.bone_display_list=[]
326 b'toon01.bmp', b'toon02.bmp',
327 b'toon03.bmp', b'toon04.bmp',
328 b'toon05.bmp', b'toon06.bmp',
329 b'toon07.bmp', b'toon08.bmp',
330 b'toon09.bmp', b'toon10.bmp',
333 self.no_parent_bones=[]
338 def getName(self): return self.name.decode('cp932')
339 def setName(self, u): self.name=u
340 def getComment(self): return self.comment.decode('cp932')
341 def setComment(self, u): self.comment=u
342 def getEnglishName(self): return self.english_name.decode('cp932')
343 def setEnglishName(self, u): self.english_name=u
344 def getEnglishComment(self): return self.english_comment.decode('cp932')
345 def setEnglishComment(self, u): self.english_comment=u
347 def getToonTexture(self, i): return self.toon_textures[i]
348 def each_vertex(self): return self.vertices
349 def getUV(self, i): return self.vertices[i].uv
352 self.vertices.append(v)
354 def addMaterial(self):
356 self.materials.append(m)
364 self.ik_list.append(ik)
368 self.morph_list.append(s)
370 def addBoneGroup(self):
372 self.bone_group_list.append(g)
374 def addBoneDisplay(self, b, g):
375 self.bone_display_list.append((b, g))
378 return '<PMDLoader version: %g, model: "%s", vertex: %d, face: %d, material: %d, bone: %d ik: %d, skin: %d>' % (
379 self.version, self.name, len(self.vertices), len(self.indices),
380 len(self.materials), len(self.bones), len(self.ik_list), len(self.morph_list))
382 def _check_position(self):
383 self.pos=self.io.tell()
385 def read(self, path):
386 size=os.path.getsize(path)
387 with open(path, "rb") as f:
388 return self.load(path, f, size)
390 def load(self, path, io, end):
392 self.pos=self.io.tell()
394 self._check_position()
396 if not self._loadHeader():
398 self._check_position()
400 if not self._loadVertex():
402 self._check_position()
404 if not self._loadFace():
406 self._check_position()
408 if not self._loadMaterial():
410 self._check_position()
412 if not self._loadBone():
414 self._check_position()
416 if not self._loadIK():
418 self._check_position()
420 if not self._loadSkin():
422 self._check_position()
424 if not self._loadSkinIndex():
426 self._check_position()
428 if not self._loadBoneName():
430 self._check_position()
432 if not self._loadBoneIndex():
434 self._check_position()
436 if not self._loadExtend():
437 print('fail to loadExtend')
441 if self.io.tell()!=self.end:
442 print("can not reach eof.")
443 print("current: %d, end: %d, remain: %d" % (
444 self.io.tell(), self.end, self.end-self.io.tell()))
447 for i, child in enumerate(self.bones):
448 if child.parent_index==0xFFFF:
450 self.no_parent_bones.append(child)
454 parent=self.bones[child.parent_index]
456 parent.children.append(child)
459 child.tail=self.bones[child.tail_index].pos
463 def write(self, path):
469 io.write(struct.pack("f", self.version))
470 io.write(struct.pack("20s", self.name))
471 io.write(struct.pack("256s", self.comment))
474 io.write(struct.pack("I", len(self.vertices)))
475 sVertex=struct.Struct("=8f2H2B") # 38byte
476 assert(sVertex.size==38)
477 for v in self.vertices:
479 v.pos[0], v.pos[1], v.pos[2],
480 v.normal[0], v.normal[1], v.normal[2],
482 v.bone0, v.bone1, v.weight0, v.edge_flag)
486 io.write(struct.pack("I", len(self.indices)))
487 io.write(struct.pack("=%dH" % len(self.indices), *self.indices))
490 io.write(struct.pack("I", len(self.materials)))
491 sMaterial=struct.Struct("=3fff3f3fBBI20s") # 70byte
492 assert(sMaterial.size==70)
493 for m in self.materials:
494 io.write(sMaterial.pack(
495 m.diffuse[0], m.diffuse[1], m.diffuse[2], m.diffuse[3],
497 m.specular[0], m.specular[1], m.specular[2],
498 m.ambient[0], m.ambient[1], m.ambient[2],
499 m.toon_index, m.flag,
505 io.write(struct.pack("H", len(self.bones)))
506 sBone=struct.Struct("=20sHHBH3f")
507 assert(sBone.size==39)
511 b.parent_index, b.tail_index, b.type, b.ik_index,
512 b.pos[0], b.pos[1], b.pos[2]))
515 io.write(struct.pack("H", len(self.ik_list)))
516 for ik in self.ik_list:
517 io.write(struct.pack("=2HBHf",
518 ik.index, ik.target, ik.length, ik.iterations, ik.weight
520 for c in ik.children:
521 io.write(struct.pack("H", c))
524 io.write(struct.pack("H", len(self.morph_list)))
525 for s in self.morph_list:
526 io.write(struct.pack("20sIB",
527 s.name, len(s.indices), s.type))
528 for i, v in zip(s.indices, s.pos_list):
529 io.write(struct.pack("I3f", i, v[0], v[1], v[2]))
532 io.write(struct.pack("B", len(self.face_list)))
533 for i in self.face_list:
534 io.write(struct.pack("H", i))
537 io.write(struct.pack("B", len(self.bone_group_list)))
538 for g in self.bone_group_list:
539 io.write(struct.pack("50s", g.name))
542 io.write(struct.pack("I", len(self.bone_display_list)))
543 for l in self.bone_display_list:
544 io.write(struct.pack("=HB", *l))
549 def _loadExtend(self):
550 ############################################################
551 # extend1: english name
552 ############################################################
553 if self.io.tell()>=self.end:
555 if struct.unpack("B", self.io.read(1))[0]==1:
556 if not self.loadEnglishName():
558 self._check_position()
560 ############################################################
561 # extend2: toon texture list
562 ############################################################
563 if self.io.tell()>=self.end:
565 if not self.loadToonTexture():
567 self._check_position()
569 ############################################################
571 ############################################################
572 if self.io.tell()>=self.end:
574 if not self.loadPhysics():
576 self._check_position()
580 def _loadHeader(self):
581 signature=struct.unpack("3s", self.io.read(3))[0]
582 if signature!=b"Pmd":
583 print("invalid signature", signature)
585 self.version=struct.unpack("f", self.io.read(4))[0]
586 self.name = truncate_zero(struct.unpack("20s", self.io.read(20))[0])
587 self.comment = truncate_zero(
588 struct.unpack("256s", self.io.read(256))[0])
591 def _loadVertex(self):
592 count = struct.unpack("I", self.io.read(4))[0]
593 for i in xrange(count):
594 self.vertices.append(Vertex(*struct.unpack("8f2H2B", self.io.read(38))))
598 count = struct.unpack("I", self.io.read(4))[0]
599 for i in xrange(0, count, 3):
600 self.indices+=struct.unpack("HHH", self.io.read(6))
603 def _loadMaterial(self):
604 count = struct.unpack("I", self.io.read(4))[0]
605 for i in xrange(count):
606 material=Material(*struct.unpack("4ff3f3f", self.io.read(44)))
607 material.toon_index=struct.unpack("B", self.io.read(1))[0]
608 material.flag=struct.unpack("B", self.io.read(1))[0]
609 material.vertex_count=struct.unpack("I", self.io.read(4))[0]
610 texture=truncate_zero(struct.unpack("20s", self.io.read(20))[0])
612 #material.texture=texture.split('*')[0]
613 material.texture=texture
614 self.materials.append(material)
618 size = struct.unpack("H", self.io.read(2))[0]
619 for i in xrange(size):
620 name=truncate_zero(struct.unpack("20s", self.io.read(20))[0])
621 parent_index, tail_index = struct.unpack("HH", self.io.read(4))
622 type = struct.unpack("B", self.io.read(1))[0]
623 bone=createBone(name, type)
624 bone.parent_index=parent_index
625 bone.tail_index=tail_index
626 bone.ik_index = struct.unpack("H", self.io.read(2))[0]
627 bone.pos = Vector3(*struct.unpack("3f", self.io.read(12)))
628 bone.english_name="bone%03d" % len(self.bones)
629 self.bones.append(bone)
633 size = struct.unpack("H", self.io.read(2))[0]
634 for i in xrange(size):
635 ik=IK(*struct.unpack("2H", self.io.read(4)))
636 ik.length = struct.unpack("B", self.io.read(1))[0]
637 ik.iterations = struct.unpack("H", self.io.read(2))[0]
638 ik.weight = struct.unpack("f", self.io.read(4))[0]
639 for j in xrange(ik.length):
640 ik.children.append(struct.unpack("H", self.io.read(2))[0])
641 self.ik_list.append(ik)
645 size = struct.unpack("H", self.io.read(2))[0]
646 for i in xrange(size):
647 skin=Skin(truncate_zero(struct.unpack("20s", self.io.read(20))[0]))
648 skin_size = struct.unpack("I", self.io.read(4))[0]
649 skin.type = struct.unpack("B", self.io.read(1))[0]
650 for j in xrange(skin_size):
651 skin.indices.append(struct.unpack("I", self.io.read(4))[0])
652 skin.pos_list.append(
653 Vector3(*struct.unpack("3f", self.io.read(12))))
654 skin.english_name="skin%03d" % len(self.morph_list)
655 self.morph_list.append(skin)
658 def _loadSkinIndex(self):
659 size = struct.unpack("B", self.io.read(1))[0]
660 for i in xrange(size):
661 self.face_list.append(struct.unpack("H", self.io.read(2))[0])
664 def _loadBoneName(self):
665 size = struct.unpack("B", self.io.read(1))[0]
666 for i in xrange(size):
667 self.bone_group_list.append(BoneGroup(
668 truncate_zero(struct.unpack("50s", self.io.read(50))[0])))
671 def _loadBoneIndex(self):
672 size = struct.unpack("I", self.io.read(4))[0]
673 for i in xrange(size):
674 first=struct.unpack("H", self.io.read(2))[0]
675 second=struct.unpack("B", self.io.read(1))[0]
676 self.bone_display_list.append((first, second))
679 def loadToonTexture(self):
684 self.toon_textures.append(
685 truncate_zero(struct.unpack("100s", self.io.read(100))[0]))
688 def loadEnglishName(self):
690 self.english_name=truncate_zero(
691 struct.unpack("20s", self.io.read(20))[0])
692 self.english_comment=truncate_zero(
693 struct.unpack("256s", self.io.read(256))[0])
694 self._check_position()
696 for bone in self.bones:
697 english_name=truncate_zero(
698 struct.unpack("20s", self.io.read(20))[0])
699 bone.english_name=english_name
700 self._check_position()
702 for skin in self.morph_list:
703 if skin.name=='base':
705 english_name=truncate_zero(
706 struct.unpack("20s", self.io.read(20))[0])
707 #skin=self.morph_list[index]
708 if english_name!=skin.name:
709 skin.english_name=english_name
710 self._check_position()
712 for i in xrange(0, len(self.bone_group_list)):
713 self.bone_group_list[i].english_name=truncate_zero(
714 struct.unpack("50s", self.io.read(50))[0])
715 self._check_position()
718 def loadPhysics(self):
720 count = struct.unpack("I", self.io.read(4))[0]
721 for i in xrange(count):
722 name=truncate_zero(struct.unpack("20s", self.io.read(20))[0])
723 rigidbody=RigidBody(name)
724 rigidbody.boneIndex=struct.unpack("H", self.io.read(2))[0]
725 rigidbody.group=struct.unpack("B", self.io.read(1))[0]
726 rigidbody.target=struct.unpack("H", self.io.read(2))[0]
727 rigidbody.shapeType=struct.unpack("B", self.io.read(1))[0]
728 rigidbody.w=struct.unpack("f", self.io.read(4))[0]
729 rigidbody.h=struct.unpack("f", self.io.read(4))[0]
730 rigidbody.d=struct.unpack("f", self.io.read(4))[0]
731 rigidbody.position.x=struct.unpack("f", self.io.read(4))[0]
732 rigidbody.position.y=struct.unpack("f", self.io.read(4))[0]
733 rigidbody.position.z=struct.unpack("f", self.io.read(4))[0]
734 rigidbody.rotation.x=struct.unpack("f", self.io.read(4))[0]
735 rigidbody.rotation.y=struct.unpack("f", self.io.read(4))[0]
736 rigidbody.rotation.z=struct.unpack("f", self.io.read(4))[0]
737 rigidbody.weight=struct.unpack("f", self.io.read(4))[0]
738 rigidbody.linearDamping=struct.unpack("f", self.io.read(4))[0]
739 rigidbody.angularDamping=struct.unpack("f", self.io.read(4))[0]
740 rigidbody.restitution=struct.unpack("f", self.io.read(4))[0]
741 rigidbody.friction=struct.unpack("f", self.io.read(4))[0]
742 rigidbody.processType=struct.unpack("B", self.io.read(1))[0]
743 self.rigidbodies.append(rigidbody)
744 self._check_position()
747 count = struct.unpack("I", self.io.read(4))[0]
748 for i in xrange(count):
749 name=truncate_zero(struct.unpack("20s", self.io.read(20))[0])
750 constraint=Constraint(name)
751 constraint.rigidA=struct.unpack("I", self.io.read(4))[0]
752 constraint.rigidB=struct.unpack("I", self.io.read(4))[0]
753 constraint.pos.x=struct.unpack("f", self.io.read(4))[0]
754 constraint.pos.y=struct.unpack("f", self.io.read(4))[0]
755 constraint.pos.z=struct.unpack("f", self.io.read(4))[0]
756 constraint.rot.x=struct.unpack("f", self.io.read(4))[0]
757 constraint.rot.y=struct.unpack("f", self.io.read(4))[0]
758 constraint.rot.z=struct.unpack("f", self.io.read(4))[0]
759 constraint.constraintPosMin.x=struct.unpack("f", self.io.read(4))[0]
760 constraint.constraintPosMin.y=struct.unpack("f", self.io.read(4))[0]
761 constraint.constraintPosMin.z=struct.unpack("f", self.io.read(4))[0]
762 constraint.constraintPosMax.x=struct.unpack("f", self.io.read(4))[0]
763 constraint.constraintPosMax.y=struct.unpack("f", self.io.read(4))[0]
764 constraint.constraintPosMax.z=struct.unpack("f", self.io.read(4))[0]
765 constraint.constraintRotMin.x=struct.unpack("f", self.io.read(4))[0]
766 constraint.constraintRotMin.y=struct.unpack("f", self.io.read(4))[0]
767 constraint.constraintRotMin.z=struct.unpack("f", self.io.read(4))[0]
768 constraint.constraintRotMax.x=struct.unpack("f", self.io.read(4))[0]
769 constraint.constraintRotMax.y=struct.unpack("f", self.io.read(4))[0]
770 constraint.constraintRotMax.z=struct.unpack("f", self.io.read(4))[0]
771 constraint.springPos.x=struct.unpack("f", self.io.read(4))[0]
772 constraint.springPos.y=struct.unpack("f", self.io.read(4))[0]
773 constraint.springPos.z=struct.unpack("f", self.io.read(4))[0]
774 constraint.springRot.x=struct.unpack("f", self.io.read(4))[0]
775 constraint.springRot.y=struct.unpack("f", self.io.read(4))[0]
776 constraint.springRot.z=struct.unpack("f", self.io.read(4))[0]
777 self.constraints.append(constraint)
778 self._check_position()