OSDN Git Service

refactoring export_pmd
[meshio/pymeshio.git] / pymeshio / pmd / writer.py
1 # coding: utf-8\r
2 """\r
3 pmd writer\r
4 """\r
5 import io\r
6 import struct\r
7 from .. import common\r
8 from .. import pmd\r
9 \r
10 \r
11 class Writer(common.BinaryWriter):\r
12     def write_veritices(self, vertices):\r
13         self.write_uint(len(vertices), 4)\r
14         for v in vertices:\r
15             self.write_vector3(v.pos)\r
16             self.write_vector3(v.normal)\r
17             self.write_vector2(v.uv)\r
18             self.write_uint(v.bone0, 2)\r
19             self.write_uint(v.bone1, 2)\r
20             self.write_uint(v.weight0, 1)\r
21             self.write_uint(v.edge_flag, 1)\r
22 \r
23     def write_indices(self, indices):\r
24         self.write_uint(len(indices), 4)\r
25         self.ios.write(struct.pack("=%dH" % len(indices), *indices))\r
26 \r
27     def write_materials(self, materials):\r
28         self.write_uint(len(materials), 4)\r
29         for m in materials:\r
30             self.write_rgb(m.diffuse_color)\r
31             self.write_float(m.alpha)\r
32             self.write_float(m.specular_factor)\r
33             self.write_rgb(m.specular_color)\r
34             self.write_rgb(m.ambient_color)\r
35             self.write_uint(m.toon_index, 1)\r
36             self.write_uint(m.edge_flag, 1)\r
37             self.write_uint(m.vertex_count, 4)\r
38             self.write_bytes(m.texture_file, 20)\r
39 \r
40     def write_bones(self, bones):\r
41         self.write_uint(len(bones), 2)\r
42         sBone=struct.Struct("=20sHHBH3f")\r
43         assert(sBone.size==39)\r
44         for b in bones:\r
45             self.write_bytes(b.name, 20)\r
46             self.write_uint(b.parent_index, 2)\r
47             self.write_uint(b.tail_index, 2)\r
48             self.write_uint(b.type, 1)\r
49             self.write_uint(b.ik_index, 2)\r
50             self.write_vector3(b.pos)\r
51 \r
52     def write_ik_list(self, ik_list):\r
53         self.write_uint(len(ik_list), 2)\r
54         for ik in ik_list:\r
55             self.write_uint(ik.index, 2)\r
56             self.write_uint(ik.target, 2)\r
57             self.write_uint(len(ik.children), 1)\r
58             self.write_uint(ik.iterations, 2)\r
59             self.write_float(ik.weight)\r
60             self.ios.write(struct.pack("=%dH" % len(ik.children), *ik.children))\r
61 \r
62     def write_morphs(self, morphs):\r
63         self.write_uint(len(morphs), 2)\r
64         for morph in morphs:\r
65             self.write_bytes(morph.name, 20)\r
66             self.write_uint(len(morph.indices), 4)\r
67             self.write_uint(morph.type, 1)\r
68             for i, v in zip(morph.indices, morph.pos_list):\r
69                 self.write_uint(i, 4)\r
70                 self.write_vector3(v)\r
71 \r
72     def write_morph_indices(self, morph_indices):\r
73         self.write_uint(len(morph_indices), 1)\r
74         self.ios.write(struct.pack("=%dH" % len(morph_indices), *morph_indices))\r
75 \r
76     def write_bone_group_list(self, bone_group_list):\r
77         self.write_uint(len(bone_group_list), 1)\r
78         for g in bone_group_list:\r
79             self.write_bytes(g.name, 50)\r
80 \r
81     def write_bone_display_list(self, bone_display_list):\r
82         self.write_uint(len(bone_display_list), 4)\r
83         for l in bone_display_list:\r
84             self.write_uint(l[0], 2)\r
85             self.write_uint(l[1], 1)\r
86 \r
87     def write_rigidbodies(self, rigidbodies):\r
88         self.write_uint(len(rigidbodies), 4)\r
89         for r in rigidbodies:\r
90             self.write_bytes(r.name, 20)\r
91             self.write_int(r.bone_index, 2)\r
92             self.write_uint(r.collision_group, 1)\r
93             self.write_int(r.no_collision_group, 2)\r
94             self.write_uint(r.shape_type, 1)\r
95             self.write_vector3(r.shape_size)\r
96             self.write_vector3(r.shape_position)\r
97             self.write_vector3(r.shape_rotation)\r
98             self.write_float(r.mass)\r
99             self.write_float(r.linear_damping)\r
100             self.write_float(r.angular_damping)\r
101             self.write_float(r.restitution)\r
102             self.write_float(r.friction)\r
103             self.write_uint(r.mode, 1)\r
104 \r
105     def write_joints(self, joints):\r
106         self.write_uint(len(joints), 4)\r
107         for j in joints:\r
108             self.write_bytes(j.name, 20)\r
109             self.write_uint(j.rigidbody_index_a, 4)\r
110             self.write_uint(j.rigidbody_index_b, 4)\r
111             self.write_vector3(j.position)\r
112             self.write_vector3(j.rotation)\r
113             self.write_vector3(j.translation_limit_min)\r
114             self.write_vector3(j.translation_limit_max)\r
115             self.write_vector3(j.rotation_limit_min)\r
116             self.write_vector3(j.rotation_limit_max)\r
117             self.write_vector3(j.spring_constant_translation)\r
118             self.write_vector3(j.spring_constant_rotation)\r
119 \r
120 \r
121 def write(ios, model):\r
122     """\r
123     write model to ios.\r
124 \r
125     :Parameters:\r
126         ios\r
127             output stream (in io.IOBase)\r
128         model\r
129             pmd model\r
130 \r
131     >>> import pymeshio.pmd.writer\r
132     >>> pymeshio.pmd.writer.write(io.open('out.pmd', 'wb'), pmd_model)\r
133 \r
134     """\r
135     assert(isinstance(ios, io.IOBase))\r
136     assert(isinstance(model, pmd.Model))\r
137     writer=Writer(ios)\r
138     writer.write_bytes(b"Pmd")\r
139     writer.write_float(model.version)\r
140     writer.write_bytes(model.name, 20)\r
141     writer.write_bytes(model.comment, 256)\r
142     writer.write_veritices(model.vertices)\r
143     writer.write_indices(model.indices)\r
144     writer.write_materials(model.materials)\r
145     writer.write_bones(model.bones)\r
146     writer.write_ik_list(model.ik_list)\r
147     writer.write_morphs(model.morphs)\r
148     writer.write_morph_indices(model.morph_indices)\r
149     writer.write_bone_group_list(model.bone_group_list)\r
150     writer.write_bone_display_list(model.bone_display_list)\r
151     # extend data\r
152     writer.write_uint(1, 1)\r
153     writer.write_bytes(model.english_name, 20)\r
154     writer.write_bytes(model.english_comment, 256)\r
155     for bone in model.bones:\r
156         writer.write_bytes(bone.english_name, 20)\r
157     for skin in model.morphs:\r
158         if skin.name==b'base':\r
159             continue\r
160         writer.write_bytes(skin.english_name, 20)\r
161     for g in model.bone_group_list:\r
162         writer.write_bytes(g.english_name, 50)\r
163     for toon_texture in model.toon_textures:\r
164         writer.write_bytes(toon_texture, 100)\r
165     writer.write_rigidbodies(model.rigidbodies)\r
166     writer.write_joints(model.joints)\r
167     return True\r
168 \r