6 from .pymeshio import pmx
7 from .pymeshio import common
8 from .pymeshio.pmx import writer
11 def near(x, y, EPSILON=1e-5):
13 return d>=-EPSILON and d<=EPSILON
20 model.english_name=o.name
21 model.name=o[bl.MMD_MB_NAME] if bl.MMD_MB_NAME in o else 'Blenderエクスポート'
22 model.comment=o[bl.MMD_MB_COMMENT] if bl.MMD_MB_COMMENT in o else 'Blnderエクスポート\n'
23 model.english_comment=o[bl.MMD_COMMENT] if bl.MMD_COMMENT in o else 'blender export\n'
25 def get_deform(b0, b1, weight):
27 return pmx.Bdef1(b1, weight)
29 return pmx.Bdef1(b0, weight)
31 return pmx.Bdef2(b0, b1, weight)
33 model.vertices=[pmx.Vertex(
34 # convert right-handed z-up to left-handed y-up
35 common.Vector3(pos[0], pos[2], pos[1]),
36 # convert right-handed z-up to left-handed y-up
37 common.Vector3(attribute.nx, attribute.nz, attribute.ny),
39 common.Vector2(attribute.u, 1.0-attribute.v),
40 get_deform(ex.skeleton.indexByName(b0), ex.skeleton.indexByName(b1), weight),
41 # edge flag, 0: enable edge, 1: not edge
44 for pos, attribute, b0, b1, weight in ex.oneSkinMesh.vertexArray.zip()]
50 # convert right-handed z-up to left-handed y-up
51 position=common.Vector3(
52 b.pos[0] if not near(b.pos[0], 0) else 0,
53 b.pos[2] if not near(b.pos[2], 0) else 0,
54 b.pos[1] if not near(b.pos[1], 0) else 0
56 parent_index=b.parent_index,
60 tail_index=b.tail_index,
69 model.bones=[create_bone(b)
70 for b in ex.skeleton.bones]
75 for ik in self.skeleton.ik_list:
77 solver.index=self.skeleton.getIndex(ik.target)
78 solver.target=self.skeleton.getIndex(ik.effector)
79 solver.length=ik.length
80 b=self.skeleton.bones[ik.effector.parent_index]
81 for i in range(solver.length):
82 solver.children.append(self.skeleton.getIndex(b))
83 b=self.skeleton.bones[b.parent_index]
84 solver.iterations=ik.iterations
85 solver.weight=ik.weight
86 model.ik_list.append(solver)
89 vertexCount=self.oneSkinMesh.getVertexCount()
90 for material_name, indices in self.oneSkinMesh.vertexArray.each():
91 #print('material:', material_name)
93 m=bl.material.get(material_name)
96 def get_texture_name(texture):
97 pos=texture.replace("\\", "/").rfind("/")
101 return texture[pos+1:]
102 textures=[get_texture_name(path)
103 for path in bl.material.eachEnalbeTexturePath(m)]
106 model.materials.append(pmd.Material(
108 common.RGB(m.diffuse_color[0], m.diffuse_color[1], m.diffuse_color[2]),
111 0 if m.specular_toon_size<1e-5 else m.specular_hardness*10,
113 common.RGB(m.specular_color[0], m.specular_color[1], m.specular_color[2]),
115 common.RGB(m.mirror_color[0], m.mirror_color[1], m.mirror_color[2]),
117 1 if m.subsurface_scattering.use else 0,
123 ('*'.join(textures) if len(textures)>0 else "").encode('cp932')
127 assert(i<vertexCount)
128 for i in range(0, len(indices), 3):
130 model.indices.append(indices[i])
131 model.indices.append(indices[i+1])
132 model.indices.append(indices[i+2])
135 for i, m in enumerate(self.oneSkinMesh.morphList):
136 v=englishmap.getUnicodeSkinName(m.name)
138 v=[m.name, m.name, 0]
141 morph=pmd.Morph(v[1].encode("cp932"))
142 morph.english_name=m.name.encode("cp932")
145 for index, offset in m.offsets:
146 # convert right-handed z-up to left-handed y-up
147 morph.append(index, offset[0], offset[2], offset[1])
148 morph.vertex_count=len(m.offsets)
152 for i, m in enumerate(self.oneSkinMesh.morphList):
154 model.morph_indices.append(i)
155 for i, m in enumerate(self.oneSkinMesh.morphList):
157 model.morph_indices.append(i)
158 for i, m in enumerate(self.oneSkinMesh.morphList):
160 model.morph_indices.append(i)
161 for i, m in enumerate(self.oneSkinMesh.morphList):
163 model.morph_indices.append(i)
166 for g in self.skeleton.bone_groups:
167 name=englishmap.getUnicodeBoneGroupName(g[0])
172 model.bone_group_list.append(pmd.BoneGroup(
173 (name+'\n').encode('cp932'),
174 (englishName+'\n').encode('cp932')
178 for i, b in enumerate(self.skeleton.bones):
183 model.bone_display_list.append((i, self.skeleton.getBoneGroup(b)))
186 model.english_name=self.englishName.encode('cp932')
187 model.english_comment=self.englishComment.encode('cp932')
191 for o in bl.object.each():
193 if o.name.startswith(bl.TOON_TEXTURE_OBJECT):
199 toonMesh=bl.object.getData(toonMeshObject)
200 toonMaterial=bl.mesh.getMaterial(toonMesh, 0)
202 t=bl.material.getTexture(toonMaterial, i)
204 model.toon_textures[i]=("%s" % t.name).encode('cp932')
206 model.toon_textures[i]=("toon%02d.bmp" % (i+1)).encode('cp932')
209 model.toon_textures[i]=("toon%02d.bmp" % (i+1)).encode('cp932')
213 for i, b in enumerate(self.skeleton.bones):
214 boneNameMap[b.name]=b
216 for i, obj in enumerate(self.oneSkinMesh.rigidbodies):
217 name=obj[bl.RIGID_NAME] if bl.RIGID_NAME in obj else obj.name
220 boneIndex=boneNameMap[obj[bl.RIGID_BONE_NAME]]
223 bone=self.skeleton.bones[0]
225 bone=self.skeleton.bones[boneIndex]
226 if obj[bl.RIGID_SHAPE_TYPE]==0:
227 shape_type=pmd.SHAPE_SPHERE
228 shape_size=common.Vector3(obj.scale[0], 0, 0)
229 elif obj[bl.RIGID_SHAPE_TYPE]==1:
230 shape_type=pmd.SHAPE_BOX
231 shape_size=common.Vector3(obj.scale[0], obj.scale[1], obj.scale[2])
232 elif obj[bl.RIGID_SHAPE_TYPE]==2:
233 shape_type=pmd.SHAPE_CAPSULE
234 shape_size=common.Vector3(obj.scale[0], obj.scale[2], 0)
235 rigidBody=pmd.RigidBody(
236 name.encode('cp932'),
237 collision_group=obj[bl.RIGID_GROUP],
238 no_collision_group=obj[bl.RIGID_INTERSECTION_GROUP],
239 bone_index=boneIndex,
240 shape_position=common.Vector3(
241 obj.location.x-bone.pos[0],
242 obj.location.z-bone.pos[2],
243 obj.location.y-bone.pos[1]),
244 shape_rotation=common.Vector3(
245 -obj.rotation_euler[0],
246 -obj.rotation_euler[2],
247 -obj.rotation_euler[1]),
248 shape_type=shape_type,
249 shape_size=shape_size,
250 mass=obj[bl.RIGID_WEIGHT],
251 linear_damping=obj[bl.RIGID_LINEAR_DAMPING],
252 angular_damping=obj[bl.RIGID_ANGULAR_DAMPING],
253 restitution=obj[bl.RIGID_RESTITUTION],
254 friction=obj[bl.RIGID_FRICTION],
255 mode=obj[bl.RIGID_PROCESS_TYPE]
257 model.rigidbodies.append(rigidBody)
260 model.joints=[pmd.Joint(
261 name=obj[bl.CONSTRAINT_NAME].encode('cp932'),
262 rigidbody_index_a=rigidNameMap[obj[bl.CONSTRAINT_A]],
263 rigidbody_index_b=rigidNameMap[obj[bl.CONSTRAINT_B]],
264 position=common.Vector3(
268 rotation=common.Vector3(
269 -obj.rotation_euler[0],
270 -obj.rotation_euler[2],
271 -obj.rotation_euler[1]),
272 translation_limit_min=common.Vector3(
273 obj[bl.CONSTRAINT_POS_MIN][0],
274 obj[bl.CONSTRAINT_POS_MIN][1],
275 obj[bl.CONSTRAINT_POS_MIN][2]
277 translation_limit_max=common.Vector3(
278 obj[bl.CONSTRAINT_POS_MAX][0],
279 obj[bl.CONSTRAINT_POS_MAX][1],
280 obj[bl.CONSTRAINT_POS_MAX][2]
282 rotation_limit_min=common.Vector3(
283 obj[bl.CONSTRAINT_ROT_MIN][0],
284 obj[bl.CONSTRAINT_ROT_MIN][1],
285 obj[bl.CONSTRAINT_ROT_MIN][2]),
286 rotation_limit_max=common.Vector3(
287 obj[bl.CONSTRAINT_ROT_MAX][0],
288 obj[bl.CONSTRAINT_ROT_MAX][1],
289 obj[bl.CONSTRAINT_ROT_MAX][2]),
290 spring_constant_translation=common.Vector3(
291 obj[bl.CONSTRAINT_SPRING_POS][0],
292 obj[bl.CONSTRAINT_SPRING_POS][1],
293 obj[bl.CONSTRAINT_SPRING_POS][2]),
294 spring_constant_rotation=common.Vector3(
295 obj[bl.CONSTRAINT_SPRING_ROT][0],
296 obj[bl.CONSTRAINT_SPRING_ROT][1],
297 obj[bl.CONSTRAINT_SPRING_ROT][2])
299 for obj in self.oneSkinMesh.constraints]
302 bl.message('write: %s' % path)
303 return writer.write(io.open(path, 'wb'), model)
306 def _execute(filepath):
307 active=bl.object.getActive()
309 print("abort. no active object.")
312 ex=exporter.Exporter()
316 bl.object.activate(active)
317 with io.open(filepath, 'wb') as f:
318 writer.write(f, model)