1 #!/usr/bin/env python
\r
4 ========================
\r
5 MikuMikuDance PMX format
\r
6 ========================
\r
10 * PMDEditor's Lib/PMX仕様/PMX仕様.txt
\r
14 * textencoding: unicode
\r
15 * coordinate: left handed y-up(DirectX)
\r
17 * face: only triangle
\r
21 __author__="ousttrue"
\r
23 __versioon__="1.0.0"
\r
29 from pymeshio import common
\r
33 class DifferenceException(Exception):
\r
38 def _diff(self, rhs, key):
\r
39 l=getattr(self, key)
\r
44 raise DifferenceException(key)
\r
46 def _diff_array(self, rhs, key):
\r
47 la=getattr(self, key)
\r
48 ra=getattr(rhs, key)
\r
49 if len(la)!=len(ra):
\r
50 raise DifferenceException("%s diffrence %d with %d" % (key, len(la), len(ra)))
\r
51 for i, (l, r) in enumerate(zip(la, ra)):
\r
52 if isinstance(l, Diff):
\r
55 except DifferenceException as e:
\r
59 raise DifferenceException("{0}: {1}".format(key, e.message))
\r
65 raise DifferenceException("{0}".format(key))
\r
77 def __init__(self, target_index, loop, limit_radian, link=[]):
\r
78 self.target_index=target_index
\r
80 self.limit_radian=limit_radian
\r
83 def __eq__(self, rhs):
\r
85 self.target_index==rhs.target_index
\r
86 and self.loop==rhs.loop
\r
87 and self.limit_radian==rhs.limit_radian
\r
88 and self.link==rhs.link
\r
91 def diff(self, rhs):
\r
92 self._diff(rhs, 'target_index')
\r
93 self._diff(rhs, 'loop')
\r
94 self._diff(rhs, 'limit_radian')
\r
95 self._diff_array(rhs, 'link')
\r
107 def __init__(self, bone_index, limit_angle, limit_min=common.Vector3(), limit_max=common.Vector3()):
\r
108 self.bone_index=bone_index
\r
109 self.limit_angle=limit_angle
\r
110 self.limit_min=limit_min
\r
111 self.limit_max=limit_max
\r
113 def __eq__(self, rhs):
\r
115 self.bone_index==rhs.bone_index
\r
116 and self.limit_angle==rhs.limit_angle
\r
117 and self.limit_min==rhs.limit_min
\r
118 and self.limit_max==rhs.limit_max
\r
121 def diff(self, rhs):
\r
122 self._diff(rhs, 'bone_index')
\r
123 self._diff(rhs, 'limit_angle')
\r
124 self._diff(rhs, 'limit_min')
\r
125 self._diff(rhs, 'limit_max')
\r
158 tail_position=common.Vector3(),
\r
162 fixed_axis=common.Vector3(),
\r
163 local_x_vector=common.Vector3(),
\r
164 local_z_vector=common.Vector3(),
\r
169 self.english_name=english_name
\r
170 self.position=position
\r
171 self.parent_index=parent_index
\r
174 self.tail_position=tail_position
\r
175 self.tail_index=tail_index
\r
176 self.effect_index=effect_index
\r
177 self.effect_factor=effect_factor
\r
178 self.fixed_axis=fixed_axis
\r
179 self.local_x_vector=local_x_vector
\r
180 self.local_z_vector=local_z_vector
\r
181 self.external_key=external_key
\r
184 def __eq__(self, rhs):
\r
186 self.name==rhs.name
\r
187 and self.english_name==rhs.english_name
\r
188 and self.position==rhs.position
\r
189 and self.parent_index==rhs.parent_index
\r
190 and self.layer==rhs.layer
\r
191 and self.flag==rhs.flag
\r
194 def __ne__(self, rhs):
\r
195 return not self.__eq__(rhs)
\r
197 def diff(self, rhs):
\r
198 self._diff(rhs, 'name')
\r
199 self._diff(rhs, 'english_name')
\r
200 self._diff(rhs, 'position')
\r
201 self._diff(rhs, 'parent_index')
\r
202 #self._diff(rhs, 'layer')
\r
203 self._diff(rhs, 'flag')
\r
204 self._diff(rhs, 'tail_position')
\r
205 self._diff(rhs, 'tail_index')
\r
206 #self._diff(rhs, 'effect_index')
\r
207 #self._diff(rhs, 'effect_factor')
\r
208 #self._diff(rhs, 'fixed_axis')
\r
209 self._diff(rhs, 'local_x_vector')
\r
210 self._diff(rhs, 'local_z_vector')
\r
211 self._diff(rhs, 'external_key')
\r
212 if self.ik and rhs.ik:
\r
213 self.ik.diff(rhs.ik)
\r
215 self._diff(rhs, 'ik')
\r
217 def getConnectionFlag(self):
\r
218 return self.flag & 0x0001
\r
220 def getIkFlag(self):
\r
221 return (self.flag & 0x0020) >> 5
\r
223 def getRotationFlag(self):
\r
224 return (self.flag & 0x0100) >> 8
\r
226 def getTranslationFlag(self):
\r
227 return (self.flag & 0x0200) >> 9
\r
229 def getFixedAxisFlag(self):
\r
230 return (self.flag & 0x0400) >> 10
\r
232 def getLocalCoordinateFlag(self):
\r
233 return (self.flag & 0x0800) >> 11
\r
235 def getExternalParentDeformFlag(self):
\r
236 return (self.flag & 0x2000) >> 13
\r
239 class Material(Diff):
\r
242 Attributes: see __init__
\r
256 'sphere_texture_index',
\r
258 'toon_sharing_flag',
\r
259 'toon_texture_index',
\r
275 sphere_texture_index,
\r
278 toon_texture_index=0,
\r
279 comment=common.unicode(""),
\r
283 self.english_name=english_name
\r
284 self.diffuse_color=diffuse_color
\r
286 self.specular_color=specular_color
\r
287 self.specular_factor=specular_factor
\r
288 self.ambient_color=ambient_color
\r
290 self.edge_color=edge_color
\r
291 self.edge_size=edge_size
\r
292 self.texture_index=texture_index
\r
293 self.sphere_texture_index=sphere_texture_index
\r
294 self.sphere_mode=sphere_mode
\r
295 self.toon_sharing_flag=toon_sharing_flag
\r
296 self.toon_texture_index=toon_texture_index
\r
297 self.comment=comment
\r
298 self.vertex_count=vertex_count
\r
300 def __eq__(self, rhs):
\r
302 self.name==rhs.name
\r
303 and self.english_name==rhs.english_name
\r
304 and self.diffuse_color==rhs.diffuse_color
\r
305 and self.alpha==rhs.alpha
\r
306 and self.specular_color==rhs.specular_color
\r
307 and self.specular_factor==rhs.specular_factor
\r
308 and self.ambient_color==rhs.ambient_color
\r
309 and self.flag==rhs.flag
\r
310 and self.edge_color==rhs.edge_color
\r
311 and self.edge_size==rhs.edge_size
\r
312 and self.texture_index==rhs.texture_index
\r
313 and self.sphere_texture_index==rhs.sphere_texture_index
\r
314 and self.sphere_mode==rhs.sphere_mode
\r
315 and self.toon_sharing_flag==rhs.toon_sharing_flag
\r
316 and self.toon_texture_index==rhs.toon_texture_index
\r
317 and self.comment==rhs.comment
\r
318 and self.vertex_count==rhs.vertex_count
\r
321 def diff(self, rhs):
\r
322 #self._diff(rhs, "name")
\r
323 self._diff(rhs, "english_name")
\r
324 self._diff(rhs, "diffuse_color")
\r
325 self._diff(rhs, "alpha")
\r
326 self._diff(rhs, "specular_color")
\r
327 self._diff(rhs, "specular_factor")
\r
328 self._diff(rhs, "ambient_color")
\r
329 self._diff(rhs, "flag")
\r
330 self._diff(rhs, "edge_color")
\r
331 self._diff(rhs, "edge_size")
\r
332 self._diff(rhs, "texture_index")
\r
333 self._diff(rhs, "sphere_texture_index")
\r
334 self._diff(rhs, "sphere_mode")
\r
335 self._diff(rhs, "toon_sharing_flag")
\r
336 self._diff(rhs, "toon_texture_index")
\r
337 self._diff(rhs, "comment")
\r
338 self._diff(rhs, "vertex_count")
\r
340 def __ne__(self, rhs):
\r
341 return not self.__eq__(rhs)
\r
344 return ("<pmx.Material {name}>".format(
\r
345 name=self.english_name
\r
350 """bone deform. use a weight
\r
352 Attributes: see __init__
\r
354 __slots__=[ 'index0']
\r
355 def __init__(self, index0):
\r
359 return "<Bdef1 {0}>".format(self.index0)
\r
361 def __eq__(self, rhs):
\r
362 return self.index0==rhs.index0
\r
364 def __ne__(self, rhs):
\r
365 return not self.__eq__(rhs)
\r
369 """bone deform. use two weights
\r
371 Attributes: see __init__
\r
373 __slots__=[ 'index0', 'index1', 'weight0']
\r
374 def __init__(self,
\r
380 self.weight0=weight0
\r
383 return "<Bdef2 {0}, {1}, {2}>".format(self.index0, self.index1, self.weight0)
\r
385 def __eq__(self, rhs):
\r
387 self.index0==rhs.index0
\r
388 and self.index1==rhs.index1
\r
389 #and self.weight0==rhs.weight0
\r
390 and abs(self.weight0-rhs.weight0)<1e-5
\r
393 def __ne__(self, rhs):
\r
394 return not self.__eq__(rhs)
\r
397 class Vertex(Diff):
\r
411 Bdef1, Bdef2 or Bdef4
\r
415 __slots__=[ 'position', 'normal', 'uv', 'deform', 'edge_factor' ]
\r
416 def __init__(self,
\r
422 self.position=position
\r
426 self.edge_factor=edge_factor
\r
429 return "<Vertex position:{0}, normal:{1}, uv:{2}, deform:{3}, edge:{4}".format(
\r
430 self.position, self.normal, self.uv, self.deform, self.edge_factor
\r
433 def __eq__(self, rhs):
\r
435 self.position==rhs.position
\r
436 and self.normal==rhs.normal
\r
437 and self.uv==rhs.uv
\r
438 and self.deform==rhs.deform
\r
439 and self.edge_factor==rhs.edge_factor
\r
442 def __ne__(self, rhs):
\r
443 return not self.__eq__(rhs)
\r
445 def diff(self, rhs):
\r
446 self._diff(rhs, "position")
\r
447 self._diff(rhs, "normal")
\r
448 self._diff(rhs, "uv")
\r
449 self._diff(rhs, "deform")
\r
450 self._diff(rhs, "edge_factor")
\r
470 def __init__(self, name, english_name, panel, morph_type, offsets=[]):
\r
472 self.english_name=english_name
\r
474 self.morph_type=morph_type
\r
475 self.offsets=offsets
\r
477 def __eq__(self, rhs):
\r
479 self.name==rhs.name
\r
480 and self.english_name==rhs.english_name
\r
481 and self.panel==rhs.panel
\r
482 and self.morph_type==rhs.morph_type
\r
483 and self.offsets==rhs.offsets
\r
486 def __ne__(self, rhs):
\r
487 return not self.__eq__(rhs)
\r
489 def diff(self, rhs):
\r
490 self._diff(rhs, 'name')
\r
491 self._diff(rhs, 'english_name')
\r
492 #self._diff(rhs, 'panel')
\r
493 self._diff(rhs, 'morph_type')
\r
494 self._diff_array(rhs, 'offsets')
\r
497 class VerexMorphOffset(Diff):
\r
498 """pmx vertex morph offset
\r
502 position_offset: Vector3
\r
508 def __init__(self, vertex_index, position_offset):
\r
509 self.vertex_index=vertex_index
\r
510 self.position_offset=position_offset
\r
512 def __eq__(self, rhs):
\r
514 self.vertex_index==rhs.vertex_index
\r
515 and self.position_offset==rhs.position_offset
\r
518 def __ne__(self, rhs):
\r
519 return not self.__eq__(rhs)
\r
521 def diff(self, rhs):
\r
522 self._diff(rhs, 'vertex_index')
\r
523 self._diff(rhs, 'position_offset')
\r
526 class DisplaySlot(Diff):
\r
527 """pmx display slot
\r
533 refrences: list of (ref_type, ref_index)
\r
541 def __init__(self, name, english_name, special_flag, refrences=[]):
\r
543 self.english_name=english_name
\r
544 self.special_flag=special_flag
\r
545 self.refrences=refrences
\r
547 def __eq__(self, rhs):
\r
549 self.name==rhs.name
\r
550 and self.english_name==rhs.english_name
\r
551 and self.special_flag==rhs.special_flag
\r
552 and self.refrences==rhs.refrences
\r
555 def __ne__(self, rhs):
\r
556 return not self.__eq__(rhs)
\r
558 def diff(self, rhs):
\r
559 self._diff(rhs, 'name')
\r
560 self._diff(rhs, 'english_name')
\r
561 self._diff(rhs, 'special_flag')
\r
562 #self._diff_array(rhs, 'refrences')
\r
565 class RigidBodyParam(Diff):
\r
566 """pmx rigidbody param(for bullet)
\r
582 def __init__(self, mass,
\r
583 linear_damping, angular_damping, restitution, friction):
\r
585 self.linear_damping=linear_damping
\r
586 self.angular_damping=angular_damping
\r
587 self.restitution=restitution
\r
588 self.friction=friction
\r
590 def __eq__(self, rhs):
\r
592 self.mass==rhs.mass
\r
593 and self.linear_damping==rhs.linear_damping
\r
594 and self.angular_damping==rhs.angular_damping
\r
595 and self.restitution==rhs.restitution
\r
596 and self.friction==rhs.friction
\r
599 def __ne__(self, rhs):
\r
600 return not self.__eq__(rhs)
\r
602 def diff(self, rhs):
\r
603 self._diff(rhs, 'mass')
\r
604 self._diff(rhs, 'linear_damping')
\r
605 self._diff(rhs, 'angular_damping')
\r
606 self._diff_array(rhs, 'restitution')
\r
607 self._diff_array(rhs, 'friction')
\r
610 class RigidBody(Diff):
\r
618 no_collision_group:
\r
628 'no_collision_group',
\r
641 no_collision_group,
\r
654 self.english_name=english_name
\r
655 self.bone_index=bone_index
\r
656 self.collision_group=collision_group
\r
657 self.no_collision_group=no_collision_group
\r
658 self.shape_type=shape_type
\r
659 self.shape_size=shape_size
\r
660 self.shape_position=shape_position
\r
661 self.shape_rotation=shape_rotation
\r
662 self.param=RigidBodyParam(mass,
\r
663 linear_damping, angular_damping,
\r
664 restitution, friction)
\r
667 def __eq__(self, rhs):
\r
669 self.name==rhs.name
\r
670 and self.english_name==rhs.english_name
\r
671 and self.bone_index==rhs.bone_index
\r
672 and self.collision_group==rhs.collision_group
\r
673 and self.no_collision_group==rhs.no_collision_group
\r
674 and self.shape_type==rhs.shape_type
\r
675 and self.shape_size==rhs.shape_size
\r
676 and self.param==rhs.param
\r
677 and self.mode==rhs.mode
\r
680 def __ne__(self, rhs):
\r
681 return not self.__eq__(rhs)
\r
683 def diff(self, rhs):
\r
684 self._diff(rhs, 'name')
\r
685 self._diff(rhs, 'english_name')
\r
686 self._diff(rhs, 'bone_index')
\r
687 self._diff(rhs, 'collision_group')
\r
688 self._diff(rhs, 'no_collision_group')
\r
689 self._diff(rhs, 'shape_type')
\r
690 self._diff(rhs, 'shape_size')
\r
691 #self._diff(rhs, 'shape_position')
\r
692 self._diff(rhs, 'shape_rotation')
\r
693 self._diff(rhs, 'param')
\r
694 self._diff(rhs, 'mode')
\r
708 translation_limit_min: Vector3
\r
709 translation_limit_max: Vector3
\r
710 rotation_limit_min: Vector3
\r
711 rotation_limit_max: Vector3
\r
712 spring_constant_translation: Vector3
\r
713 spring_constant_rotation: Vector3
\r
719 'rigidbody_index_a',
\r
720 'rigidbody_index_b',
\r
723 'translation_limit_min',
\r
724 'translation_limit_max',
\r
725 'rotation_limit_min',
\r
726 'rotation_limit_max',
\r
727 'spring_constant_translation',
\r
728 'spring_constant_rotation',
\r
730 def __init__(self, name, english_name,
\r
736 translation_limit_min,
\r
737 translation_limit_max,
\r
738 rotation_limit_min,
\r
739 rotation_limit_max,
\r
740 spring_constant_translation,
\r
741 spring_constant_rotation
\r
744 self.english_name=english_name
\r
745 self.joint_type=joint_type
\r
746 self.rigidbody_index_a=rigidbody_index_a
\r
747 self.rigidbody_index_b=rigidbody_index_b
\r
748 self.position=position
\r
749 self.rotation=rotation
\r
750 self.translation_limit_min=translation_limit_min
\r
751 self.translation_limit_max=translation_limit_max
\r
752 self.rotation_limit_min=rotation_limit_min
\r
753 self.rotation_limit_max=rotation_limit_max
\r
754 self.spring_constant_translation=spring_constant_translation
\r
755 self.spring_constant_rotation=spring_constant_rotation
\r
757 def __eq__(self, rhs):
\r
759 self.name==rhs.name
\r
760 and self.english_name==rhs.english_name
\r
761 and self.joint_type==rhs.joint_type
\r
762 and self.rigidbody_index_a==rhs.rigidbody_index_a
\r
763 and self.rigidbody_index_b==rhs.rigidbody_index_b
\r
764 and self.position==rhs.position
\r
765 and self.rotation==rhs.rotation
\r
766 and self.translation_limit_min==rhs.translation_limit_min
\r
767 and self.translation_limit_max==rhs.translation_limit_max
\r
768 and self.rotation_limit_min==rhs.rotation_limit_min
\r
769 and self.rotation_limit_max==rhs.rotation_limit_max
\r
770 and self.spring_constant_translation==rhs.spring_constant_translation
\r
771 and self.spring_constant_rotation==rhs.spring_constant_rotation
\r
774 def __ne__(self, rhs):
\r
775 return not self.__eq__(rhs)
\r
777 def diff(self, rhs):
\r
778 self._diff(rhs, 'name')
\r
779 self._diff(rhs, 'joint_type')
\r
780 self._diff(rhs, 'rigidbody_index_a')
\r
781 self._diff(rhs, 'rigidbody_index_b')
\r
782 self._diff(rhs, 'position')
\r
783 self._diff(rhs, 'rotation')
\r
784 self._diff(rhs, 'translation_limit_min')
\r
785 self._diff(rhs, 'translation_limit_max')
\r
786 self._diff(rhs, 'rotation_limit_min')
\r
787 self._diff(rhs, 'rotation_limit_max')
\r
788 self._diff(rhs, 'spring_constant_translation')
\r
789 self._diff(rhs, 'spring_constant_rotation')
\r
800 pmx version(expected 2.0)
\r
820 display list for bone/morph grouping
\r
822 bullet physics rigidbody list
\r
824 bullet physics joint list
\r
843 def __init__(self, version=2.0):
\r
845 self.version=version
\r
847 self.english_name=''
\r
849 self.english_comment=''
\r
856 self.display_slots=[]
\r
857 self.rigidbodies=[]
\r
861 return ('<pmx-{version} "{name}" {vertices}vertices>'.format(
\r
862 version=self.version,
\r
863 name=self.english_name,
\r
864 vertices=len(self.vertices)
\r
867 def __eq__(self, rhs):
\r
869 self.version==rhs.version
\r
870 and self.name==rhs.name
\r
871 and self.english_name==rhs.english_name
\r
872 and self.comment==rhs.comment
\r
873 and self.english_comment==rhs.english_comment
\r
874 and self.vertices==rhs.vertices
\r
875 and self.indices==rhs.indices
\r
876 and self.textures==rhs.textures
\r
877 and self.materials==rhs.materials
\r
878 and self.bones==rhs.bones
\r
879 and self.morphs==rhs.morphs
\r
880 and self.display_slots==rhs.display_slots
\r
881 and self.rigidbodies==rhs.rigidbodies
\r
882 and self.joints==rhs.joints
\r
885 def __ne__(self, rhs):
\r
886 return not self.__eq__(rhs)
\r
888 def diff(self, rhs):
\r
889 self._diff(rhs, "version")
\r
890 self._diff(rhs, "name")
\r
891 self._diff(rhs, "english_name")
\r
892 self._diff(rhs, "comment")
\r
893 self._diff(rhs, "english_comment")
\r
894 self._diff_array(rhs, "vertices")
\r
895 self._diff_array(rhs, "indices")
\r
896 self._diff_array(rhs, "textures")
\r
897 self._diff_array(rhs, "materials")
\r
898 self._diff_array(rhs, "bones")
\r
899 self._diff_array(rhs, "morphs")
\r
900 self._diff_array(rhs, "display_slots")
\r
901 self._diff_array(rhs, "rigidbodies")
\r
902 self._diff_array(rhs, "joints")
\r