5 from Blender import Mathutils
8 #
\e$B%U%!%$%k%7%9%F%`$NJ8;z%3!<%I
\e(B
9 #
\e$B2~B$HG$H$N6&MQ$N$?$a
\e(B
10 FS_ENCODING=sys.getfilesystemencoding()
11 if os.path.exists(os.path.dirname(sys.argv[0])+"/utf8"):
12 INTERNAL_ENCODING='utf-8'
14 INTERNAL_ENCODING=FS_ENCODING
17 def createEmptyObject(scene, name):
18 empty=scene.objects.new("Empty")
23 def createMqoMaterial(m):
24 material = Blender.Material.New(m.getName().encode(INTERNAL_ENCODING))
25 material.mode |= Blender.Material.Modes.SHADELESS
26 material.rgbCol = [m.color.r, m.color.g, m.color.b]
27 material.alpha = m.color.a
28 material.amb = m.ambient
29 material.spec = m.specular
30 material.hard = int(255 * m.power)
34 def createTexture(path):
35 image = Blender.Image.Load(path.encode(INTERNAL_ENCODING))
36 texture = Blender.Texture.New(path.encode(INTERNAL_ENCODING))
37 texture.type = Blender.Texture.Types.IMAGE
42 def materialAddTexture(material, texture):
43 material.mode = material.mode | Blender.Material.Modes.TEXFACE
44 material.setTexture(0, texture, Blender.Texture.TexCo.UV)
47 def createMesh(scene, name):
48 mesh = Blender.Mesh.New()
49 mesh_object=scene.objects.new(mesh, name.encode(INTERNAL_ENCODING))
50 return mesh, mesh_object
53 def objectMakeParent(parent, child):
54 parent.makeParent([child])
57 def meshAddMqoGeometry(mesh, o, materials, imageMap, scale):
59 mesh.verts.extend(Mathutils.Vector(0, 0, 0)) # dummy
60 mesh.verts.extend([(v.x, -v.z, v.y) for v in o.vertices])
65 for i in xrange(face.index_count):
66 face_indices.append(face.getIndex(i)+1)
67 mesh_faces.append(face_indices)
68 #new_faces=mesh.faces.extend([face.indices for face in o.faces],
69 new_faces=mesh.faces.extend(mesh_faces,
74 # gather used materials
79 materialMap[o.faces[i].material_index]=True
81 # blender limits 16 materials per mesh
83 for i, material_index in enumerate(materialMap.keys()):
85 print("over 16 materials!")
87 mesh.materials+=[materials[material_index]]
88 materialMap[material_index]=i
91 for i, f in enumerate(o.faces):
92 if not type(new_faces[i]) is int:
95 face=mesh.faces[new_faces[i]]
98 for i in xrange(f.index_count):
99 uv_array.append(Blender.Mathutils.Vector(
105 except Exception as msg:
107 #print face.index, uv_array
110 if f.material_index in materialMap:
111 face.mat = materialMap[f.material_index]
115 # rmeove dummy 0 vertex
118 mesh.mode |= Blender.Mesh.Modes.AUTOSMOOTH
119 mesh.maxSmoothAngle = int(o.smoothing)
127 mod=mesh_object.modifiers.append(Blender.Modifier.Types.MIRROR)
129 ###############################################################################
130 # for mqo mikoto bone.
131 ###############################################################################
132 class MikotoBone(object):
135 'iHead', 'iTail', 'iUp',
136 'vHead', 'vTail', 'vUp',
137 'parent', 'isFloating',
140 def __init__(self, face=None, vertices=None, materials=None):
142 self.isFloating=False
148 self.name=materials[face.material_index].name.encode('utf-8')
159 sqNorm0=e01.getSqNorm()
160 sqNorm1=e12.getSqNorm()
161 sqNorm2=e20.getSqNorm()
197 self.vHead=vertices[self.iHead]
198 self.vTail=vertices[self.iTail]
199 self.vUp=vertices[self.iUp]
201 if self.name.endswith('[]'):
202 basename=self.name[0:-2]
205 self.name="%s_L" % basename
207 self.name="%s_R" % basename
210 def setParent(self, parent, floating=False):
214 parent.children.append(self)
216 def printTree(self, indent=''):
217 print("%s%s" % (indent, self.name))
218 for child in self.children:
219 child.printTree(indent+' ')
222 def build_armature(armature, mikotoBone, parent=None):
224 create a armature bone.
226 bone = Armature.Editbone()
227 bone.name = mikotoBone.name.encode('utf-8')
228 armature.bones[bone.name] = bone
230 bone.head = Mathutils.Vector(*mikotoBone.vHead.to_a())
231 bone.tail = Mathutils.Vector(*mikotoBone.vTail.to_a())
234 if mikotoBone.isFloating:
237 bone.options=[Armature.CONNECTED]
239 for child in mikotoBone.children:
240 build_armature(armature, child, bone)
243 def create_armature(scene, mqo):
248 for o in mqo.objects:
249 if o.name.startswith('bone'):
256 for f in boneObject.faces:
258 print("invalid index_count: %d" % f.index_count)
260 b=MikotoBone(f, boneObject.vertices, mqo.materials)
264 # build mikoto bone tree
266 mikotoRoot=MikotoBone()
268 for b in tailMap.values():
269 # each bone has unique parent or is root bone.
270 if b.iHead in tailMap:
271 b.setParent(tailMap[b.iHead])
274 for e in boneObject.edges:
275 if b.iHead==e.indices[0]:
277 if e.indices[1] in tailMap:
278 b.setParent(tailMap[e.indices[1]], True)
281 elif b.iHead==e.indices[1]:
283 if e.indices[0] in tailMap:
284 b.setParent(tailMap[e.indices[0]], True)
291 b.setParent(mikotoRoot, True)
293 if len(mikotoRoot.children)==0:
294 print("no root bone")
297 if len(mikotoRoot.children)==1:
299 mikotoRoot=mikotoRoot.children[0]
300 mikotoRoot.parent=None
302 mikotoRoot.vHead=Vector3(0, 10, 0)
303 mikotoRoot.vTail=Vector3(0, 0, 0)
308 armature = Armature.New()
310 armature_object = scene.objects.new(armature)
312 act = Armature.NLA.NewAction()
313 act.setActive(armature_object)
315 armature_object.drawMode |= Object.DrawModes.XRAY
317 armature.drawType = Armature.OCTAHEDRON
318 armature.envelopes = False
319 armature.vertexGroups = True
320 armature.mirrorEdit = True
321 armature.drawNames=True
324 armature.makeEditable()
325 build_armature(armature, mikotoRoot)
328 return armature_object
331 class TrianglePlane(object):
333 mikoto
\e$BJ}<0%\!<%s$N%"%s%+!<%&%'%$%H7W;;MQ!#
\e(B
339 def __init__(self, v0, v1, v2):
344 def isInsideXY(self, p):
345 v0=Vector2(self.v0.x, self.v0.y)
346 v1=Vector2(self.v1.x, self.v1.y)
347 v2=Vector2(self.v2.x, self.v2.y)
351 c0=Vector2.cross(e01, p-v0)
352 c1=Vector2.cross(e12, p-v1)
353 c2=Vector2.cross(e20, p-v2)
354 if c0>=0 and c1>=0 and c2>=0:
356 if c0<=0 and c1<=0 and c2<=0:
359 def isInsideYZ(self, p):
360 v0=Vector2(self.v0.y, self.v0.z)
361 v1=Vector2(self.v1.y, self.v1.z)
362 v2=Vector2(self.v2.y, self.v2.z)
366 c0=Vector2.cross(e01, p-v0)
367 c1=Vector2.cross(e12, p-v1)
368 c2=Vector2.cross(e20, p-v2)
369 if c0>=0 and c1>=0 and c2>=0:
371 if c0<=0 and c1<=0 and c2<=0:
374 def isInsideZX(self, p):
375 v0=Vector2(self.v0.z, self.v0.x)
376 v1=Vector2(self.v1.z, self.v1.x)
377 v2=Vector2(self.v2.z, self.v2.x)
381 c0=Vector2.cross(e01, p-v0)
382 c1=Vector2.cross(e12, p-v1)
383 c2=Vector2.cross(e20, p-v2)
384 if c0>=0 and c1>=0 and c2>=0:
386 if c0<=0 and c1<=0 and c2<=0:
390 class MikotoAnchor(object):
392 mikoto
\e$BJ}<0%9%1%k%H%s$N%"%s%+!<!#
\e(B
401 def push(self, face, vertices):
402 if face.index_count==3:
403 self.triangles.append(TrianglePlane(
404 vertices[face.indices[0]],
405 vertices[face.indices[1]],
406 vertices[face.indices[2]]
408 elif face.index_count==4:
409 self.triangles.append(TrianglePlane(
410 vertices[face.indices[0]],
411 vertices[face.indices[1]],
412 vertices[face.indices[2]]
414 self.triangles.append(TrianglePlane(
415 vertices[face.indices[2]],
416 vertices[face.indices[3]],
417 vertices[face.indices[0]]
421 self.bbox=BoundingBox(vertices[face.indices[0]])
422 for i in face.indices:
423 self.bbox.expand(vertices[i])
426 def calcWeight(self, v):
427 if not self.bbox.isInside(v):
430 if self.anyXY(v.x, v.y) and self.anyYZ(v.y, v.z) and self.anyZX(v.z, v.x):
435 def anyXY(self, x, y):
436 for t in self.triangles:
437 if t.isInsideXY(Vector2(x, y)):
441 def anyYZ(self, y, z):
442 for t in self.triangles:
443 if t.isInsideYZ(Vector2(y, z)):
447 def anyZX(self, z, x):
448 for t in self.triangles:
449 if t.isInsideZX(Vector2(z, x)):
454 def create_bone_weight(scene, mqo, armature_object, objects):
456 create mikoto bone weight.
459 # setup mikoto anchors
460 for o in mqo.objects:
461 if o.name.startswith("anchor"):
463 name=mqo.materials[f.material_index].name
464 if name.endswith('[]'):
466 v=o.vertices[f.indices[0]]
470 if not name_L in anchorMap:
471 anchorMap[name_L]=MikotoAnchor()
472 anchorMap[name_L].push(f, o.vertices)
476 if not name_R in anchorMap:
477 anchorMap[name_R]=MikotoAnchor()
478 anchorMap[name_R].push(f, o.vertices)
482 if not name in anchorMap:
483 anchorMap[name]=MikotoAnchor()
484 anchorMap[name].push(f, o.vertices)
487 # add armature modifier
488 mod=o.modifiers.append(Modifier.Types.ARMATURE)
489 mod[Modifier.Settings.OBJECT] = armature_object
490 mod[Modifier.Settings.ENVELOPES] = False
492 # create vertex group
493 mesh=o.getData(mesh=True)
494 for name in anchorMap.keys():
495 mesh.addVertGroup(name)
498 # assing vertices to vertex group
500 mesh=o.getData(mesh=True)
501 for i, mvert in enumerate(mesh.verts):
503 for name, anchor in anchorMap.items():
504 weight=anchor.calcWeight(mvert.co)
506 mesh.assignVertsToGroup(
507 name, [i], weight, Mesh.AssignModes.ADD)
510 # debug orphan vertex
511 print('orphan', mvert)