OSDN Git Service

fix
[meshio/pymeshio.git] / pymeshio / converter.py
1 # coding: utf-8
2 """
3 convert model
4 """
5
6 import math
7 from . import common
8 from .common import unicode as u
9 from . import pmx
10 from . import pmd
11
12 class ConvertException(Exception):
13     """
14     Exception in writer
15     """
16     pass
17
18
19 def pmd_to_pmx(src):
20     """
21     return pymeshio.pmx.Model.
22
23     :Parameters:
24         src
25             pymeshio.pmd.Model
26     """
27     dst=pmx.Model()
28     # model info
29     dst.name=src.name.decode("cp932")
30     dst.english_name=src.english_name.decode("cp932")
31     dst.comment=src.comment.replace(
32             b"\n", b"\r\n").decode("cp932")
33     dst.english_comment=src.english_comment.replace(
34             b"\n", b"\r\n").decode("cp932")
35     # vertices
36     def createDeform(bone0, bone1, weight0):
37         if weight0==0:
38             return pmx.Bdef1(bone1)
39         elif weight0==100:
40             return pmx.Bdef1(bone0)
41         else:
42             return pmx.Bdef2(bone0, bone1, weight0*0.01)
43     dst.vertices=[
44             pmx.Vertex(
45                 v.pos, 
46                 v.normal, 
47                 v.uv, 
48                 createDeform(v.bone0, v.bone1, v.weight0), 
49                 1.0 if v.edge_flag==0 else 0.0
50                 )
51             for v in src.vertices]
52     # indices
53     dst.indices=src.indices[:]
54     # materials
55     texture_map={}
56     def get_flag(m):
57         return (
58                 (1 if False  else 0)+
59                 (2 if (m.edge_flag & 1!=0) else 0)+
60                 (4 if True else 0)+
61                 (8 if True else 0)+
62                 (16 if (m.edge_flag & 1!=0) else 0)
63                 )
64     def get_texture_file(path):
65         if len(path)==0:
66             return None
67         elif path.find(b'*')==-1:
68             return path
69         else:
70             return b'*'.split(path)[0]
71     def get_sphere_texture_file(path):
72         if len(path)==0:
73             return None
74         elif path.find(b'*')==-1:
75             return None
76         else:
77             return b'*'.split(path)[1]
78     def get_texture_index(path):
79         try:
80             return texture_map[get_texture_file(path)]
81         except KeyError:
82             return -1
83     def get_sphere_texture_index(path):
84         try:
85             return texture_map[get_sphere_texture_file(path)]
86         except KeyError:
87             return -1
88     def get_sphere_texture_flag(path):
89         sphere_texture=get_sphere_texture_file(path)
90         if sphere_texture:
91             if sphere_texture.endswith('.sph'):
92                 return 1
93             elif sphere_texture.endswith('.spa'):
94                 return 2
95             else:
96                 raise ConvertException(
97                         "invalid sphere texture: {0}".format(sphere_texture))
98         return 0
99     def get_toon_shared_flag(m):
100         return 1
101     def get_toon_index(m):
102         return m.toon_index
103     for m in src.materials:
104         texture=get_texture_file(m.texture_file)
105         if texture and not texture in texture_map:
106             texture_map[texture]=len(texture_map)
107             dst.textures.append(texture.decode("cp932"))
108         sphere_texture=get_sphere_texture_file(m.texture_file)
109         if sphere_texture and not sphere_texture in texture_map:
110             texture_map[sphere_texture]=len(texture_map)
111             dst.textures.append(sphere_texture.decode("cp932"))
112     dst.materials=[
113             pmx.Material(
114                 name=common.unicode(""),
115                 english_name=common.unicode(""),
116                 diffuse_color=m.diffuse_color,
117                 alpha=m.alpha,
118                 specular_factor=m.specular_factor,
119                 specular_color=m.specular_color,
120                 ambient_color=m.ambient_color,
121                 flag=get_flag(m),
122                 edge_color=common.RGBA(0.0, 0.0, 0.0, 1.0),
123                 edge_size=1.0,
124                 texture_index=get_texture_index(m.texture_file),
125                 sphere_texture_index=get_sphere_texture_index(m.texture_file),
126                 sphere_mode=get_sphere_texture_flag(m.texture_file),
127                 toon_sharing_flag=get_toon_shared_flag(m),
128                 toon_texture_index=get_toon_index(m),
129                 comment=common.unicode(""),
130                 vertex_count=m.vertex_count
131                 )
132             for i, m in enumerate(src.materials)]
133     # bones
134     ik_map={}
135     for ik in src.ik_list:
136         ik_map[ik.index]=ik
137     def is_connected(b):
138         if isinstance(b, pmd.Bone_Rolling):
139             return False
140         if isinstance(b, pmd.Bone_Tweak):
141             return False
142         return True
143     def is_rotatable(b):
144         if isinstance(b, pmd.Bone_Rotate):
145             return True
146         if isinstance(b, pmd.Bone_RotateMove):
147             return True
148         if isinstance(b, pmd.Bone_RotateInfl):
149             return True
150         if isinstance(b, pmd.Bone_IKRotateInfl):
151             return True
152         if isinstance(b, pmd.Bone_Rolling):
153             return True
154         if isinstance(b, pmd.Bone_IKTarget):
155             return True
156         if isinstance(b, pmd.Bone_IK):
157             return True
158         if isinstance(b, pmd.Bone_Unvisible):
159             return True
160         if isinstance(b, pmd.Bone_Tweak):
161             return True
162     def is_movable(b):
163         if isinstance(b, pmd.Bone_RotateMove):
164             return True
165         if isinstance(b, pmd.Bone_IK):
166             return True
167     def is_visible(b):
168         if isinstance(b, pmd.Bone_Unvisible):
169             return False
170         if isinstance(b, pmd.Bone_IKTarget):
171             return False
172         if isinstance(b, pmd.Bone_Tweak):
173             return False
174         return True
175     def is_manupilatable(b):
176         return True
177     def has_ik(b):
178         if isinstance(b, pmd.Bone_IK):
179             return True
180     def is_external_rotation(b):
181         if isinstance(b, pmd.Bone_RotateInfl):
182             return True
183         if isinstance(b, pmd.Bone_Tweak):
184             return True
185     def is_fixed_axis(b):
186         if isinstance(b, pmd.Bone_Rolling):
187             return True
188     def is_local_axis(b):
189         pass
190     def after_physics(b):
191         pass
192     def external_parent(b):
193         pass
194     def get_bone_flag(b):
195         return (
196                 (1 if is_connected(b) else 0)+
197                 (2 if is_rotatable(b) else 0)+
198                 (4 if is_movable(b) else 0)+
199                 (8 if is_visible(b) else 0)+
200
201                 (16 if is_manupilatable(b) else 0)+
202                 (32 if has_ik(b) else 0)+
203                 0+
204                 0+
205
206                 (256 if is_external_rotation(b) else 0)+
207                 0+
208                 (1024 if is_fixed_axis(b) else 0)+
209                 (2048 if is_local_axis(b) else 0)+
210
211                 (4096 if after_physics(b) else 0)+
212                 (8192 if external_parent(b) else 0)
213                 )
214     def get_tail_position(b):
215         return common.Vector3()
216     def get_tail_index(b):
217         if isinstance(b, pmd.Bone_Rolling):
218             return -1
219         if isinstance(b, pmd.Bone_IKTarget):
220             return -1
221         if isinstance(b, pmd.Bone_Unvisible):
222             return -1
223         if isinstance(b, pmd.Bone_Tweak):
224             return -1
225         return b.tail_index
226     def get_ik_link(bone_index):
227         b=src.bones[bone_index]
228         if b.english_name.find(b'knee')==-1:
229             return pmx.IkLink(
230                             bone_index, 0, 
231                             common.Vector3(), 
232                             common.Vector3())
233         else:
234             return pmx.IkLink(
235                             bone_index, 1, 
236                             common.Vector3(-3.1415927410125732, 0.0, 0.0), 
237                             common.Vector3(-0.00872664619237184524536132812500, 0.0, 0.0))
238     def get_ik(b):
239         if isinstance(b, pmd.Bone_IK):
240             ik=ik_map[b.index]
241             return pmx.Ik(
242                     ik.target, ik.iterations, ik.weight * 4, [
243                         get_ik_link(child) for child in ik.children ])
244         return None
245     def get_layer(b):
246         return 0
247     dst.bones=[
248             pmx.Bone(
249                 name=b.name.decode('cp932'),
250                 english_name=b.english_name.decode('cp932'),
251                 position=b.pos,
252                 parent_index=b.parent_index if b.parent_index!=65535 else -1,
253                 layer=get_layer(b),
254                 flag=get_bone_flag(b),
255                 tail_position=get_tail_position(b),
256                 tail_index=get_tail_index(b),
257                 effect_index=-1,
258                 effect_factor=0.0,
259                 fixed_axis=common.Vector3(),
260                 local_x_vector=common.Vector3(),
261                 local_z_vector=common.Vector3(),
262                 external_key=-1,
263                 ik=get_ik(b),
264                 )
265             for i, b in enumerate(src.bones)]
266     # bones
267     def get_panel(m):
268         return 1
269     if len(src.morphs)>0:
270         base=src.morphs[0]
271         assert(base.name==b"base")
272         dst.morphs=[
273                 pmx.Morph(
274                     name=m.name.decode('cp932'),
275                     english_name=m.english_name.decode('cp932'),
276                     panel=get_panel(m),
277                     morph_type=1,
278                     offsets=[pmx.VertexMorphOffset(base.indices[i], pos)
279                         for i, pos in zip(m.indices, m.pos_list)]
280                     )
281                 for i, m in enumerate(src.morphs) if m.name!=b"base"]
282     # display_slots
283     dst.display_slots=[
284             pmx.DisplaySlot(u('Root'), u('Root'), 1),
285             pmx.DisplaySlot(u('表情'), u('Exp'), 1)]+[
286                     pmx.DisplaySlot(
287                         name=g.name.strip().decode('cp932'),
288                         english_name=g.english_name.strip().decode('cp932'),
289                         special_flag=0)
290                     for i, g in enumerate(src.bone_group_list)]
291     # rigidbodies
292     dst.rigidbodies=[
293             pmx.RigidBody(
294                 name=r.name.decode("cp932"),
295                 english_name=u(""),
296                 bone_index=r.bone_index,
297                 collision_group=r.collision_group,
298                 no_collision_group=r.no_collision_group,
299                 shape_type=r.shape_type,
300                 shape_size=r.shape_size,
301                 shape_position=(r.shape_position+src.bones[0].pos if r.bone_index==-1 
302                     else r.shape_position+src.bones[r.bone_index].pos),
303                 shape_rotation=r.shape_rotation,
304                 mass=r.mass,
305                 linear_damping=r.linear_damping,
306                 angular_damping=r.angular_damping,
307                 restitution=r.restitution,
308                 friction=r.friction,
309                 mode=r.mode
310                 )
311             for i, r in enumerate(src.rigidbodies)]
312     # joints
313     dst.joints=[
314             pmx.Joint(
315                 j.name.decode('cp932'),
316                 u(""),
317                 0,
318                 j.rigidbody_index_a,
319                 j.rigidbody_index_b,
320                 j.position,
321                 j.rotation,
322                 j.translation_limit_min,
323                 j.translation_limit_max,
324                 j.rotation_limit_min,
325                 j.rotation_limit_max,
326                 j.spring_constant_translation,
327                 j.spring_constant_rotation
328                 )
329             for i, j in enumerate(src.joints)]
330     return dst
331