OSDN Git Service

77d45a38e28e2335d1e2579bb521f366d575f081
[meshio/pymeshio.git] / pymeshio / pmx / __init__.py
1 #!/usr/bin/env python\r
2 # coding: utf-8\r
3 """\r
4 ========================\r
5 MikuMikuDance PMX format\r
6 ========================\r
7 \r
8 file format\r
9 ~~~~~~~~~~~\r
10 * PMDEditor's Lib/PMX仕様/PMX仕様.txt\r
11 \r
12 specs\r
13 ~~~~~\r
14 * textencoding: unicode\r
15 * coordinate: left handed y-up(DirectX)\r
16 * uv origin: \r
17 * face: only triangle\r
18 * backculling: \r
19 \r
20 """\r
21 __author__="ousttrue"\r
22 __license__="zlib"\r
23 __versioon__="1.0.0"\r
24 \r
25 \r
26 import io\r
27 import os\r
28 import struct\r
29 from pymeshio import common\r
30 \r
31 \r
32 \r
33 class Ik(object):\r
34     """ik info\r
35     """\r
36     __slots__=[\r
37             'target_index',\r
38             'loop',\r
39             'limit_radian',\r
40             'link',\r
41             ]\r
42     def __init__(self, target_index, loop, limit_radian):\r
43         self.target_index=target_index\r
44         self.loop=loop\r
45         self.limit_radian=limit_radian\r
46         self.link=[]\r
47 \r
48 \r
49 class IkLink(object):\r
50     """ik link info\r
51     """\r
52     __slots__=[\r
53             'bone_index',\r
54             'limit_angle',\r
55             'limit_min',\r
56             'limit_max',\r
57             ]\r
58     def __init__(self, bone_index, limit_angle):\r
59         self.bone_index=bone_index\r
60         self.limit_angle=limit_angle\r
61         self.limit_min=None\r
62         self.limit_max=None\r
63 \r
64 \r
65 class Bone(object):\r
66     """material\r
67 \r
68     Bone: see __init__\r
69     """\r
70     __slots__=[\r
71             'name',\r
72             'english_name',\r
73             'position',\r
74             'parent_index',\r
75             'layer',\r
76             'flag',\r
77 \r
78             'tail_positoin',\r
79             'tail_index',\r
80             'effect_index',\r
81             'effect_factor',\r
82             'fixed_axis',\r
83             'local_x_vector',\r
84             'local_z_vector',\r
85             'external_key',\r
86             'ik',\r
87             ]\r
88     def __init__(self,\r
89             name,\r
90             english_name,\r
91             position,\r
92             parent_index,\r
93             layer,\r
94             flag\r
95             ):\r
96         self.name=name\r
97         self.english_name=english_name\r
98         self.position=position\r
99         self.parent_index=parent_index\r
100         self.layer=layer\r
101         self.flag=flag\r
102 \r
103     def __eq__(self, rhs):\r
104         return (\r
105                 self.name==rhs.name\r
106                 and self.english_name==rhs.english_name\r
107                 and self.position==rhs.position\r
108                 and self.parent_index==rhs.parent_index\r
109                 and self.layer==rhs.layer\r
110                 and self.flag==rhs.flag\r
111                 )\r
112 \r
113     def getConnectionFlag(self):\r
114         return self.flag & 0x0001\r
115 \r
116     def getIkFlag(self):\r
117         return (self.flag & 0x0020) >> 5\r
118 \r
119     def getRotationFlag(self):\r
120         return (self.flag & 0x0100) >> 8\r
121 \r
122     def getTranslationFlag(self):\r
123         return (self.flag & 0x0200) >> 9\r
124 \r
125     def getFixedAxisFlag(self):\r
126         return (self.flag & 0x0400) >> 10\r
127 \r
128     def getLocalCoordinateFlag(self):\r
129         return (self.flag &  0x0800) >> 11\r
130     \r
131     def getExternalParentDeformFlag(self):\r
132         return (self.flag &  0x2000) >> 13\r
133 \r
134  \r
135 class Material(object):\r
136     """material\r
137 \r
138     Attributes: see __init__\r
139     """\r
140     __slots__=[\r
141             'name',\r
142             'english_name',\r
143             'diffuse_color',\r
144             'alpha',\r
145             'specular_color',\r
146             'specular_factor',\r
147             'ambient_color',\r
148             'flag',\r
149             'edge_color',\r
150             'edge_size',\r
151             'texture_index',\r
152             'sphere_texture_index',\r
153             'sphere_mode',\r
154             'toon_sharing_flag',\r
155             'toon_texture_index',\r
156             'comment',\r
157             'vertex_count',\r
158             ]\r
159     def __init__(self,\r
160             name,\r
161             english_name,\r
162             diffuse_color,\r
163             alpha,\r
164             specular_color,\r
165             specular_factor,\r
166             ambient_color,\r
167             flag,\r
168             edge_color,\r
169             edge_size,\r
170             texture_index,\r
171             sphere_texture_index,\r
172             sphere_mode,\r
173             toon_sharing_flag\r
174             ):\r
175         self.name=name\r
176         self.english_name=english_name\r
177         self.diffuse_color=diffuse_color\r
178         self.alpha=alpha\r
179         self.specular_color=specular_color\r
180         self.specular_factor=specular_factor\r
181         self.ambient_color=ambient_color\r
182         self.flag=flag\r
183         self.edge_color=edge_color\r
184         self.edge_size=edge_size\r
185         self.texture_index=texture_index\r
186         self.sphere_texture_index=sphere_texture_index\r
187         self.sphere_mode=sphere_mode\r
188         self.toon_sharing_flag=toon_sharing_flag\r
189         #\r
190         self.toon_texture_index=None\r
191         self.comment=name.__class__() # unicode\r
192         self.vertex_count=0\r
193 \r
194     def __eq__(self, rhs):\r
195         return (\r
196                 self.name==rhs.name\r
197                 and self.english_name==rhs.english_name\r
198                 and self.diffuse_color==rhs.diffuse_color\r
199                 and self.alpha==rhs.alpha\r
200                 and self.specular_color==rhs.specular_color\r
201                 and self.specular_factor==rhs.specular_factor\r
202                 and self.ambient_color==rhs.ambient_color\r
203                 and self.flag==rhs.flag\r
204                 and self.edge_color==rhs.edge_color\r
205                 and self.edge_size==rhs.edge_size\r
206                 and self.texture_index==rhs.texture_index\r
207                 and self.sphere_texture_index==rhs.sphere_texture_index\r
208                 and self.sphere_mode==rhs.sphere_mode\r
209                 and self.toon_sharing_flag==rhs.toon_sharing_flag\r
210                 and self.toon_texture_index==rhs.toon_texture_index\r
211                 and self.comment==rhs.comment\r
212                 and self.vertex_count==rhs.vertex_count\r
213                 )\r
214 \r
215     def __str__(self):\r
216         return ("<pmx.Material {name}>".format(\r
217             name=self.english_name\r
218             ))\r
219 \r
220 \r
221 class Deform(object):\r
222     pass\r
223 \r
224 \r
225 class Bdef1(object):\r
226     """bone deform. use a weight\r
227 \r
228     Attributes: see __init__\r
229     """\r
230     __slots__=[ 'index0']\r
231     def __init__(self, index0):\r
232         self.index0=index0\r
233 \r
234     def __eq__(self, rhs):\r
235         return self.index0==rhs.index0\r
236 \r
237 \r
238 class Bdef2(object):\r
239     """bone deform. use two weights\r
240 \r
241     Attributes: see __init__\r
242     """\r
243     __slots__=[ 'index0', 'index1', 'weight0']\r
244     def __init__(self, \r
245             index0,\r
246             index1,\r
247             weight0):\r
248         self.index0=index0\r
249         self.index1=index1\r
250         self.weight0=weight0\r
251 \r
252     def __eq__(self, rhs):\r
253         return (\r
254                 self.index0==rhs.index0\r
255                 and self.index1==rhs.index1\r
256                 and self.weight0==rhs.weight0\r
257                 )\r
258 \r
259 \r
260 class Vertex(object):\r
261     """pmx vertex\r
262 \r
263     Attributes: see __init__\r
264     """\r
265     __slots__=[ 'position', 'normal', 'uv', 'deform', 'edge_factor' ]\r
266     def __init__(self, \r
267             position, \r
268             normal, \r
269             uv, \r
270             deform, \r
271             edge_factor):\r
272         self.position=position \r
273         self.normal=normal\r
274         self.uv=uv\r
275         self.deform=deform\r
276         self.edge_factor=edge_factor\r
277 \r
278     def __eq__(self, rhs):\r
279         return (\r
280                 self.position==rhs.position\r
281                 and self.normal==rhs.normal\r
282                 and self.uv==rhs.uv\r
283                 and self.deform==rhs.deform\r
284                 and self.edge_factor==rhs.edge_factor\r
285                 )\r
286 \r
287 \r
288 class Morph(object):\r
289     """pmx morph\r
290 \r
291     Attributes:\r
292         name: \r
293         english_name: \r
294         panel:\r
295         morph_type:\r
296         offsets:\r
297     """\r
298     __slots__=[\r
299             'name',\r
300             'english_name',\r
301             'panel',\r
302             'morph_type',\r
303             'offsets',\r
304             ]\r
305     def __init__(self, name, english_name, panel, morph_type):\r
306         self.name=name\r
307         self.english_name=english_name\r
308         self.panel=panel\r
309         self.morph_type=morph_type\r
310         self.offsets=[]\r
311 \r
312     def __eq__(self, rhs):\r
313         return (\r
314                 self.name==rhs.name\r
315                 and self.english_name==rhs.english_name\r
316                 and self.panel==rhs.panel\r
317                 and self.morph_type==rhs.morph_type\r
318                 and self.offsets==rhs.offsets\r
319                 )\r
320 \r
321 \r
322 class VerexMorphOffset(object):\r
323     """pmx vertex morph offset\r
324 \r
325     Attributes:\r
326         vertex_index:\r
327         position_offset: Vector3\r
328     """\r
329     __slots__=[\r
330             'vertex_index',\r
331             'position_offset',\r
332             ]\r
333     def __init__(self, vertex_index, position_offset):\r
334         self.vertex_index=vertex_index\r
335         self.position_offset=position_offset\r
336 \r
337     def __eq__(self, rhs):\r
338         return (\r
339                 self.vertex_index==rhs.vertex_index \r
340                 and self.position_offset==rhs.position_offset\r
341                 )\r
342 \r
343 \r
344 class DisplaySlot(object):\r
345     """pmx display slot\r
346 \r
347     Attributes:\r
348         name: \r
349         english_name: \r
350         special_flag:\r
351         refrences: list of (ref_type, ref_index)\r
352     """\r
353     __slots__=[\r
354             'name',\r
355             'english_name',\r
356             'special_flag',\r
357             'refrences',\r
358             ]\r
359     def __init__(self, name, english_name, special_flag):\r
360         self.name=name\r
361         self.english_name=english_name\r
362         self.special_flag=special_flag\r
363         self.refrences=[]\r
364 \r
365     def __eq__(self, rhs):\r
366         return (\r
367                 self.name==rhs.name\r
368                 and self.english_name==rhs.english_name\r
369                 and self.special_flag==rhs.special_flag\r
370                 and self.refrences==rhs.refrences\r
371                 )\r
372 \r
373 \r
374 class RigidBodyParam(object):\r
375     """pmx rigidbody param(for bullet)\r
376 \r
377     Attributes:\r
378         mass:\r
379         linear_damping:\r
380         angular_damping:\r
381         restitution:\r
382         friction:\r
383     """\r
384     __slots__=[\r
385             'mass',\r
386             'linear_damping',\r
387             'angular_damping',\r
388             'restitution',\r
389             'friction',\r
390             ]\r
391     def __init__(self, mass, \r
392             linear_damping, angular_damping, restitution, friction):\r
393         self.mass=mass\r
394         self.linear_damping=linear_damping\r
395         self.angular_damping=angular_damping\r
396         self.restitution=restitution\r
397         self.friction=friction\r
398 \r
399     def __eq__(self, rhs):\r
400         return (\r
401                 self.mass==rhs.mass\r
402                 and self.linear_damping==rhs.linear_damping\r
403                 and self.angular_damping==rhs.angular_damping\r
404                 and self.restitution==rhs.restitution\r
405                 and self.friction==rhs.friction\r
406                 )\r
407 \r
408 \r
409 class RigidBody(object):\r
410     """pmx rigidbody\r
411 \r
412     Attributes:\r
413         name: \r
414         english_name: \r
415         bone_index:\r
416         collision_group:\r
417         no_collision_group:\r
418         shape:\r
419         param:\r
420         mode:\r
421     """\r
422     __slots__=[\r
423             'name',\r
424             'english_name',\r
425             'bone_index',\r
426             'collision_group',\r
427             'no_collision_group',\r
428             'shape_type',\r
429             'shape_size',\r
430             'shape_position',\r
431             'shape_rotation',\r
432             'param',\r
433             'mode',\r
434             ]\r
435     def __init__(self,\r
436             name,\r
437             english_name,\r
438             bone_index,\r
439             collision_group,\r
440             no_collision_group,\r
441             shape_type,\r
442             shape_size,\r
443             shape_position,\r
444             shape_rotation,\r
445             mass,\r
446             linear_damping,\r
447             angular_damping,\r
448             restitution,\r
449             friction,\r
450             mode\r
451             ):\r
452         self.name=name\r
453         self.english_name=english_name\r
454         self.bone_index=bone_index\r
455         self.collision_group=collision_group\r
456         self.no_collision_group=no_collision_group\r
457         self.shape_type=shape_type\r
458         self.shape_size=shape_size\r
459         self.shape_position=shape_position\r
460         self.shape_rotation=shape_rotation\r
461         self.param=RigidBodyParam(mass,\r
462                 linear_damping, angular_damping,\r
463                 restitution, friction)\r
464         self.mode=mode\r
465 \r
466     def __eq__(self, rhs):\r
467         return (\r
468                 self.name==rhs.name\r
469                 and self.english_name==rhs.english_name\r
470                 and self.bone_index==rhs.bone_index\r
471                 and self.collision_group==rhs.collision_group\r
472                 and self.no_collision_group==rhs.no_collision_group\r
473                 and self.shape_type==rhs.shape_type\r
474                 and self.shape_size==rhs.shape_size\r
475                 and self.param==rhs.param\r
476                 and self.mode==rhs.mode\r
477                 )\r
478 \r
479 \r
480 class Joint(object):\r
481     """pmx joint\r
482 \r
483     Attributes:\r
484         name: \r
485         english_name: \r
486         joint_type:\r
487         rigidbody_index_a:\r
488         rigidbody_index_b:\r
489         position: Vector3\r
490         rotation: Vector3\r
491         translation_limit_min: Vector3\r
492         translation_limit_max: Vector3\r
493         rotation_limit_min: Vector3\r
494         rotation_limit_max: Vector3\r
495         spring_constant_translation: Vector3\r
496         spring_constant_rotation: Vector3\r
497     """\r
498     __slots__=[\r
499             'name',\r
500             'english_name',\r
501             'joint_type',\r
502             'rigidbody_index_a',\r
503             'rigidbody_index_b',\r
504             'position',\r
505             'rotation',\r
506             'translation_limit_min',\r
507             'translation_limit_max',\r
508             'rotation_limit_min',\r
509             'rotation_limit_max',\r
510             'spring_constant_translation',\r
511             'spring_constant_rotation',\r
512             ]\r
513     def __init__(self, name, english_name,\r
514             joint_type,\r
515             rigidbody_index_a,\r
516             rigidbody_index_b,\r
517             position,\r
518             rotation,\r
519             translation_limit_min,\r
520             translation_limit_max,\r
521             rotation_limit_min,\r
522             rotation_limit_max,\r
523             spring_constant_translation,\r
524             spring_constant_rotation\r
525             ):\r
526         self.name=name\r
527         self.english_name=english_name\r
528         self.joint_type=joint_type\r
529         self.rigidbody_index_a=rigidbody_index_a\r
530         self.rigidbody_index_b=rigidbody_index_b\r
531         self.position=position\r
532         self.rotation=rotation\r
533         self.translation_limit_min=translation_limit_min\r
534         self.translation_limit_max=translation_limit_max\r
535         self.rotation_limit_min=rotation_limit_min\r
536         self.rotation_limit_max=rotation_limit_max\r
537         self.spring_constant_translation=spring_constant_translation\r
538         self.spring_constant_rotation=spring_constant_rotation\r
539 \r
540     def __eq__(self, rhs):\r
541         return (\r
542                 self.name==rhs.name\r
543                 and self.english_name==rhs.english_name\r
544                 and self.joint_type==rhs.joint_type\r
545                 and self.rigidbody_index_a==rhs.rigidbody_index_a\r
546                 and self.rigidbody_index_b==rhs.rigidbody_index_b\r
547                 and self.position==rhs.position\r
548                 and self.rotation==rhs.rotation\r
549                 and self.translation_limit_min==rhs.translation_limit_min\r
550                 and self.translation_limit_max==rhs.translation_limit_max\r
551                 and self.rotation_limit_min==rhs.rotation_limit_min\r
552                 and self.rotation_limit_max==rhs.rotation_limit_max\r
553                 and self.spring_constant_translation==rhs.spring_constant_translation\r
554                 and self.spring_constant_rotation==rhs.spring_constant_rotation\r
555                 )\r
556 \r
557 \r
558 class Model(object):\r
559     """pmx data representation\r
560 \r
561     Attributes:\r
562         version: pmx version(expected 2.0)\r
563         name: \r
564         english_name: \r
565         comment: \r
566         english_comment: \r
567         vertices:\r
568         textures:\r
569         materials:\r
570         bones:\r
571         morph:\r
572         display_slots:\r
573         rigidbodies:\r
574         joints:\r
575     """\r
576     __slots__=[\r
577             'version', # pmx version\r
578             'name', # model name\r
579             'english_name', # model name in english\r
580             'comment', # model comment\r
581             'english_comment', # model comment in english\r
582             'vertices',\r
583             'indices',\r
584             'textures',\r
585             'materials',\r
586             'bones',\r
587             'morphs',\r
588             'display_slots',\r
589             'rigidbodies',\r
590             'joints',\r
591             ]\r
592     def __init__(self, version):\r
593         self.version=version\r
594         self.name=''\r
595         self.english_name=''\r
596         self.comment=''\r
597         self.english_comment=''\r
598         self.vertices=[]\r
599         self.indices=[]\r
600         self.textures=[]\r
601         self.materials=[]\r
602         self.bones=[]\r
603         self.morphs=[]\r
604         self.display_slots=[]\r
605         self.rigidbodies=[]\r
606         self.joints=[]\r
607 \r
608     def __str__(self):\r
609         return ('<pmx-{version} "{name}" {vertices}vertices>'.format(\r
610             version=self.version,\r
611             name=self.english_name,\r
612             vertices=len(self.vertices)\r
613             ))\r
614 \r
615     def __eq__(self, rhs):\r
616         return (\r
617                 self.version==rhs.version\r
618                 and self.name==rhs.name\r
619                 and self.english_name==rhs.english_name\r
620                 and self.comment==rhs.comment\r
621                 and self.english_comment==rhs.english_comment\r
622                 and self.vertices==rhs.vertices\r
623                 and self.indices==rhs.indices\r
624                 and self.textures==rhs.textures\r
625                 and self.materials==rhs.materials\r
626                 and self.bones==rhs.bones\r
627                 and self.morphs==rhs.morphs\r
628                 and self.display_slots==rhs.display_slots\r
629                 and self.rigidbodies==rhs.rigidbodies\r
630                 and self.joints==rhs.joints\r
631                 )\r
632 \r