OSDN Git Service

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