OSDN Git Service

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