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()]
48 for ik in self.skeleton.ik_list:
50 solver.index=self.skeleton.getIndex(ik.target)
51 solver.target=self.skeleton.getIndex(ik.effector)
52 solver.length=ik.length
53 b=self.skeleton.bones[ik.effector.parent_index]
54 for i in range(solver.length):
55 solver.children.append(self.skeleton.getIndex(b))
56 b=self.skeleton.bones[b.parent_index]
57 solver.iterations=ik.iterations
58 solver.weight=ik.weight
59 model.ik_list.append(solver)
65 # convert right-handed z-up to left-handed y-up
66 position=common.Vector3(
67 b.pos[0] if not near(b.pos[0], 0) else 0,
68 b.pos[2] if not near(b.pos[2], 0) else 0,
69 b.pos[1] if not near(b.pos[1], 0) else 0
71 parent_index=b.parent_index,
75 tail_index=b.tail_index,
84 model.bones=[create_bone(b)
85 for b in ex.skeleton.bones]
88 def get_texture_name(texture):
89 pos=texture.replace("\\", "/").rfind("/")
93 return texture[pos+1:]
94 for m in ex.oneSkinMesh.vertexArray.indexArrays.keys():
95 for path in bl.material.eachEnalbeTexturePath(bl.material.get(m)):
96 textures.add(get_texture_name(path))
97 model.textures=list(textures)
100 vertexCount=ex.oneSkinMesh.getVertexCount()
101 for material_name, indices in ex.oneSkinMesh.vertexArray.each():
102 #print('material:', material_name)
104 m=bl.material.get(material_name)
105 except KeyError as e:
108 model.materials.append(pmx.Material(
111 diffuse_color=common.RGB(m.diffuse_color[0], m.diffuse_color[1], m.diffuse_color[2]),
113 specular_factor=0 if m.specular_toon_size<1e-5 else m.specular_hardness*10,
114 specular_color=common.RGB(m.specular_color[0], m.specular_color[1], m.specular_color[2]),
115 ambient_color=common.RGB(m.mirror_color[0], m.mirror_color[1], m.mirror_color[2]),
116 flag=1 if m.subsurface_scattering.use else 0,
117 edge_color=common.RGBA(0, 0, 0, 1),
120 sphere_texture_index=0,
123 toon_texture_index=0,
125 vertex_count=len(indices)
129 assert(i<vertexCount)
130 for i in range(0, len(indices), 3):
132 model.indices.append(indices[i+2])
133 model.indices.append(indices[i+1])
134 model.indices.append(indices[i])
137 for i, m in enumerate(ex.oneSkinMesh.morphList):
144 morph.offsets=[pmx.VertexMorphOffset(
146 common.Vector3(offset[0], offset[2], offset[1])
148 for index, offset in m.offsets]
152 model.display_slots=[pmx.DisplaySlot(
157 for name, members in ex.skeleton.bone_groups]
161 for i, b in enumerate(ex.skeleton.bones):
162 boneNameMap[b.name]=i
164 for i, obj in enumerate(ex.oneSkinMesh.rigidbodies):
165 name=obj[bl.RIGID_NAME] if bl.RIGID_NAME in obj else obj.name
168 boneIndex=boneNameMap[obj[bl.RIGID_BONE_NAME]]
171 bone=ex.skeleton.bones[0]
173 bone=ex.skeleton.bones[boneIndex]
174 if obj[bl.RIGID_SHAPE_TYPE]==0:
176 shape_size=common.Vector3(obj.scale[0], 0, 0)
177 elif obj[bl.RIGID_SHAPE_TYPE]==1:
179 shape_size=common.Vector3(obj.scale[0], obj.scale[1], obj.scale[2])
180 elif obj[bl.RIGID_SHAPE_TYPE]==2:
182 shape_size=common.Vector3(obj.scale[0], obj.scale[2], 0)
183 rigidBody=pmx.RigidBody(
186 collision_group=obj[bl.RIGID_GROUP],
187 no_collision_group=obj[bl.RIGID_INTERSECTION_GROUP],
188 bone_index=boneIndex,
189 shape_position=common.Vector3(
190 obj.location.x-bone.pos[0],
191 obj.location.z-bone.pos[2],
192 obj.location.y-bone.pos[1]),
193 shape_rotation=common.Vector3(
194 -obj.rotation_euler[0],
195 -obj.rotation_euler[2],
196 -obj.rotation_euler[1]),
197 shape_type=shape_type,
198 shape_size=shape_size,
199 mass=obj[bl.RIGID_WEIGHT],
200 linear_damping=obj[bl.RIGID_LINEAR_DAMPING],
201 angular_damping=obj[bl.RIGID_ANGULAR_DAMPING],
202 restitution=obj[bl.RIGID_RESTITUTION],
203 friction=obj[bl.RIGID_FRICTION],
204 mode=obj[bl.RIGID_PROCESS_TYPE]
206 model.rigidbodies.append(rigidBody)
209 model.joints=[pmx.Joint(
210 name=obj[bl.CONSTRAINT_NAME],
213 rigidbody_index_a=rigidNameMap[obj[bl.CONSTRAINT_A]],
214 rigidbody_index_b=rigidNameMap[obj[bl.CONSTRAINT_B]],
215 position=common.Vector3(
219 rotation=common.Vector3(
220 -obj.rotation_euler[0],
221 -obj.rotation_euler[2],
222 -obj.rotation_euler[1]),
223 translation_limit_min=common.Vector3(
224 obj[bl.CONSTRAINT_POS_MIN][0],
225 obj[bl.CONSTRAINT_POS_MIN][1],
226 obj[bl.CONSTRAINT_POS_MIN][2]
228 translation_limit_max=common.Vector3(
229 obj[bl.CONSTRAINT_POS_MAX][0],
230 obj[bl.CONSTRAINT_POS_MAX][1],
231 obj[bl.CONSTRAINT_POS_MAX][2]
233 rotation_limit_min=common.Vector3(
234 obj[bl.CONSTRAINT_ROT_MIN][0],
235 obj[bl.CONSTRAINT_ROT_MIN][1],
236 obj[bl.CONSTRAINT_ROT_MIN][2]),
237 rotation_limit_max=common.Vector3(
238 obj[bl.CONSTRAINT_ROT_MAX][0],
239 obj[bl.CONSTRAINT_ROT_MAX][1],
240 obj[bl.CONSTRAINT_ROT_MAX][2]),
241 spring_constant_translation=common.Vector3(
242 obj[bl.CONSTRAINT_SPRING_POS][0],
243 obj[bl.CONSTRAINT_SPRING_POS][1],
244 obj[bl.CONSTRAINT_SPRING_POS][2]),
245 spring_constant_rotation=common.Vector3(
246 obj[bl.CONSTRAINT_SPRING_ROT][0],
247 obj[bl.CONSTRAINT_SPRING_ROT][1],
248 obj[bl.CONSTRAINT_SPRING_ROT][2])
250 for obj in ex.oneSkinMesh.constraints]
255 def _execute(filepath):
256 active=bl.object.getActive()
258 print("abort. no active object.")
261 ex=exporter.Exporter()
265 bl.object.activate(active)
266 with io.open(filepath, 'wb') as f:
267 writer.write(f, model)