OSDN Git Service

bc0b13cc5aa32e5c08571d029264a973f7b62ebf
[meshio/pymeshio.git] / pymeshio / pmx / writer.py
1 # coding: utf-8\r
2 """\r
3 pmx writer\r
4 """\r
5 import io\r
6 import struct\r
7 from .. import common\r
8 from .. import pmx\r
9 \r
10 class Writer(common.BinaryWriter):\r
11     """pmx writer\r
12     """\r
13     def __init__(self, ios,\r
14             text_encoding, extended_uv,\r
15             vertex_index_size, texture_index_size, material_index_size,\r
16             bone_index_size, morph_index_size, rigidbody_index_size):\r
17         super(Writer, self).__init__(ios)\r
18         if text_encoding==0:\r
19             def write_text(unicode):\r
20                utf16=unicode.encode('utf16') \r
21                self.write_uint(len(utf16), 4)\r
22                self.write_bytes(utf16)\r
23             self.write_text=write_text\r
24         elif text_encoding==1:\r
25             def write_text(unicode):\r
26                utf8=unicode.encode('utf8') \r
27                self.write_uint(len(utf8), 4)\r
28                self.write_bytes(utf8)\r
29             self.write_text=write_text\r
30         else:\r
31             raise WriteError(\r
32                     "invalid text_encoding: {0}".format(text_encoding))\r
33 \r
34         self.write_vertex_index=lambda index: self.write_uint(index, vertex_index_size)\r
35         self.write_texture_index=lambda index: self.write_uint(index, texture_index_size)\r
36         self.write_material_index=lambda index: self.write_uint(index, material_index_size)\r
37         self.write_bone_index=lambda index: self.write_uint(index, bone_index_size)\r
38         self.write_morph_index=lambda index: self.write_uint(index, morph_index_size)\r
39         self.write_rigidbody_index=lambda index: self.write_uint(index, rigidbody_index_size)\r
40 \r
41     def write_vertices(self, vertices):\r
42         self.write_uint(len(vertices), 4)\r
43         for v in vertices:\r
44             self.write_vector3(v.position)\r
45             self.write_vector3(v.normal)\r
46             self.write_vector2(v.uv)\r
47             self.write_deform(v.deform)\r
48             self.write_float(v.edge_factor)\r
49 \r
50     def write_deform(self, deform):\r
51         if isinstance(deform, pmx.Bdef1):\r
52             self.write_uint(0, 1)\r
53             self.write_bone_index(deform.index0)\r
54         elif isinstance(deform, pmx.Bdef2):\r
55             self.write_uint(1, 1)\r
56             self.write_bone_index(deform.index0)\r
57             self.write_bone_index(deform.index1)\r
58             self.write_float(deform.weight0)\r
59         elif isinstance(deform, pmx.Bdef4):\r
60             # todo\r
61             raise pymeshio.common.WriteException(\r
62                     "not implemented Bdef4")\r
63         else:\r
64             raise pymeshio.common.WriteException(\r
65                     "unknown deform type: {0}".format(deform.type))\r
66 \r
67     def write_indices(self, indices):\r
68         self.write_uint(len(indices), 4)\r
69         for i in indices:\r
70             self.write_vertex_index(i)\r
71 \r
72     def write_textures(self, textures):\r
73         self.write_uint(len(textures), 4)\r
74         for t in textures:\r
75             self.write_text(t)\r
76 \r
77     def write_materials(self, materials):\r
78         self.write_uint(len(materials), 4)\r
79         for m in materials:\r
80             self.write_text(m.name)\r
81             self.write_text(m.english_name)\r
82             self.write_rgb(m.diffuse_color)\r
83             self.write_float(m.alpha)\r
84             self.write_rgb(m.specular_color)\r
85             self.write_float(m.specular_factor)\r
86             self.write_rgb(m.ambient_color)\r
87             self.write_uint(m.flag, 1)\r
88             self.write_rgba(m.edge_color)\r
89             self.write_float(m.edge_size)\r
90             self.write_texture_index(m.texture_index)\r
91             self.write_texture_index(m.sphere_texture_index)\r
92             self.write_uint(m.sphere_mode, 1)\r
93             self.write_uint(m.toon_sharing_flag, 1)\r
94             if m.toon_sharing_flag==0:\r
95                 self.write_texture_index(m.toon_texture_index)\r
96             elif m.toon_sharing_flag==1:\r
97                 self.write_uint(m.toon_texture_index, 1)\r
98             else:\r
99                 raise common.WriteException(\r
100                         "unknown toon_sharing_flag {0}".format(m.toon_sharing_flag))\r
101             self.write_text(m.comment)\r
102             self.write_uint(m.vertex_count, 4)\r
103 \r
104     def write_bones(self, bones):\r
105         self.write_uint(len(bones), 4)\r
106         for bone in bones:\r
107             self.write_text(bone.name)\r
108             self.write_text(bone.english_name)\r
109             self.write_vector3(bone.position)\r
110             self.write_bone_index(bone.parent_index)\r
111             self.write_uint(bone.layer, 4)\r
112             self.write_uint(bone.flag, 2)\r
113             if bone.getConnectionFlag()==0:\r
114                 self.write_vector3(bone.tail_positoin)\r
115             elif bone.getConnectionFlag()==1:\r
116                 self.write_bone_index(bone.tail_index)\r
117             else:\r
118                 raise pymeshio.common.WriteException(\r
119                         "unknown bone conenction flag: {0}".format(\r
120                             bone.getConnectionFlag()))\r
121 \r
122             if bone.getRotationFlag()==1 or bone.getTranslationFlag()==1:\r
123                 self.write_bone_index(bone.effect_index)\r
124                 self.write_float(bone.effect_factor)\r
125 \r
126             if bone.getFixedAxisFlag()==1:\r
127                 self.write_vector3(bone.fixed_axis)\r
128 \r
129             if bone.getLocalCoordinateFlag()==1:\r
130                 self.write_vector3(bone.local_x_vector)\r
131                 self.write_vector3(bone.local_z_vector)\r
132 \r
133             if bone.getExternalParentDeformFlag()==1:\r
134                 self.write_uint(bone.external_key, 4)\r
135 \r
136             if bone.getIkFlag()==1:\r
137                 self.write_ik(bone.ik)\r
138 \r
139     def write_ik(self, ik):\r
140         self.write_bone_index(ik.target_index)\r
141         self.write_uint(ik.loop, 4)\r
142         self.write_float(ik.limit_radian)\r
143         self.write_uint(len(ik.link), 4)\r
144         for l in ik.link:\r
145             self.write_ik_link(l)\r
146 \r
147     def write_ik_link(self, link):\r
148         self.write_bone_index(link.bone_index)\r
149         self.write_uint(link.limit_angle, 1)\r
150         if link.limit_angle==0:\r
151             pass\r
152         elif link.limit_angle==1:\r
153             self.write_vector3(link.limit_min)\r
154             self.write_vector3(link.limit_max)\r
155         else:\r
156             raise pymeshio.common.WriteException(\r
157                     "invalid ik link limit_angle: {0}".format(\r
158                         link.limit_angle))\r
159  \r
160     def write_morph(self, morphs):\r
161         self.write_uint(len(morphs), 4)\r
162         for m in morphs:\r
163             self.write_text(m.name)\r
164             self.write_text(m.english_name)\r
165             self.write_uint(m.panel, 1)\r
166             self.write_uint(m.morph_type, 1)\r
167             if m.morph_type==0:\r
168                 # todo\r
169                 raise pymeshio.common.WriteException(\r
170                         "not implemented GroupMorph")\r
171             elif m.morph_type==1:\r
172                 self.write_uint(len(m.offsets), 4)\r
173                 for o in m.offsets:\r
174                     self.write_vertex_index(o.vertex_index)\r
175                     self.write_vector3(o.position_offset)\r
176             elif m.morph_type==2:\r
177                 # todo\r
178                 raise pymeshio.common.WriteException(\r
179                         "not implemented BoneMorph")\r
180             elif m.morph_type==3:\r
181                 # todo\r
182                 raise pymeshio.common.WriteException(\r
183                         "not implemented UvMorph")\r
184             elif m.morph_type==4:\r
185                 # todo\r
186                 raise pymeshio.common.WriteException(\r
187                         "not implemented extended UvMorph1")\r
188             elif m.morph_type==5:\r
189                 # todo\r
190                 raise pymeshio.common.WriteException(\r
191                         "not implemented extended UvMorph2")\r
192             elif m.morph_type==6:\r
193                 # todo\r
194                 raise pymeshio.common.WriteException(\r
195                         "not implemented extended UvMorph3")\r
196             elif m.morph_type==7:\r
197                 # todo\r
198                 raise pymeshio.common.WriteException(\r
199                         "not implemented extended UvMorph4")\r
200             elif m.morph_type==8:\r
201                 # todo\r
202                 raise pymeshio.common.WriteException(\r
203                         "not implemented extended MaterialMorph")\r
204             else:\r
205                 raise pymeshio.common.WriteException(\r
206                         "unknown morph type: {0}".format(m.morph_type))\r
207 \r
208     def write_display_slots(self, display_slots):\r
209         self.write_uint(len(display_slots), 4)\r
210         for s in display_slots:\r
211             self.write_text(s.name)\r
212             self.write_text(s.english_name)\r
213             self.write_uint(s.special_flag, 1)\r
214             self.write_uint(len(s.refrences), 4)\r
215             for r in s.refrences:\r
216                 self.write_uint(r[0], 1)\r
217                 if r[0]==0:\r
218                     self.write_bone_index(r[1])\r
219                 elif r[0]==1:\r
220                     self.write_morph_index(r[1])\r
221                 else:\r
222                     raise pymeshio.common.WriteException(\r
223                             "unknown display_type: {0}".format(r[0]))\r
224 \r
225     def write_rigidbodies(self, rigidbodies):\r
226         self.write_uint(len(rigidbodies), 4)\r
227         for rb in rigidbodies:\r
228             self.write_text(rb.name)\r
229             self.write_text(rb.english_name)\r
230             self.write_bone_index(rb.bone_index)\r
231             self.write_uint(rb.collision_group, 1)\r
232             self.write_uint(rb.no_collision_group, 2)\r
233             self.write_uint(rb.shape_type, 1)\r
234             self.write_vector3(rb.shape_size)\r
235             self.write_vector3(rb.shape_position)\r
236             self.write_vector3(rb.shape_rotation)\r
237             self.write_float(rb.param.mass)\r
238             self.write_float(rb.param.linear_damping)\r
239             self.write_float(rb.param.angular_damping)\r
240             self.write_float(rb.param.restitution)\r
241             self.write_float(rb.param.friction)\r
242             self.write_uint(rb.mode, 1)\r
243 \r
244     def write_joints(self, joints):\r
245         self.write_uint(len(joints), 4)\r
246         for j in joints:\r
247             self.write_text(j.name)\r
248             self.write_text(j.english_name)\r
249             self.write_uint(j.joint_type, 1)\r
250             self.write_rigidbody_index(j.rigidbody_index_a)\r
251             self.write_rigidbody_index(j.rigidbody_index_b)\r
252             self.write_vector3(j.position)\r
253             self.write_vector3(j.rotation)\r
254             self.write_vector3(j.translation_limit_min)\r
255             self.write_vector3(j.translation_limit_max)\r
256             self.write_vector3(j.rotation_limit_min)\r
257             self.write_vector3(j.rotation_limit_max)\r
258             self.write_vector3(j.spring_constant_translation)\r
259             self.write_vector3(j.spring_constant_rotation)\r
260 \r
261 \r
262 def write(ios, model, text_encoding=1):\r
263     """pmx書き込み\r
264     """\r
265     assert(isinstance(ios, io.IOBase))\r
266     assert(isinstance(model, pmx.Model))\r
267     writer=common.BinaryWriter(ios)\r
268     # header\r
269     writer.write_bytes(b"PMX ")\r
270     writer.write_float(model.version)\r
271 \r
272     # flags\r
273     writer.write_uint(8, 1)\r
274     # textencoding\r
275     writer.write_uint(text_encoding, 1)\r
276     # extend uv\r
277     writer.write_uint(0, 1)\r
278     def get_array_size(size):\r
279         if size<128:\r
280             return 1\r
281         elif size<32768:\r
282             return 2\r
283         elif size<2147483647:\r
284             return 4\r
285         else:\r
286             raise common.WriteError(\r
287                     "invalid array_size: {0}".format(size))\r
288     # vertex_index_size\r
289     vertex_index_size=get_array_size(len(model.vertices))\r
290     writer.write_uint(vertex_index_size, 1)\r
291     # texture_index_size\r
292     texture_index_size=get_array_size(len(model.textures))\r
293     writer.write_uint(texture_index_size, 1)\r
294     # material_index_size\r
295     material_index_size=get_array_size(len(model.materials))\r
296     writer.write_uint(material_index_size, 1)\r
297     # bone_index_size\r
298     bone_index_size=get_array_size(len(model.bones))\r
299     writer.write_uint(bone_index_size, 1)\r
300     # morph_index_size\r
301     morph_index_size=get_array_size(len(model.morphs))\r
302     writer.write_uint(morph_index_size, 1)\r
303     # rigidbody_index_size\r
304     rigidbody_index_size=get_array_size(len(model.rigidbodies))\r
305     writer.write_uint(rigidbody_index_size, 1)\r
306 \r
307     writer=Writer(writer.ios, \r
308             text_encoding, 0,\r
309             vertex_index_size, texture_index_size, material_index_size,\r
310             bone_index_size, morph_index_size, rigidbody_index_size)\r
311  \r
312     # model info\r
313     writer.write_text(model.name)\r
314     writer.write_text(model.english_name)\r
315     writer.write_text(model.comment)\r
316     writer.write_text(model.english_comment)\r
317 \r
318     # model data\r
319     writer.write_vertices(model.vertices)\r
320     writer.write_indices(model.indices)\r
321     writer.write_textures(model.textures)\r
322     writer.write_materials(model.materials)\r
323     writer.write_bones(model.bones)\r
324     writer.write_morph(model.morphs)\r
325     writer.write_display_slots(model.display_slots)\r
326     writer.write_rigidbodies(model.rigidbodies)\r
327     writer.write_joints(model.joints)\r
328     return True\r
329 \r