9 from .pymeshio import pmx
10 from .pymeshio.pmx import reader
13 def convert_coord(pos):
15 Left handed y-up to Right handed z-up
17 return (pos.x, pos.z, pos.y)
19 def __create_a_material(m, name, textures_and_images):
29 list of (texture, image)
31 material = bl.material.create(name)
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
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)
41 material.mirror_color=[m.ambient_color.r, m.ambient_color.g, m.ambient_color.b]
47 material.preview_render_type='FLAT'
48 material.use_transparency=True
50 if m.texture_index!=-1:
51 bl.material.addTexture(material, textures_and_images[m.texture_index][0])
54 def __create_armature(bones, display_slots):
60 list of pymeshio.pmx.Bone
62 armature, armature_object=bl.armature.create()
65 bl.armature.makeEditable(armature_object)
67 bone=bl.armature.createBone(armature, b.name)
69 bone.head=bl.createVector(*convert_coord(b.position))
70 if not b.getConnectionFlag():
71 bone.tail=bl.createVector(*convert_coord(b.position))
72 elif not b.getVisibleFlag():
73 bone.tail=bone.head+bl.createVector(0, 1, 0)
76 bl_bones=[create_bone(b) for b in bones]
79 for b, bone in zip(bones, bl_bones):
80 assert(b.name==bone.name)
81 if b.parent_index!=-1:
82 print("%s -> %s" % (bones[b.parent_index].name, b.name))
83 parent_bone=bl_bones[b.parent_index]
84 bone.parent=parent_bone
85 if b.getConnectionFlag() and b.tail_index!=-1:
86 assert(b.tail_index!=0)
87 tail_bone=bl_bones[b.tail_index]
88 bone.tail=tail_bone.head
89 bl.bone.setConnected(tail_bone)
91 print("no parent %s" % b.name)
92 bl.armature.update(armature)
94 # create ik constraint
96 pose = bl.object.getPose(armature_object)
97 for b, bone in zip(bones, bl_bones):
100 assert(len(ik.link)<16)
101 p_bone=pose.bones[bones[ik.target_index].name]
103 constraint=bl.armature.createIkConstraint(
104 armature_object, p_bone, bone.name,
105 ik.link, ik.limit_radian, ik.loop)
106 bl.armature.makeEditable(armature_object)
107 bl.armature.update(armature)
111 pose = bl.object.getPose(armature_object)
112 for i, ds in enumerate(display_slots):
114 g=bl.object.createBoneGroup(armature_object, ds.name, "THEME%02d" % (i+1))
115 for t, index in ds.references:
117 name=bones[index].name
119 pose.bones[name].bone_group=g
120 except KeyError as e:
121 print("pose %s is not found" % name)
124 return armature_object
126 def _execute(filepath):
130 bl.progress_set('load %s' % filepath, 0.0)
133 model=reader.read_from_file(filepath)
135 print("fail to load %s" % filepath)
138 bl.progress_set('loaded', 0.1)
140 # メッシュをまとめるエンプティオブジェクト
141 model_name=model.english_name
142 if len(model_name)==0:
143 model_name=os.path.basename(filepath)
144 root_object=bl.object.createEmpty(model_name)
145 root_object[bl.MMD_MB_NAME]=model.name
146 root_object[bl.MMD_MB_COMMENT]=model.comment
147 root_object[bl.MMD_COMMENT]=model.english_comment
150 armature_object=__create_armature(model.bones, model.display_slots)
152 bl.object.makeParent(root_object, armature_object)
155 texture_dir=os.path.dirname(filepath)
156 textures_and_images=[bl.texture.create(os.path.join(texture_dir, t))
157 for t in model.textures]
158 print(textures_and_images)
160 index_generator=(i for i in model.indices)
161 # 頂点配列。(Left handed y-up) to (Right handed z-up)
162 vertices=[convert_coord(pos)
163 for pos in (v.position for v in model.vertices)]
166 def get_object_name(index, name):
170 len_list=[len(name[:i].encode('utf-8')) for i in range(1, len(name)+1, 1)]
172 for str_len in len_list:
173 if str_len<18: # 21-3
177 name="{0:02}:{1}".format(index, name[:letter_count])
178 print("%s(%d)" % (name, letter_count))
180 for i, m in enumerate(model.materials):
183 material=__create_a_material(m, m.name, textures_and_images)
184 # object名はutf-8で21byteまで
185 mesh, mesh_object=bl.mesh.create(get_object_name(i, m.name))
186 bl.mesh.addMaterial(mesh, material)
188 bl.object.deselectAll()
189 bl.object.activate(mesh_object)
190 bl.object.makeParent(root_object, mesh_object)
192 indices=[next(index_generator)
193 for _ in range(m.vertex_count)]
194 bl.mesh.addGeometry(mesh, vertices,
195 [(indices[i], indices[i+1], indices[i+2])
196 for i in range(0, len(indices), 3)])
197 assert(len(model.vertices), len(mesh.vertices))
201 hasTexture=bl.material.hasTexture(material)
203 index_gen=(i for i in indices)
204 image=(textures_and_images.get[m.texture_index]
205 if m.texture_index in textures_and_images
207 for i, face in enumerate(mesh.faces):
208 bl.face.setMaterial(face, 0)
210 uv0=model.vertices[next(index_gen)].uv
211 uv1=model.vertices[next(index_gen)].uv
212 uv2=model.vertices[next(index_gen)].uv
213 bl.mesh.setFaceUV(mesh, i, face, [# fix uv
222 bl.modifier.addArmature(mesh_object, armature_object)
223 # set vertex attributes(normal, bone weights)
224 bl.mesh.useVertexUV(mesh)
225 for i, (v, mvert) in enumerate(zip(model.vertices, mesh.vertices)):
226 bl.vertex.setNormal(mvert, convert_coord(v.normal))
227 if isinstance(v.deform, pmx.Bdef1):
228 bl.object.assignVertexGroup(mesh_object,
229 model.bones[v.deform.index0].name, i, 1.0)
230 elif isinstance(v.deform, pmx.Bdef2):
231 bl.object.assignVertexGroup(mesh_object,
232 model.bones[v.deform.index0].name, i, v.deform.weight0)
233 bl.object.assignVertexGroup(mesh_object,
234 model.bones[v.deform.index1].name, i, 1.0-v.deform.weight0)
236 raise Exception("unknown deform: %s" % v.deform)
239 bl.object.pinShape(mesh_object, True)
241 baseShapeBlock=bl.object.addShapeKey(mesh_object, bl.BASE_SHAPE_NAME)
243 for m in model.morphs:
244 new_shape_key=bl.object.addShapeKey(mesh_object, m.name)
246 if isinstance(o, pmx.VertexMorphOffset):
247 bl.shapekey.assign(new_shape_key,
249 mesh.vertices[o.vertex_index].co+
250 bl.createVector(*convert_coord(o.position_offset)))
252 raise Exception("unknown morph type: %s" % o)
254 bl.object.setActivateShapeKey(mesh_object, 0)