###############################################################################
-# for mqo mikoto bone.
-###############################################################################
-class MikotoBone(object):
- __slots__=[
- 'name',
- 'iHead', 'iTail', 'iUp',
- 'vHead', 'vTail', 'vUp',
- 'parent', 'isFloating',
- 'children',
- ]
- def __init__(self, face=None, vertices=None, materials=None):
- self.parent=None
- self.isFloating=False
- self.children=[]
- if not face:
- self.name='root'
- return
-
- self.name=materials[face.material_index].name.encode('utf-8')
-
- i0=face.indices[0]
- i1=face.indices[1]
- i2=face.indices[2]
- v0=vertices[i0]
- v1=vertices[i1]
- v2=vertices[i2]
- e01=v1-v0
- e12=v2-v1
- e20=v0-v2
- sqNorm0=e01.getSqNorm()
- sqNorm1=e12.getSqNorm()
- sqNorm2=e20.getSqNorm()
- if sqNorm0>sqNorm1:
- if sqNorm1>sqNorm2:
- # e01 > e12 > e20
- self.iHead=i2
- self.iTail=i1
- self.iUp=i0
- else:
- if sqNorm0>sqNorm2:
- # e01 > e20 > e12
- self.iHead=i2
- self.iTail=i0
- self.iUp=i1
- else:
- # e20 > e01 > e12
- self.iHead=i1
- self.iTail=i0
- self.iUp=i2
- else:
- # 0 < 1
- if sqNorm1<sqNorm2:
- # e20 > e12 > e01
- self.iHead=i1
- self.iTail=i2
- self.iUp=i0
- else:
- if sqNorm0<sqNorm2:
- # e12 > e20 > e01
- self.iHead=i0
- self.iTail=i2
- self.iUp=i1
- else:
- # e12 > e01 > e20
- self.iHead=i0
- self.iTail=i1
- self.iUp=i2
- self.vHead=vertices[self.iHead]
- self.vTail=vertices[self.iTail]
- self.vUp=vertices[self.iUp]
-
- if self.name.endswith('[]'):
- basename=self.name[0:-2]
- # expand LR name
- if self.vTail.x>0:
- self.name="%s_L" % basename
- else:
- self.name="%s_R" % basename
-
-
- def setParent(self, parent, floating=False):
- if floating:
- self.isFloating=True
- self.parent=parent
- parent.children.append(self)
-
- def printTree(self, indent=''):
- print("%s%s" % (indent, self.name))
- for child in self.children:
- child.printTree(indent+' ')
-
-
-def build_armature(armature, mikotoBone, parent=None):
- """
- create a armature bone.
- """
- bone = Armature.Editbone()
- bone.name = mikotoBone.name.encode('utf-8')
- armature.bones[bone.name] = bone
-
- bone.head = Mathutils.Vector(*mikotoBone.vHead.to_a())
- bone.tail = Mathutils.Vector(*mikotoBone.vTail.to_a())
- if parent:
- bone.parent=parent
- if mikotoBone.isFloating:
- pass
- else:
- bone.options=[Armature.CONNECTED]
-
- for child in mikotoBone.children:
- build_armature(armature, child, bone)
-
-
-def create_armature(scene, mqo):
- """
- create armature
- """
- boneObject=None
- for o in mqo.objects:
- if o.name.startswith('bone'):
- boneObject=o
- break
- if not boneObject:
- return
-
- tailMap={}
- for f in boneObject.faces:
- if f.index_count!=3:
- print("invalid index_count: %d" % f.index_count)
- continue
- b=MikotoBone(f, boneObject.vertices, mqo.materials)
- tailMap[b.iTail]=b
-
- ####################
- # build mikoto bone tree
- ####################
- mikotoRoot=MikotoBone()
-
- for b in tailMap.values():
- # each bone has unique parent or is root bone.
- if b.iHead in tailMap:
- b.setParent(tailMap[b.iHead])
- else:
- isFloating=False
- for e in boneObject.edges:
- if b.iHead==e.indices[0]:
- # floating bone
- if e.indices[1] in tailMap:
- b.setParent(tailMap[e.indices[1]], True)
- isFloating=True
- break
- elif b.iHead==e.indices[1]:
- # floating bone
- if e.indices[0] in tailMap:
- b.setParent(tailMap[e.indices[0]], True)
- isFloating=True
- break
- if isFloating:
- continue
-
- # no parent bone
- b.setParent(mikotoRoot, True)
-
- if len(mikotoRoot.children)==0:
- print("no root bone")
- return
-
- if len(mikotoRoot.children)==1:
- # single root
- mikotoRoot=mikotoRoot.children[0]
- mikotoRoot.parent=None
- else:
- mikotoRoot.vHead=Vector3(0, 10, 0)
- mikotoRoot.vTail=Vector3(0, 0, 0)
-
- ####################
- # create armature
- ####################
- armature = Armature.New()
- # link to object
- armature_object = scene.objects.new(armature)
- # create action
- act = Armature.NLA.NewAction()
- act.setActive(armature_object)
- # set XRAY
- armature_object.drawMode |= Object.DrawModes.XRAY
- # armature settings
- armature.drawType = Armature.OCTAHEDRON
- armature.envelopes = False
- armature.vertexGroups = True
- armature.mirrorEdit = True
- armature.drawNames=True
-
- # edit bones
- armature.makeEditable()
- build_armature(armature, mikotoRoot)
- armature.update()
-
- return armature_object
-
-
-class TrianglePlane(object):
- """
- mikoto方式ボーンのアンカーウェイト計算用。
- (不完全)
- """
- __slots__=['normal',
- 'v0', 'v1', 'v2',
- ]
- def __init__(self, v0, v1, v2):
- self.v0=v0
- self.v1=v1
- self.v2=v2
-
- def isInsideXY(self, p):
- v0=Vector2(self.v0.x, self.v0.y)
- v1=Vector2(self.v1.x, self.v1.y)
- v2=Vector2(self.v2.x, self.v2.y)
- e01=v1-v0
- e12=v2-v1
- e20=v0-v2
- c0=Vector2.cross(e01, p-v0)
- c1=Vector2.cross(e12, p-v1)
- c2=Vector2.cross(e20, p-v2)
- if c0>=0 and c1>=0 and c2>=0:
- return True
- if c0<=0 and c1<=0 and c2<=0:
- return True
-
- def isInsideYZ(self, p):
- v0=Vector2(self.v0.y, self.v0.z)
- v1=Vector2(self.v1.y, self.v1.z)
- v2=Vector2(self.v2.y, self.v2.z)
- e01=v1-v0
- e12=v2-v1
- e20=v0-v2
- c0=Vector2.cross(e01, p-v0)
- c1=Vector2.cross(e12, p-v1)
- c2=Vector2.cross(e20, p-v2)
- if c0>=0 and c1>=0 and c2>=0:
- return True
- if c0<=0 and c1<=0 and c2<=0:
- return True
-
- def isInsideZX(self, p):
- v0=Vector2(self.v0.z, self.v0.x)
- v1=Vector2(self.v1.z, self.v1.x)
- v2=Vector2(self.v2.z, self.v2.x)
- e01=v1-v0
- e12=v2-v1
- e20=v0-v2
- c0=Vector2.cross(e01, p-v0)
- c1=Vector2.cross(e12, p-v1)
- c2=Vector2.cross(e20, p-v2)
- if c0>=0 and c1>=0 and c2>=0:
- return True
- if c0<=0 and c1<=0 and c2<=0:
- return True
-
-
-class MikotoAnchor(object):
- """
- mikoto方式スケルトンのアンカー。
- """
- __slots__=[
- "triangles", "bbox",
- ]
- def __init__(self):
- self.triangles=[]
- self.bbox=None
-
- def push(self, face, vertices):
- if face.index_count==3:
- self.triangles.append(TrianglePlane(
- vertices[face.indices[0]],
- vertices[face.indices[1]],
- vertices[face.indices[2]]
- ))
- elif face.index_count==4:
- self.triangles.append(TrianglePlane(
- vertices[face.indices[0]],
- vertices[face.indices[1]],
- vertices[face.indices[2]]
- ))
- self.triangles.append(TrianglePlane(
- vertices[face.indices[2]],
- vertices[face.indices[3]],
- vertices[face.indices[0]]
- ))
- # bounding box
- if not self.bbox:
- self.bbox=BoundingBox(vertices[face.indices[0]])
- for i in face.indices:
- self.bbox.expand(vertices[i])
-
-
- def calcWeight(self, v):
- if not self.bbox.isInside(v):
- return 0
-
- if self.anyXY(v.x, v.y) and self.anyYZ(v.y, v.z) and self.anyZX(v.z, v.x):
- return 1.0
- else:
- return 0
-
- def anyXY(self, x, y):
- for t in self.triangles:
- if t.isInsideXY(Vector2(x, y)):
- return True
- return False
-
- def anyYZ(self, y, z):
- for t in self.triangles:
- if t.isInsideYZ(Vector2(y, z)):
- return True
- return False
-
- def anyZX(self, z, x):
- for t in self.triangles:
- if t.isInsideZX(Vector2(z, x)):
- return True
- return False
-
-
-def create_bone_weight(scene, mqo, armature_object, objects):
- """
- create mikoto bone weight.
- """
- anchorMap={}
- # setup mikoto anchors
- for o in mqo.objects:
- if o.name.startswith("anchor"):
- for f in o.faces:
- name=mqo.materials[f.material_index].name
- if name.endswith('[]'):
- basename=name[0:-2]
- v=o.vertices[f.indices[0]]
- if(v.x>0):
- # L
- name_L=basename+'_L'
- if not name_L in anchorMap:
- anchorMap[name_L]=MikotoAnchor()
- anchorMap[name_L].push(f, o.vertices)
- elif(v.x<0):
- # R
- name_R=basename+'_R'
- if not name_R in anchorMap:
- anchorMap[name_R]=MikotoAnchor()
- anchorMap[name_R].push(f, o.vertices)
- else:
- print("no side", v)
- else:
- if not name in anchorMap:
- anchorMap[name]=MikotoAnchor()
- anchorMap[name].push(f, o.vertices)
-
- for o in objects:
- # add armature modifier
- mod=o.modifiers.append(Modifier.Types.ARMATURE)
- mod[Modifier.Settings.OBJECT] = armature_object
- mod[Modifier.Settings.ENVELOPES] = False
- o.makeDisplayList()
- # create vertex group
- mesh=o.getData(mesh=True)
- for name in anchorMap.keys():
- mesh.addVertGroup(name)
- mesh.update()
-
- # assing vertices to vertex group
- for o in objects:
- mesh=o.getData(mesh=True)
- for i, mvert in enumerate(mesh.verts):
- hasWeight=False
- for name, anchor in anchorMap.items():
- weight=anchor.calcWeight(mvert.co)
- if weight>0:
- mesh.assignVertsToGroup(
- name, [i], weight, Mesh.AssignModes.ADD)
- hasWeight=True
- if not hasWeight:
- # debug orphan vertex
- print('orphan', mvert)
- mesh.update()
-
-###############################################################################
def createEmptyObject(scene, name):
empty=scene.objects.new("Empty")
empty.setName(name)
mesh.materials+=[material]
-def meshAddMqoGeometry(mesh, o, materials, imageMap, scale):
+def meshAddMqoGeometry(mesh_object, o, materials, imageMap, scale):
+ mesh=mesh_object.getData(mesh=True)
# add vertices
mesh.verts.extend(Mathutils.Vector(0, 0, 0)) # dummy
mesh.verts.extend([(v.x * scale, -v.z * scale, v.y * scale) for v in o.vertices])
for i, enable in enumerate(layers):
if enable!=0:
mask+=(1<<i)
- object.layerMask=mask
+ object.Layers=mask
def objectPinShape(o):
o.pinShape=True
\r
\r
def has_mikoto(mqo):\r
+ #for o in mqo.objects:\r
+ # if o.getName().startswith('bone'):\r
+ # return True\r
+ # if o.getName().startswith('sdef'):\r
+ # return True\r
+ # if o.getName().startswith('anchor'):\r
+ # return True\r
return False\r
\r
\r
elif o.getName().startswith('bone'):\r
bl.objectLayerMask(mesh_object, [0, 1])\r
\r
- bl.meshAddMqoGeometry(mesh, o, materials, imageMap, scale)\r
+ bl.meshAddMqoGeometry(mesh_object, o, materials, imageMap, scale)\r
\r
return objects\r
\r
\r
+###############################################################################\r
+# for mqo mikoto bone.\r
+###############################################################################\r
+class MikotoBone(object):\r
+ __slots__=[\r
+ 'name',\r
+ 'iHead', 'iTail', 'iUp',\r
+ 'vHead', 'vTail', 'vUp',\r
+ 'parent', 'isFloating',\r
+ 'children',\r
+ ]\r
+ def __init__(self, face=None, vertices=None, materials=None):\r
+ self.parent=None\r
+ self.isFloating=False\r
+ self.children=[]\r
+ if not face:\r
+ self.name='root'\r
+ return\r
+\r
+ self.name=materials[face.material_index].name.encode('utf-8')\r
+\r
+ i0=face.getIndex(0)\r
+ i1=face.getIndex(1)\r
+ i2=face.getIndex(2)\r
+ v0=vertices[i0]\r
+ v1=vertices[i1]\r
+ v2=vertices[i2]\r
+ e01=v1-v0\r
+ e12=v2-v1\r
+ e20=v0-v2\r
+ sqNorm0=e01.getSqNorm()\r
+ sqNorm1=e12.getSqNorm()\r
+ sqNorm2=e20.getSqNorm()\r
+ if sqNorm0>sqNorm1:\r
+ if sqNorm1>sqNorm2:\r
+ # e01 > e12 > e20\r
+ self.iHead=i2\r
+ self.iTail=i1\r
+ self.iUp=i0\r
+ else:\r
+ if sqNorm0>sqNorm2:\r
+ # e01 > e20 > e12\r
+ self.iHead=i2\r
+ self.iTail=i0\r
+ self.iUp=i1\r
+ else:\r
+ # e20 > e01 > e12\r
+ self.iHead=i1\r
+ self.iTail=i0\r
+ self.iUp=i2\r
+ else:\r
+ # 0 < 1\r
+ if sqNorm1<sqNorm2:\r
+ # e20 > e12 > e01\r
+ self.iHead=i1\r
+ self.iTail=i2\r
+ self.iUp=i0\r
+ else:\r
+ if sqNorm0<sqNorm2:\r
+ # e12 > e20 > e01\r
+ self.iHead=i0\r
+ self.iTail=i2\r
+ self.iUp=i1\r
+ else:\r
+ # e12 > e01 > e20\r
+ self.iHead=i0\r
+ self.iTail=i1\r
+ self.iUp=i2\r
+ self.vHead=vertices[self.iHead]\r
+ self.vTail=vertices[self.iTail]\r
+ self.vUp=vertices[self.iUp]\r
+\r
+ if self.name.endswith('[]'):\r
+ basename=self.name[0:-2]\r
+ # expand LR name\r
+ if self.vTail.x>0:\r
+ self.name="%s_L" % basename\r
+ else:\r
+ self.name="%s_R" % basename\r
+\r
+\r
+ def setParent(self, parent, floating=False):\r
+ if floating:\r
+ self.isFloating=True\r
+ self.parent=parent\r
+ parent.children.append(self)\r
+\r
+ def printTree(self, indent=''):\r
+ print("%s%s" % (indent, self.name))\r
+ for child in self.children:\r
+ child.printTree(indent+' ')\r
+\r
+\r
+def build_armature(armature, mikotoBone, parent=None):\r
+ """\r
+ create a armature bone.\r
+ """\r
+ bone = Armature.Editbone()\r
+ bone.name = mikotoBone.name.encode('utf-8')\r
+ armature.bones[bone.name] = bone\r
+\r
+ bone.head = Mathutils.Vector(*mikotoBone.vHead.to_a())\r
+ bone.tail = Mathutils.Vector(*mikotoBone.vTail.to_a())\r
+ if parent:\r
+ bone.parent=parent\r
+ if mikotoBone.isFloating:\r
+ pass\r
+ else:\r
+ bone.options=[Armature.CONNECTED]\r
+\r
+ for child in mikotoBone.children:\r
+ build_armature(armature, child, bone)\r
+\r
+\r
+def create_armature(scene, mqo):\r
+ """\r
+ create armature\r
+ """\r
+ boneObject=None\r
+ for o in mqo.objects:\r
+ if o.name.startswith('bone'):\r
+ boneObject=o\r
+ break\r
+ if not boneObject:\r
+ return\r
+\r
+ tailMap={}\r
+ for f in boneObject.faces:\r
+ if f.index_count!=3:\r
+ print("invalid index_count: %d" % f.index_count)\r
+ continue\r
+ b=MikotoBone(f, boneObject.vertices, mqo.materials)\r
+ tailMap[b.iTail]=b\r
+\r
+ #################### \r
+ # build mikoto bone tree\r
+ #################### \r
+ mikotoRoot=MikotoBone()\r
+\r
+ for b in tailMap.values():\r
+ # each bone has unique parent or is root bone.\r
+ if b.iHead in tailMap:\r
+ b.setParent(tailMap[b.iHead])\r
+ else: \r
+ isFloating=False\r
+ for e in boneObject.edges:\r
+ if b.iHead==e.indices[0]:\r
+ # floating bone\r
+ if e.indices[1] in tailMap:\r
+ b.setParent(tailMap[e.indices[1]], True)\r
+ isFloating=True\r
+ break\r
+ elif b.iHead==e.indices[1]:\r
+ # floating bone\r
+ if e.indices[0] in tailMap:\r
+ b.setParent(tailMap[e.indices[0]], True)\r
+ isFloating=True\r
+ break\r
+ if isFloating:\r
+ continue\r
+\r
+ # no parent bone\r
+ b.setParent(mikotoRoot, True)\r
+\r
+ if len(mikotoRoot.children)==0:\r
+ print("no root bone")\r
+ return\r
+\r
+ if len(mikotoRoot.children)==1:\r
+ # single root\r
+ mikotoRoot=mikotoRoot.children[0]\r
+ mikotoRoot.parent=None\r
+ else:\r
+ mikotoRoot.vHead=Vector3(0, 10, 0)\r
+ mikotoRoot.vTail=Vector3(0, 0, 0)\r
+\r
+ #################### \r
+ # create armature\r
+ #################### \r
+ armature = Armature.New()\r
+ # link to object\r
+ armature_object = scene.objects.new(armature)\r
+ # create action\r
+ act = Armature.NLA.NewAction()\r
+ act.setActive(armature_object)\r
+ # set XRAY\r
+ armature_object.drawMode |= Object.DrawModes.XRAY\r
+ # armature settings\r
+ armature.drawType = Armature.OCTAHEDRON\r
+ armature.envelopes = False\r
+ armature.vertexGroups = True\r
+ armature.mirrorEdit = True\r
+ armature.drawNames=True\r
+\r
+ # edit bones\r
+ armature.makeEditable()\r
+ build_armature(armature, mikotoRoot)\r
+ armature.update()\r
+\r
+ return armature_object\r
+ \r
+\r
+class TrianglePlane(object):\r
+ """\r
+ mikoto\e$BJ}<0%\!<%s$N%"%s%+!<%&%'%$%H7W;;MQ!#\e(B\r
+ (\e$BIT40A4\e(B)\r
+ """\r
+ __slots__=['normal', \r
+ 'v0', 'v1', 'v2',\r
+ ]\r
+ def __init__(self, v0, v1, v2):\r
+ self.v0=v0\r
+ self.v1=v1\r
+ self.v2=v2\r
+\r
+ def isInsideXY(self, p):\r
+ v0=Vector2(self.v0.x, self.v0.y)\r
+ v1=Vector2(self.v1.x, self.v1.y)\r
+ v2=Vector2(self.v2.x, self.v2.y)\r
+ e01=v1-v0\r
+ e12=v2-v1\r
+ e20=v0-v2\r
+ c0=Vector2.cross(e01, p-v0)\r
+ c1=Vector2.cross(e12, p-v1)\r
+ c2=Vector2.cross(e20, p-v2)\r
+ if c0>=0 and c1>=0 and c2>=0:\r
+ return True\r
+ if c0<=0 and c1<=0 and c2<=0:\r
+ return True\r
+\r
+ def isInsideYZ(self, p):\r
+ v0=Vector2(self.v0.y, self.v0.z)\r
+ v1=Vector2(self.v1.y, self.v1.z)\r
+ v2=Vector2(self.v2.y, self.v2.z)\r
+ e01=v1-v0\r
+ e12=v2-v1\r
+ e20=v0-v2\r
+ c0=Vector2.cross(e01, p-v0)\r
+ c1=Vector2.cross(e12, p-v1)\r
+ c2=Vector2.cross(e20, p-v2)\r
+ if c0>=0 and c1>=0 and c2>=0:\r
+ return True\r
+ if c0<=0 and c1<=0 and c2<=0:\r
+ return True\r
+\r
+ def isInsideZX(self, p):\r
+ v0=Vector2(self.v0.z, self.v0.x)\r
+ v1=Vector2(self.v1.z, self.v1.x)\r
+ v2=Vector2(self.v2.z, self.v2.x)\r
+ e01=v1-v0\r
+ e12=v2-v1\r
+ e20=v0-v2\r
+ c0=Vector2.cross(e01, p-v0)\r
+ c1=Vector2.cross(e12, p-v1)\r
+ c2=Vector2.cross(e20, p-v2)\r
+ if c0>=0 and c1>=0 and c2>=0:\r
+ return True\r
+ if c0<=0 and c1<=0 and c2<=0:\r
+ return True\r
+\r
+\r
+class MikotoAnchor(object):\r
+ """\r
+ mikoto\e$BJ}<0%9%1%k%H%s$N%"%s%+!<!#\e(B\r
+ """\r
+ __slots__=[\r
+ "triangles", "bbox",\r
+ ]\r
+ def __init__(self):\r
+ self.triangles=[]\r
+ self.bbox=None\r
+\r
+ def push(self, face, vertices):\r
+ if face.index_count==3:\r
+ self.triangles.append(TrianglePlane(\r
+ vertices[face.indices[0]],\r
+ vertices[face.indices[1]],\r
+ vertices[face.indices[2]]\r
+ ))\r
+ elif face.index_count==4:\r
+ self.triangles.append(TrianglePlane(\r
+ vertices[face.indices[0]],\r
+ vertices[face.indices[1]],\r
+ vertices[face.indices[2]]\r
+ ))\r
+ self.triangles.append(TrianglePlane(\r
+ vertices[face.indices[2]],\r
+ vertices[face.indices[3]],\r
+ vertices[face.indices[0]]\r
+ ))\r
+ # bounding box\r
+ if not self.bbox:\r
+ self.bbox=BoundingBox(vertices[face.indices[0]])\r
+ for i in face.indices:\r
+ self.bbox.expand(vertices[i])\r
+\r
+\r
+ def calcWeight(self, v):\r
+ if not self.bbox.isInside(v):\r
+ return 0\r
+\r
+ if self.anyXY(v.x, v.y) and self.anyYZ(v.y, v.z) and self.anyZX(v.z, v.x):\r
+ return 1.0\r
+ else:\r
+ return 0\r
+ \r
+ def anyXY(self, x, y):\r
+ for t in self.triangles:\r
+ if t.isInsideXY(Vector2(x, y)):\r
+ return True\r
+ return False\r
+\r
+ def anyYZ(self, y, z):\r
+ for t in self.triangles:\r
+ if t.isInsideYZ(Vector2(y, z)):\r
+ return True\r
+ return False\r
+\r
+ def anyZX(self, z, x):\r
+ for t in self.triangles:\r
+ if t.isInsideZX(Vector2(z, x)):\r
+ return True\r
+ return False\r
+\r
+\r
+def create_bone_weight(scene, mqo, armature_object, objects):\r
+ """\r
+ create mikoto bone weight.\r
+ """\r
+ anchorMap={}\r
+ # setup mikoto anchors\r
+ for o in mqo.objects:\r
+ if o.name.startswith("anchor"):\r
+ for f in o.faces:\r
+ name=mqo.materials[f.material_index].name\r
+ if name.endswith('[]'):\r
+ basename=name[0:-2]\r
+ v=o.vertices[f.indices[0]]\r
+ if(v.x>0):\r
+ # L\r
+ name_L=basename+'_L'\r
+ if not name_L in anchorMap:\r
+ anchorMap[name_L]=MikotoAnchor()\r
+ anchorMap[name_L].push(f, o.vertices)\r
+ elif(v.x<0):\r
+ # R\r
+ name_R=basename+'_R'\r
+ if not name_R in anchorMap:\r
+ anchorMap[name_R]=MikotoAnchor()\r
+ anchorMap[name_R].push(f, o.vertices)\r
+ else:\r
+ print("no side", v)\r
+ else:\r
+ if not name in anchorMap:\r
+ anchorMap[name]=MikotoAnchor()\r
+ anchorMap[name].push(f, o.vertices)\r
+\r
+ for o in objects:\r
+ # add armature modifier\r
+ mod=o.modifiers.append(Modifier.Types.ARMATURE)\r
+ mod[Modifier.Settings.OBJECT] = armature_object\r
+ mod[Modifier.Settings.ENVELOPES] = False\r
+ o.makeDisplayList()\r
+ # create vertex group\r
+ mesh=o.getData(mesh=True)\r
+ for name in anchorMap.keys():\r
+ mesh.addVertGroup(name)\r
+ mesh.update()\r
+ \r
+ # assing vertices to vertex group\r
+ for o in objects:\r
+ mesh=o.getData(mesh=True)\r
+ for i, mvert in enumerate(mesh.verts):\r
+ hasWeight=False\r
+ for name, anchor in anchorMap.items():\r
+ weight=anchor.calcWeight(mvert.co)\r
+ if weight>0:\r
+ mesh.assignVertsToGroup(\r
+ name, [i], weight, Mesh.AssignModes.ADD)\r
+ hasWeight=True\r
+ if not hasWeight:\r
+ # debug orphan vertex\r
+ print('orphan', mvert)\r
+ mesh.update()\r
+\r
+\r
def __execute(filename, scene, scale=1.0):\r
# parse file\r
io=mqo.IO()\r