7 ###############################################################################
9 ###############################################################################
15 __slots__=['pos', 'normal', 'uv', 'bone0', 'bone1', 'weight0', 'edge_flag']
16 def __init__(self, x=0, y=0, z=0, nx=0, ny=0, nz=0, u=0, v=0,
17 bone0=0, bone1=0, weight0=0, edge_flag=0):
18 self.pos=Vector3(x, y, z)
19 self.normal=Vector3(nx, ny, nz)
24 self.edge_flag=edge_flag
27 return "<%s %s %s, (%d, %d, %d)>" % (str(self.pos), str(self.normal), str(self.uv), self.bone0, self.bone1, self.weight0)
29 def __getitem__(self, key):
40 class Material(object):
42 'diffuse', 'shinness', 'specular',
43 'ambient', 'vertex_count', '_texture', 'toon_index', 'flag',
45 def getTexture(self): return from_str(self._texture)
46 def setTexture(self, texture): self._texture=to_str(texture)
47 texture=property(getTexture, setTexture)
49 def __init__(self, dr=0, dg=0, db=0, alpha=1,
50 specular=0, sr=0, sg=0, sb=0, ar=0, ag=0, ab=0):
51 self.diffuse=RGBA(dr, dg, db, alpha)
52 self.specular=RGBA(sr, sg, sb)
53 self.shinness=specular
54 self.ambient=RGBA(ar, ag, ab)
61 return "<Material [%f, %f, %f, %f]>" % (
62 self.diffuse[0], self.diffuse[1],
63 self.diffuse[2], self.diffuse[3],
67 # @return 各マテリアルについて、そのマテリアルが保持する面の回数だけ
69 def material_per_face(materials):
71 for x in range(int(m.vertex_count/3)):
87 __slots__=['_name', 'index', 'type', 'parent', 'ik', 'pos',
88 'children', '_english_name', 'ik_index',
89 'parent_index', 'tail_index', 'tail',
91 def getName(self): return from_str(self._name)
92 def setName(self, name): self._name=to_str(name)
93 name=property(getName, setName)
94 def getEnglishName(self): return from_str(self._english_name)
95 def setEnglishName(self, english_name): self._english_name=to_str(english_name)
96 english_name=property(getEnglishName, setEnglishName)
98 def __init__(self, name='bone', type=0):
102 self.parent_index=0xFFFF
104 self.tail=Vector3(0, 0, 0)
107 self.pos=Vector3(0, 0, 0)
112 return self.parent_index!=0xFFFF
115 return self.tail_index!=0
117 def display(self, indent=[]):
120 for i, is_end in enumerate(indent):
124 prefix+=' ' if is_end else ' |'
125 uni='%s +%s(%s)' % (prefix, unicode(self), self.english_name)
126 print(uni.encode(ENCODING))
128 uni='%s(%s)' % (unicode(self), self.english_name)
129 print(uni.encode(ENCODING))
131 child_count=len(self.children)
132 for i in range(child_count):
133 child=self.children[i]
135 child.display(indent+[False])
138 child.display(indent+[True])
141 class Bone_Rotate(Bone):
143 def __init__(self, name):
144 super(Bone_Rotate, self).__init__(name, 0)
146 return '<ROTATE %s>' % (self.name)
148 class Bone_RotateMove(Bone):
150 def __init__(self, name):
151 super(Bone_RotateMove, self).__init__(name, 1)
153 return '<ROTATE_MOVE %s>' % (self.name)
157 def __init__(self, name):
158 super(Bone_IK, self).__init__(name, 2)
160 return '<IK %s>' % (self.name)
162 class Bone_IKRotateInfl(Bone):
164 def __init__(self, name):
165 super(Bone_IKRotateInfl, self).__init__(name, 4)
167 return '<IK_ROTATE_INFL %s>' % (self.name)
169 class Bone_RotateInfl(Bone):
171 def __init__(self, name):
172 super(Bone_RotateInfl, self).__init__(name, 5)
174 return '<ROTATE_INFL %s>' % (self.name)
176 class Bone_IKTarget(Bone):
178 def __init__(self, name):
179 super(Bone_IKTarget, self).__init__(name, 6)
181 return '<IK_TARGET %s>' % (self.name)
183 class Bone_Unvisible(Bone):
185 def __init__(self, name):
186 super(Bone_Unvisible, self).__init__(name, 7)
188 return '<UNVISIBLE %s>' % (self.name)
190 class Bone_Rolling(Bone):
192 def __init__(self, name):
193 super(Bone_Rolling, self).__init__(name, 8)
195 return '<ROLLING %s>' % (self.name)
197 class Bone_Tweak(Bone):
199 def __init__(self, name):
200 super(Bone_Tweak, self).__init__(name, 9)
202 return '<TWEAK %s>' % (self.name)
205 def createBone(name, type):
207 return Bone_Rotate(name)
209 return Bone_RotateMove(name)
213 raise Exception("no used bone type: 3(%s)" % name)
215 return Bone_IKRotateInfl(name)
217 return Bone_RotateInfl(name)
219 return Bone_IKTarget(name)
221 return Bone_Unvisible(name)
223 return Bone_Rolling(name)
225 return Bone_Tweak(name)
227 raise Exception("unknown bone type: %d(%s)", type, name)
231 __slots__=['index', 'target', 'iterations', 'weight', 'length', 'children']
232 def __init__(self, index=0, target=0):
240 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))
244 __slots__=['_name', 'type', 'indices', 'pos_list', '_english_name',
246 def getName(self): return from_str(self._name)
247 def setName(self, name): self._name=to_str(name)
248 name=property(getName, setName)
249 def getEnglishName(self): return from_str(self._english_name)
250 def setEnglishName(self, english_name): self._english_name=to_str(english_name)
251 english_name=property(getEnglishName, setEnglishName)
253 def __init__(self, name='skin'):
261 def append(self, index, x, y, z):
262 self.indices.append(index)
263 self.pos_list.append(Vector3(x, y, z))
266 return '<Skin name: "%s", type: %d, vertex: %d>' % (
267 self.name, self.type, len(self.indices))
270 class BoneGroup(object):
271 __slots__=['_name', '_english_name']
272 def getName(self): return from_str(self._name)
273 def setName(self, name): self._name=to_str(name)
274 name=property(getName, setName)
275 def getEnglishName(self): return from_str(self._english_name)
276 def setEnglishName(self, english_name): self._english_name=to_str(english_name)
277 english_name=property(getEnglishName, setEnglishName)
279 def __init__(self, name='group'): self._name=name; self._english_name='center'
286 RIGIDBODY_KINEMATICS=0
288 RIGIDBODY_PHYSICS_WITH_BONE=2
291 class RigidBody(object):
292 __slots__=['_name', 'boneIndex', 'group', 'target', 'shapeType',
293 'w', 'h', 'd', 'position', 'rotation', 'weight',
294 'linearDamping', 'angularDamping', 'restitution', 'friction', 'processType'
296 def getName(self): return from_str(self._name)
297 def setName(self, name): self._name=to_str(name)
298 name=property(getName, setName)
300 def __init__(self, name):
302 self.position=Vector3()
303 self.rotation=Vector3()
306 class Constraint(object):
307 __slots__=[ '_name', 'rigidA', 'rigidB', 'pos', 'rot',
308 'constraintPosMin', 'constraintPosMax',
309 'constraintRotMin', 'constraintRotMax',
310 'springPos', 'springRot',
312 def getName(self): return from_str(self._name)
313 def setName(self, name): self._name=to_str(name)
314 name=property(getName, setName)
316 def __init__(self, name):
320 self.constraintPosMin=Vector3()
321 self.constraintPosMax=Vector3()
322 self.constraintRotMin=Vector3()
323 self.constraintRotMax=Vector3()
324 self.springPos=Vector3()
325 self.springRot=Vector3()
328 class ToonTextures(object):
329 __slots__=['_toon_textures']
331 self._toon_textures=[]
333 self._toon_textures.append('toon%02d.bmp' % (i+1))
335 def __getitem__(self, key):
336 return from_str(self._toon_textures[key])
338 def __setitem__(self, key, value):
339 self._toon_textures[key]=to_str(value)
342 for toon_texture in self._toon_textures:
343 yield from_str(toon_texture)
347 __slots__=['io', 'end', 'pos',
348 'version', '_name', '_comment',
349 '_english_name', '_english_comment',
350 'vertices', 'indices', 'materials', 'bones',
351 'ik_list', 'morph_list',
352 'face_list', 'bone_group_list', 'bone_display_list',
355 'rigidbodies', 'constraints',
357 def getName(self): return from_str(self._name)
358 def setName(self, name): self._name=to_str(name)
359 name=property(getName, setName)
360 def getEnglishName(self): return from_str(self._english_name)
361 def setEnglishName(self, english_name): self._english_name=to_str(english_name)
362 english_name=property(getEnglishName, setEnglishName)
363 def getComment(self): return from_str(self._comment)
364 def setComment(self, comment): self._comment=to_str(comment)
365 comment=property(getComment, setComment)
366 def getEnglishComment(self): return from_str(self._english_comment)
367 def setEnglishComment(self, english_comment): self._english_comment=to_str(english_comment)
368 english_comment=property(getEnglishComment, setEnglishComment)
375 self.english_comment=''
383 self.bone_group_list=[]
384 self.bone_display_list=[]
386 self.toon_textures=ToonTextures()
390 self.no_parent_bones=[]
392 def each_vertex(self): return self.vertices
393 def getUV(self, i): return self.vertices[i].uv
396 self.vertices.append(v)
398 def addMaterial(self):
400 self.materials.append(m)
408 self.ik_list.append(ik)
412 self.morph_list.append(s)
414 def addBoneGroup(self):
416 self.bone_group_list.append(g)
418 def addBoneDisplay(self, b, g):
419 self.bone_display_list.append((b, g))
422 return '<PMDLoader version: %g, model: "%s", vertex: %d, face: %d, material: %d, bone: %d ik: %d, skin: %d>' % (
423 self.version, self.name, len(self.vertices), len(self.indices),
424 len(self.materials), len(self.bones), len(self.ik_list), len(self.morph_list))
426 def _check_position(self):
427 self.pos=self.io.tell()
429 def read(self, path):
430 size=os.path.getsize(path)
431 with open(path, "rb") as f:
432 return self.load(path, f, size)
434 def load(self, path, io, end):
436 self.pos=self.io.tell()
438 self._check_position()
440 if not self._loadHeader():
442 self._check_position()
444 if not self._loadVertex():
446 self._check_position()
448 if not self._loadFace():
450 self._check_position()
452 if not self._loadMaterial():
454 self._check_position()
456 if not self._loadBone():
458 self._check_position()
460 if not self._loadIK():
462 self._check_position()
464 if not self._loadSkin():
466 self._check_position()
468 if not self._loadSkinIndex():
470 self._check_position()
472 if not self._loadBoneName():
474 self._check_position()
476 if not self._loadBoneIndex():
478 self._check_position()
480 if not self._loadExtend():
481 print('fail to loadExtend')
485 if self.io.tell()!=self.end:
486 print("can not reach eof.")
487 print("current: %d, end: %d, remain: %d" % (
488 self.io.tell(), self.end, self.end-self.io.tell()))
491 for i, child in enumerate(self.bones):
492 if child.parent_index==0xFFFF:
494 self.no_parent_bones.append(child)
498 parent=self.bones[child.parent_index]
500 parent.children.append(child)
503 child.tail=self.bones[child.tail_index].pos
507 def write(self, path):
513 io.write(struct.pack("f", self.version))
514 io.write(struct.pack("20s", self.name))
515 io.write(struct.pack("256s", self.comment))
518 io.write(struct.pack("I", len(self.vertices)))
519 sVertex=struct.Struct("=8f2H2B") # 38byte
520 assert(sVertex.size==38)
521 for v in self.vertices:
523 v.pos[0], v.pos[1], v.pos[2],
524 v.normal[0], v.normal[1], v.normal[2],
526 v.bone0, v.bone1, v.weight0, v.edge_flag)
530 io.write(struct.pack("I", len(self.indices)))
531 io.write(struct.pack("=%dH" % len(self.indices), *self.indices))
534 io.write(struct.pack("I", len(self.materials)))
535 sMaterial=struct.Struct("=3fff3f3fBBI20s") # 70byte
536 assert(sMaterial.size==70)
537 for m in self.materials:
538 io.write(sMaterial.pack(
539 m.diffuse[0], m.diffuse[1], m.diffuse[2], m.diffuse[3],
541 m.specular[0], m.specular[1], m.specular[2],
542 m.ambient[0], m.ambient[1], m.ambient[2],
543 m.toon_index, m.flag,
549 io.write(struct.pack("H", len(self.bones)))
550 sBone=struct.Struct("=20sHHBH3f")
551 assert(sBone.size==39)
555 b.parent_index, b.tail_index, b.type, b.ik_index,
556 b.pos[0], b.pos[1], b.pos[2]))
559 io.write(struct.pack("H", len(self.ik_list)))
560 for ik in self.ik_list:
561 io.write(struct.pack("=2HBHf",
562 ik.index, ik.target, ik.length, ik.iterations, ik.weight
564 for c in ik.children:
565 io.write(struct.pack("H", c))
568 io.write(struct.pack("H", len(self.morph_list)))
569 for s in self.morph_list:
570 io.write(struct.pack("20sIB",
571 s.name, len(s.indices), s.type))
572 for i, v in zip(s.indices, s.pos_list):
573 io.write(struct.pack("I3f", i, v[0], v[1], v[2]))
576 io.write(struct.pack("B", len(self.face_list)))
577 for i in self.face_list:
578 io.write(struct.pack("H", i))
581 io.write(struct.pack("B", len(self.bone_group_list)))
582 for g in self.bone_group_list:
583 io.write(struct.pack("50s", g.name))
585 io.write(struct.pack("I", len(self.bone_display_list)))
586 for l in self.bone_display_list:
587 io.write(struct.pack("=HB", *l))
589 ############################################################
591 ############################################################
592 io.write(struct.pack("B", 1))
594 io.write(struct.pack("=20s", self.english_name))
595 io.write(struct.pack("=256s", self.english_comment))
597 for bone in self.bones:
598 io.write(struct.pack("=20s", bone.english_name))
600 for skin in self.morph_list:
602 if skin.name==b'base':
604 io.write(struct.pack("=20s", skin.english_name))
606 for bone_group in self.bone_group_list:
607 io.write(struct.pack("50s", bone_group.english_name))
609 for toon_texture in self.toon_textures:
610 io.write(struct.pack("=100s", toon_texture))
612 io.write(struct.pack("I", len(self.rigidbodies)))
613 for r in self.rigidbodies:
614 io.write(struct.pack("=20sHBHB14fB",
615 r.name, r.boneIndex, r.group, r.target, r.shapeType,
617 r.position.x, r.position.y, r.position.z,
618 r.rotation.x, r.rotation.y, r.rotation.z,
620 r.linearDamping, r.angularDamping, r.restitution,
621 r.friction, r.processType))
624 io.write(struct.pack("I", len(self.constraints)))
625 for c in self.constraints:
626 io.write(struct.pack("=20sII24f",
627 c.name, c.rigidA, c.rigidB,
628 c.pos.x, c.pos.y, c.pos.z,
629 c.rot.x, c.rot.y, c.rot.z,
630 c.constraintPosMin.x, c.constraintPosMin.y, c.constraintPosMin.z,
631 c.constraintPosMax.x, c.constraintPosMax.y, c.constraintPosMax.z,
632 c.constraintRotMin.x, c.constraintRotMin.y, c.constraintRotMin.z,
633 c.constraintRotMax.x, c.constraintRotMax.y, c.constraintRotMax.z,
634 c.springPos.x, c.springPos.y, c.springPos.z,
635 c.springRot.x, c.springRot.y, c.springRot.z
641 def _loadExtend(self):
642 ############################################################
643 # extend1: english name
644 ############################################################
645 if self.io.tell()>=self.end:
647 if struct.unpack("B", self.io.read(1))[0]==1:
648 if not self.loadEnglishName():
650 self._check_position()
652 ############################################################
653 # extend2: toon texture list
654 ############################################################
655 if self.io.tell()>=self.end:
657 if not self.loadToonTexture():
659 self._check_position()
661 ############################################################
663 ############################################################
664 if self.io.tell()>=self.end:
666 if not self.loadPhysics():
668 self._check_position()
672 def _loadHeader(self):
673 signature=struct.unpack("3s", self.io.read(3))[0]
674 if signature!=b"Pmd":
675 print("invalid signature", signature)
677 self.version=struct.unpack("f", self.io.read(4))[0]
678 self.name = truncate_zero(struct.unpack("20s", self.io.read(20))[0])
679 self.comment = truncate_zero(
680 struct.unpack("256s", self.io.read(256))[0])
683 def _loadVertex(self):
684 count = struct.unpack("I", self.io.read(4))[0]
685 for i in range(count):
686 self.vertices.append(Vertex(*struct.unpack("8f2H2B", self.io.read(38))))
690 count = struct.unpack("I", self.io.read(4))[0]
691 for i in range(0, count, 3):
692 self.indices+=struct.unpack("HHH", self.io.read(6))
695 def _loadMaterial(self):
696 count = struct.unpack("I", self.io.read(4))[0]
697 for i in range(count):
698 material=Material(*struct.unpack("4ff3f3f", self.io.read(44)))
699 material.toon_index=struct.unpack("B", self.io.read(1))[0]
700 material.flag=struct.unpack("B", self.io.read(1))[0]
701 material.vertex_count=struct.unpack("I", self.io.read(4))[0]
702 texture=truncate_zero(struct.unpack("20s", self.io.read(20))[0])
704 #material.texture=texture.split('*')[0]
705 material.texture=texture
706 self.materials.append(material)
710 size = struct.unpack("H", self.io.read(2))[0]
711 for i in range(size):
712 name=truncate_zero(struct.unpack("20s", self.io.read(20))[0])
713 parent_index, tail_index = struct.unpack("HH", self.io.read(4))
714 type = struct.unpack("B", self.io.read(1))[0]
715 bone=createBone(name, type)
716 bone.parent_index=parent_index
717 bone.tail_index=tail_index
718 bone.ik_index = struct.unpack("H", self.io.read(2))[0]
719 bone.pos = Vector3(*struct.unpack("3f", self.io.read(12)))
720 bone.english_name="bone%03d" % len(self.bones)
721 self.bones.append(bone)
725 size = struct.unpack("H", self.io.read(2))[0]
726 for i in range(size):
727 ik=IK(*struct.unpack("2H", self.io.read(4)))
728 ik.length = struct.unpack("B", self.io.read(1))[0]
729 ik.iterations = struct.unpack("H", self.io.read(2))[0]
730 ik.weight = struct.unpack("f", self.io.read(4))[0]
731 for j in range(ik.length):
732 ik.children.append(struct.unpack("H", self.io.read(2))[0])
733 self.ik_list.append(ik)
737 size = struct.unpack("H", self.io.read(2))[0]
738 for i in range(size):
739 skin=Skin(truncate_zero(struct.unpack("20s", self.io.read(20))[0]))
740 skin_size = struct.unpack("I", self.io.read(4))[0]
741 skin.type = struct.unpack("B", self.io.read(1))[0]
742 for j in range(skin_size):
743 skin.indices.append(struct.unpack("I", self.io.read(4))[0])
744 skin.pos_list.append(
745 Vector3(*struct.unpack("3f", self.io.read(12))))
746 skin.english_name="skin%03d" % len(self.morph_list)
747 self.morph_list.append(skin)
750 def _loadSkinIndex(self):
751 size = struct.unpack("B", self.io.read(1))[0]
752 for i in range(size):
753 self.face_list.append(struct.unpack("H", self.io.read(2))[0])
756 def _loadBoneName(self):
757 size = struct.unpack("B", self.io.read(1))[0]
758 for i in range(size):
759 self.bone_group_list.append(BoneGroup(
760 truncate_zero(struct.unpack("50s", self.io.read(50))[0])))
763 def _loadBoneIndex(self):
764 size = struct.unpack("I", self.io.read(4))[0]
765 for i in range(size):
766 first=struct.unpack("H", self.io.read(2))[0]
767 second=struct.unpack("B", self.io.read(1))[0]
768 self.bone_display_list.append((first, second))
771 def loadToonTexture(self):
776 self.toon_textures[i]=truncate_zero(struct.unpack("100s", self.io.read(100))[0])
779 def loadEnglishName(self):
781 self.english_name=truncate_zero(
782 struct.unpack("20s", self.io.read(20))[0])
783 self.english_comment=truncate_zero(
784 struct.unpack("256s", self.io.read(256))[0])
785 self._check_position()
787 for bone in self.bones:
788 english_name=truncate_zero(
789 struct.unpack("20s", self.io.read(20))[0])
790 bone.english_name=english_name
791 self._check_position()
793 for skin in self.morph_list:
794 if skin.name==b'base':
796 english_name=truncate_zero(
797 struct.unpack("20s", self.io.read(20))[0])
798 #skin=self.morph_list[index]
799 if english_name!=skin.name:
800 skin.english_name=english_name
801 self._check_position()
803 for i in range(0, len(self.bone_group_list)):
804 self.bone_group_list[i].english_name=truncate_zero(
805 struct.unpack("50s", self.io.read(50))[0])
806 self._check_position()
809 def loadPhysics(self):
811 count = struct.unpack("I", self.io.read(4))[0]
812 for i in range(count):
813 name=truncate_zero(struct.unpack("20s", self.io.read(20))[0])
814 rigidbody=RigidBody(name)
815 rigidbody.boneIndex=struct.unpack("H", self.io.read(2))[0]
816 rigidbody.group=struct.unpack("B", self.io.read(1))[0]
817 rigidbody.target=struct.unpack("H", self.io.read(2))[0]
818 rigidbody.shapeType=struct.unpack("B", self.io.read(1))[0]
819 rigidbody.w=struct.unpack("f", self.io.read(4))[0]
820 rigidbody.h=struct.unpack("f", self.io.read(4))[0]
821 rigidbody.d=struct.unpack("f", self.io.read(4))[0]
822 rigidbody.position.x=struct.unpack("f", self.io.read(4))[0]
823 rigidbody.position.y=struct.unpack("f", self.io.read(4))[0]
824 rigidbody.position.z=struct.unpack("f", self.io.read(4))[0]
825 rigidbody.rotation.x=struct.unpack("f", self.io.read(4))[0]
826 rigidbody.rotation.y=struct.unpack("f", self.io.read(4))[0]
827 rigidbody.rotation.z=struct.unpack("f", self.io.read(4))[0]
828 rigidbody.weight=struct.unpack("f", self.io.read(4))[0]
829 rigidbody.linearDamping=struct.unpack("f", self.io.read(4))[0]
830 rigidbody.angularDamping=struct.unpack("f", self.io.read(4))[0]
831 rigidbody.restitution=struct.unpack("f", self.io.read(4))[0]
832 rigidbody.friction=struct.unpack("f", self.io.read(4))[0]
833 rigidbody.processType=struct.unpack("B", self.io.read(1))[0]
834 self.rigidbodies.append(rigidbody)
835 self._check_position()
838 count = struct.unpack("I", self.io.read(4))[0]
839 for i in range(count):
840 name=truncate_zero(struct.unpack("20s", self.io.read(20))[0])
841 constraint=Constraint(name)
842 constraint.rigidA=struct.unpack("I", self.io.read(4))[0]
843 constraint.rigidB=struct.unpack("I", self.io.read(4))[0]
844 constraint.pos.x=struct.unpack("f", self.io.read(4))[0]
845 constraint.pos.y=struct.unpack("f", self.io.read(4))[0]
846 constraint.pos.z=struct.unpack("f", self.io.read(4))[0]
847 constraint.rot.x=struct.unpack("f", self.io.read(4))[0]
848 constraint.rot.y=struct.unpack("f", self.io.read(4))[0]
849 constraint.rot.z=struct.unpack("f", self.io.read(4))[0]
850 constraint.constraintPosMin.x=struct.unpack("f", self.io.read(4))[0]
851 constraint.constraintPosMin.y=struct.unpack("f", self.io.read(4))[0]
852 constraint.constraintPosMin.z=struct.unpack("f", self.io.read(4))[0]
853 constraint.constraintPosMax.x=struct.unpack("f", self.io.read(4))[0]
854 constraint.constraintPosMax.y=struct.unpack("f", self.io.read(4))[0]
855 constraint.constraintPosMax.z=struct.unpack("f", self.io.read(4))[0]
856 constraint.constraintRotMin.x=struct.unpack("f", self.io.read(4))[0]
857 constraint.constraintRotMin.y=struct.unpack("f", self.io.read(4))[0]
858 constraint.constraintRotMin.z=struct.unpack("f", self.io.read(4))[0]
859 constraint.constraintRotMax.x=struct.unpack("f", self.io.read(4))[0]
860 constraint.constraintRotMax.y=struct.unpack("f", self.io.read(4))[0]
861 constraint.constraintRotMax.z=struct.unpack("f", self.io.read(4))[0]
862 constraint.springPos.x=struct.unpack("f", self.io.read(4))[0]
863 constraint.springPos.y=struct.unpack("f", self.io.read(4))[0]
864 constraint.springPos.z=struct.unpack("f", self.io.read(4))[0]
865 constraint.springRot.x=struct.unpack("f", self.io.read(4))[0]
866 constraint.springRot.y=struct.unpack("f", self.io.read(4))[0]
867 constraint.springRot.z=struct.unpack("f", self.io.read(4))[0]
868 self.constraints.append(constraint)
869 self._check_position()