OSDN Git Service

implementing import_pmx...
[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):
52     """
53     armatureを作成する
54
55     :Params:
56         bones
57             list of pymeshio.pmx.Bone
58     """
59     armature, armature_object=bl.armature.create()
60
61     bl.armature.makeEditable(armature_object)
62     # create bones
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         if b.parent_index!=-1:
78             print("%s -> %s" % (bones[b.parent_index].name, b.name))
79             parent_bone=bl_bones[b.parent_index]
80             bone.parent=parent_bone
81             if b.getConnectionFlag() and b.tail_index!=-1:
82                 assert(b.tail_index!=0)
83                 tail_bone=bl_bones[b.tail_index]
84                 bone.tail=tail_bone.head
85                 bl.bone.setConnected(tail_bone)
86         else:
87             print("no parent %s" % b.name)
88
89     # fix
90     bl.armature.update(armature)
91     bl.enterObjectMode()
92
93     return armature_object
94
95 def _execute(filepath):
96     """
97     importerr 本体
98     """
99     bl.progress_set('load %s' % filepath, 0.0)
100     print(filepath)
101
102     from .pymeshio.pmx import reader
103     model=reader.read_from_file(filepath)
104     if not model:
105         print("fail to load %s" % filepath)
106         return
107     print(model)
108     bl.progress_set('loaded', 0.1)
109
110     # メッシュをまとめるエンプティオブジェクト
111     model_name=model.english_name
112     if len(model_name)==0:
113         model_name=os.path.basename(filepath)
114     root_object=bl.object.createEmpty(model_name)
115     root_object[bl.MMD_MB_NAME]=model.name
116     root_object[bl.MMD_MB_COMMENT]=model.comment
117     root_object[bl.MMD_COMMENT]=model.english_comment
118
119     # armatureを作る
120     armature_object=__create_armature(model.bones)
121     if armature_object:
122         bl.object.makeParent(root_object, armature_object)
123
124     # テクスチャを作る
125     texture_dir=os.path.dirname(filepath)
126     textures_and_images=[bl.texture.create(os.path.join(texture_dir, t))
127             for t in model.textures]
128     print(textures_and_images)
129
130     def get_name(name, fmt, *args):
131         if len(name.encode("utf-8"))<16:
132             return name
133         else:
134             return fmt.format(*args)
135     index_generator=(i for i in model.indices)
136     # 頂点配列。(Left handed y-up) to (Right handed z-up)
137     vertices=[convert_coord(pos)
138             for pos in (v.position for v in model.vertices)]
139     for i, m in enumerate(model.materials):
140         # マテリアル毎にメッシュを作成する
141         print(m.name)
142         #material=__create_a_material(m, get_name(m.name, "material:{0:02}", i), textures_and_images)
143         material=__create_a_material(m, m.name, textures_and_images)
144         mesh, mesh_object=bl.mesh.create("object:{0:02}".format(i))
145         bl.mesh.addMaterial(mesh, material)
146         # activate object
147         bl.object.deselectAll()
148         bl.object.activate(mesh_object)
149         bl.object.makeParent(root_object, mesh_object)
150         # vertices & faces
151         indices=[next(index_generator)
152                     for _ in range(m.vertex_count)]
153         bl.mesh.addGeometry(mesh, vertices,
154                 [(indices[i], indices[i+1], indices[i+2])
155                     for i in range(0, len(indices), 3)])
156         if armature_object:
157             # armature modifirer
158             bl.modifier.addArmature(mesh_object, armature_object)
159
160         # shape
161
162
163     return {'FINISHED'}
164