3 from . import vertexarray
5 from ..pymeshio import englishmap
9 __slots__=['name', 'type', 'offsets']
10 def __init__(self, name, type):
15 def add(self, index, offset):
16 self.offsets.append((index, offset))
19 self.offsets.sort(key=lambda e: e[0])
22 return "<Morph %s>" % self.name
30 class DefaultMatrial(object):
34 self.diffuse_color=[1, 1, 1]
37 self.specular_toon_size=0
38 self.specular_hardness=5
39 self.specular_color=[1, 1, 1]
41 self.mirror_color=[1, 1, 1]
43 self.subsurface_scattering=SSS()
48 class OneSkinMesh(object):
49 __slots__=['vertexArray', 'morphList', 'rigidbodies', 'constraints', 'armatureObj']
51 self.vertexArray=vertexarray.VertexArray()
58 return "<OneSkinMesh %s, morph:%d>" % (
62 def build(self, node):
63 ############################################################
64 # search armature modifier
65 ############################################################
66 for m in node.o.modifiers:
67 if bl.modifier.isType(m, 'ARMATURE'):
68 armatureObj=bl.modifier.getArmatureObject(m)
69 if not self.armatureObj:
70 self.armatureObj=armatureObj
71 elif self.armatureObj!=armatureObj:
72 print("warning! found multiple armature. ignored.",
75 if node.o.type.upper()=='MESH':
78 for child in node.children:
81 def addMesh(self, obj):
82 if not bl.object.isVisible(obj):
87 self.__constraint(obj)
89 def __getWeightMap(self, obj, mesh):
93 def setWeight(i, name, w):
96 if i in secondWeightMap:
98 if w<secondWeightMap[i][1]:
100 elif w<weightMap[i][1]:
102 secondWeightMap[i]=(name, w)
105 weightMap[i]=(name, w)
107 if w>weightMap[i][1]:
109 secondWeightMap[i]=weightMap[i]
110 weightMap[i]=(name, w)
112 secondWeightMap[i]=(name, w)
114 weightMap[i]=(name, w)
116 # ToDo bone weightと関係ないvertex groupを除外する
117 for i, v in enumerate(mesh.vertices):
120 setWeight(i, obj.vertex_groups[g.group].name, g.weight)
123 setWeight(i, obj.vertex_groups[0].name, 1)
129 for i in range(len(mesh.vertices)):
130 if i in secondWeightMap:
131 secondWeightMap[i]=(secondWeightMap[i][0], 1.0-weightMap[i][1])
133 weightMap[i]=(weightMap[i][0], 1.0)
134 secondWeightMap[i]=("", 0)
136 print("no weight vertex")
138 secondWeightMap[i]=("", 0)
140 return weightMap, secondWeightMap
142 def __processFaces(self, obj_name, mesh, weightMap, secondWeightMap):
143 default_material=DefaultMatrial()
145 for i, face in enumerate(mesh.faces):
146 faceVertexCount=bl.face.getVertexCount(face)
148 material=mesh.materials[bl.face.getMaterialIndex(face)]
149 except IndexError as e:
150 material=default_material
151 v=[mesh.vertices[index] for index in bl.face.getVertices(face)]
152 uv=bl.mesh.getFaceUV(
153 mesh, i, face, bl.face.getVertexCount(face))
155 if faceVertexCount==3:
157 self.vertexArray.addTriangle(
158 obj_name, material.name,
165 bl.vertex.getNormal(v[2]),
166 bl.vertex.getNormal(v[1]),
167 bl.vertex.getNormal(v[0]),
171 weightMap[v[2].index][0],
172 weightMap[v[1].index][0],
173 weightMap[v[0].index][0],
174 secondWeightMap[v[2].index][0],
175 secondWeightMap[v[1].index][0],
176 secondWeightMap[v[0].index][0],
177 weightMap[v[2].index][1],
178 weightMap[v[1].index][1],
179 weightMap[v[0].index][1]
181 elif faceVertexCount==4:
183 self.vertexArray.addTriangle(
184 obj_name, material.name,
191 bl.vertex.getNormal(v[2]),
192 bl.vertex.getNormal(v[1]),
193 bl.vertex.getNormal(v[0]),
197 weightMap[v[2].index][0],
198 weightMap[v[1].index][0],
199 weightMap[v[0].index][0],
200 secondWeightMap[v[2].index][0],
201 secondWeightMap[v[1].index][0],
202 secondWeightMap[v[0].index][0],
203 weightMap[v[2].index][1],
204 weightMap[v[1].index][1],
205 weightMap[v[0].index][1]
207 self.vertexArray.addTriangle(
208 obj_name, material.name,
215 bl.vertex.getNormal(v[0]),
216 bl.vertex.getNormal(v[3]),
217 bl.vertex.getNormal(v[2]),
221 weightMap[v[0].index][0],
222 weightMap[v[3].index][0],
223 weightMap[v[2].index][0],
224 secondWeightMap[v[0].index][0],
225 secondWeightMap[v[3].index][0],
226 secondWeightMap[v[2].index][0],
227 weightMap[v[0].index][1],
228 weightMap[v[3].index][1],
229 weightMap[v[2].index][1]
232 def __mesh(self, obj):
233 if bl.RIGID_SHAPE_TYPE in obj:
235 if bl.CONSTRAINT_A in obj:
238 bl.message("export: %s" % obj.name)
240 # メッシュのコピーを生成してオブジェクトの行列を適用する
241 copyMesh, copyObj=bl.object.duplicate(obj)
242 if len(copyMesh.vertices)>0:
247 copyObj.scale=obj.scale
248 bpy.ops.object.transform_apply(scale=True)
249 copyObj.rotation_euler=obj.rotation_euler
250 bpy.ops.object.transform_apply(rotation=True)
251 copyObj.location=obj.location
252 bpy.ops.object.transform_apply(location=True)
253 except AttributeError as e:
255 copyObj.scale=obj.scale
256 bpy.ops.object.scale_apply()
257 copyObj.rotation_euler=obj.rotation_euler
258 bpy.ops.object.rotation_apply()
259 copyObj.location=obj.location
260 bpy.ops.object.location_apply()
262 copyMesh.transform(obj.matrix_world)
265 for m in [m for m in copyObj.modifiers]:
266 if m.type=='SOLIDFY':
268 elif m.type=='ARMATURE':
270 elif m.type=='MIRROR':
271 bpy.ops.object.modifier_apply(modifier=m.name)
275 weightMap, secondWeightMap=self.__getWeightMap(copyObj, copyMesh)
276 self.__processFaces(obj.name, copyMesh, weightMap, secondWeightMap)
277 bl.object.delete(copyObj)
279 def createEmptyBasicSkin(self):
280 self.__getOrCreateMorph('base', 0)
282 def __skin(self, obj):
283 if not bl.object.hasShapeKey(obj):
287 blenderMesh=bl.object.getData(obj)
291 vg=bl.object.getVertexGroup(obj, bl.MMD_SHAPE_GROUP_NAME)
295 for b in bl.object.getShapeKeys(obj):
296 if b.name==bl.BASE_SHAPE_NAME:
297 baseMorph=self.__getOrCreateMorph('base', 0)
302 v=bl.shapekey.getByIndex(b, index)
303 pos=[v[0], v[1], v[2]]
305 indices=self.vertexArray.getMappedIndex(obj.name, index)
306 for attribute, i in indices.items():
311 baseMorph.add(i, pos)
312 indexRelativeMap[i]=relativeIndex
317 #print(basis.name, len(baseMorph.offsets))
319 if len(baseMorph.offsets)==0:
323 for b in bl.object.getShapeKeys(obj):
324 if b.name==bl.BASE_SHAPE_NAME:
328 morph=self.__getOrCreateMorph(b.name, 4)
330 for index, src, dst in zip(
331 range(len(blenderMesh.vertices)),
332 bl.shapekey.get(basis),
334 offset=[dst[0]-src[0], dst[1]-src[1], dst[2]-src[2]]
335 if offset[0]==0 and offset[1]==0 and offset[2]==0:
338 indices=self.vertexArray.getMappedIndex(obj.name, index)
339 for attribute, i in indices.items():
343 morph.add(indexRelativeMap[i], offset)
344 assert(len(morph.offsets)<len(baseMorph.offsets))
347 original=self.morphList[:]
349 for i, v in enumerate(englishmap.skinMap):
353 return len(englishmap.skinMap)
354 self.morphList.sort(key=getIndex)
356 def __rigidbody(self, obj):
357 if not bl.RIGID_SHAPE_TYPE in obj:
359 self.rigidbodies.append(obj)
361 def __constraint(self, obj):
362 if not bl.CONSTRAINT_A in obj:
364 self.constraints.append(obj)
366 def __getOrCreateMorph(self, name, type):
367 for m in self.morphList:
371 self.morphList.append(m)
374 def getVertexCount(self):
375 return len(self.vertexArray.positions)