OSDN Git Service

pmx bug fix
[meshio/pymeshio.git] / blender26-meshio / import_pmx.py
1 # coding: utf-8
2 """
3 PMXモデルをインポートする。
4
5 1マテリアル、1オブジェクトで作成する。
6 """
7 import os
8 from . import bl
9
10
11 def convert_coord(pos):
12     """
13     Left handed y-up to Right handed z-up
14     """
15     return (pos.x, pos.z, pos.y)
16
17 def __create_a_material(m, name, textures_and_images):
18     """
19     materialを作成する
20
21     :Params:
22         m
23             pymeshio.pmx.Material
24         name
25             material name
26         textures_and_images
27             list of (texture, image)
28     """
29     material = bl.material.create(name)
30     # diffuse
31     material.diffuse_shader='FRESNEL'
32     material.diffuse_color=[m.diffuse_color.r, m.diffuse_color.g, m.diffuse_color.b]
33     material.alpha=m.alpha
34     # specular
35     material.specular_shader='TOON'
36     material.specular_color=[m.specular_color.r, m.specular_color.g, m.specular_color.b]
37     material.specular_toon_size=int(m.specular_factor)
38     # ambient
39     material.mirror_color=[m.ambient_color.r, m.ambient_color.g, m.ambient_color.b]
40     # todo
41     # flag
42     # edge_color
43     # edge_size
44     # other
45     material.preview_render_type='FLAT'
46     material.use_transparency=True
47     # texture
48     texture_index=bl.material.addTexture(material, textures_and_images[m.texture_index][0])
49     return material
50
51 def __create_armature(bones, display_slots):
52     """
53     armatureを作成する
54
55     :Params:
56         bones
57             list of pymeshio.pmx.Bone
58     """
59     armature, armature_object=bl.armature.create()
60
61     # create bones
62     bl.armature.makeEditable(armature_object)
63     def create_bone(b):
64         bone=bl.armature.createBone(armature, b.name)
65         # bone position
66         bone.head=bl.createVector(*convert_coord(b.position))
67         if not b.getConnectionFlag():
68             bone.tail=bl.createVector(*convert_coord(b.position))
69         elif not b.getVisibleFlag():
70             bone.tail=bone.head+bl.createVector(0, 1, 0)
71
72         return bone
73     bl_bones=[create_bone(b) for b in bones]
74
75     # build skeleton
76     for b, bone in zip(bones, bl_bones):
77         assert(b.name==bone.name)
78         if b.parent_index!=-1:
79             print("%s -> %s" % (bones[b.parent_index].name, b.name))
80             parent_bone=bl_bones[b.parent_index]
81             bone.parent=parent_bone
82             if b.getConnectionFlag() and b.tail_index!=-1:
83                 assert(b.tail_index!=0)
84                 tail_bone=bl_bones[b.tail_index]
85                 bone.tail=tail_bone.head
86                 bl.bone.setConnected(tail_bone)
87         else:
88             print("no parent %s" % b.name)
89     bl.armature.update(armature)
90
91     # create ik constraint
92     bl.enterObjectMode()
93     pose = bl.object.getPose(armature_object)
94     for b, bone in zip(bones, bl_bones):
95         if b.getIkFlag():
96             ik=b.ik
97             assert(len(ik.link)<16)
98             p_bone=pose.bones[bones[ik.target_index].name]
99             assert(p_bone)
100             constraint=bl.armature.createIkConstraint(
101                     armature_object, p_bone, bone.name,
102                     ik.link, ik.limit_radian, ik.loop)
103     bl.armature.makeEditable(armature_object)
104     bl.armature.update(armature)
105
106     # create bone group
107     bl.enterObjectMode()
108     pose = bl.object.getPose(armature_object)
109     for i, ds in enumerate(display_slots):
110         print(ds)
111         g=bl.object.createBoneGroup(armature_object, ds.name, "THEME%02d" % (i+1))
112         for t, index in ds.references:
113             if t==0:
114                 name=bones[index].name
115                 try:
116                     pose.bones[name].bone_group=g
117                 except KeyError as e:
118                     print("pose %s is not found" % name)
119
120     bl.enterObjectMode()
121     return armature_object
122
123 def _execute(filepath):
124     """
125     importerr 本体
126     """
127     bl.progress_set('load %s' % filepath, 0.0)
128     print(filepath)
129
130     from .pymeshio.pmx import reader
131     model=reader.read_from_file(filepath)
132     if not model:
133         print("fail to load %s" % filepath)
134         return
135     print(model)
136     bl.progress_set('loaded', 0.1)
137
138     # メッシュをまとめるエンプティオブジェクト
139     model_name=model.english_name
140     if len(model_name)==0:
141         model_name=os.path.basename(filepath)
142     root_object=bl.object.createEmpty(model_name)
143     root_object[bl.MMD_MB_NAME]=model.name
144     root_object[bl.MMD_MB_COMMENT]=model.comment
145     root_object[bl.MMD_COMMENT]=model.english_comment
146
147     # armatureを作る
148     armature_object=__create_armature(model.bones, model.display_slots)
149     if armature_object:
150         bl.object.makeParent(root_object, armature_object)
151
152     # テクスチャを作る
153     texture_dir=os.path.dirname(filepath)
154     textures_and_images=[bl.texture.create(os.path.join(texture_dir, t))
155             for t in model.textures]
156     print(textures_and_images)
157
158     def get_name(name, fmt, *args):
159         if len(name.encode("utf-8"))<16:
160             return name
161         else:
162             return fmt.format(*args)
163     index_generator=(i for i in model.indices)
164     # 頂点配列。(Left handed y-up) to (Right handed z-up)
165     vertices=[convert_coord(pos)
166             for pos in (v.position for v in model.vertices)]
167     for i, m in enumerate(model.materials):
168         # マテリアル毎にメッシュを作成する
169         print(m.name)
170         #material=__create_a_material(m, get_name(m.name, "material:{0:02}", i), textures_and_images)
171         material=__create_a_material(m, m.name, textures_and_images)
172         mesh, mesh_object=bl.mesh.create("object:{0:02}".format(i))
173         bl.mesh.addMaterial(mesh, material)
174         # activate object
175         bl.object.deselectAll()
176         bl.object.activate(mesh_object)
177         bl.object.makeParent(root_object, mesh_object)
178         # vertices & faces
179         indices=[next(index_generator)
180                     for _ in range(m.vertex_count)]
181         bl.mesh.addGeometry(mesh, vertices,
182                 [(indices[i], indices[i+1], indices[i+2])
183                     for i in range(0, len(indices), 3)])
184         if armature_object:
185             # armature modifirer
186             bl.modifier.addArmature(mesh_object, armature_object)
187
188         # shape
189
190
191     return {'FINISHED'}
192