X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=swig%2Fblender%2Fmqo_import.py;h=630501ec3a5ca415b8fb4e727635b7f36be1c8f9;hb=68a0b4bad4103f2c036484bcfbf5743ca5d6380b;hp=038ddf0d384f9743e7b3e43a57dcfcb1ef155f9b;hpb=0afdac244629258bebda6e65a25ba3e3879f4003;p=meshio%2Fmeshio.git diff --git a/swig/blender/mqo_import.py b/swig/blender/mqo_import.py index 038ddf0..630501e 100644 --- a/swig/blender/mqo_import.py +++ b/swig/blender/mqo_import.py @@ -21,15 +21,12 @@ This script imports a mqo into Blender for editing. 0.5 20100311: create armature from mikoto bone. 0.6 20100505: C extension. 0.7 20100606: integrate 2.4 and 2.5. +0.8 20100619: fix multibyte object name. +0.9 20100626: refactoring. ''' - -############################################################################### -# import -############################################################################### import os import sys -import math # C extension from meshio import mqo @@ -45,6 +42,21 @@ if isBlender24(): # wrapper import bl24 as bl + + def createMqoMaterial(m): + material = Blender.Material.New( + m.getName().encode(bl.INTERNAL_ENCODING)) + #material.mode |= Blender.Material.Modes.SHADELESS + # diffuse + material.rgbCol = [m.color.r, m.color.g, m.color.b] + material.alpha = m.color.a + # other + material.amb=m.ambient + material.spec=m.specular + material.hard=int(255 * m.power) + material.emit=m.emmit + return material + else: # for 2.5 import bpy @@ -53,596 +65,36 @@ else: # wrapper import bl25 as bl - -############################################################################### -# implement -############################################################################### -def has_mikoto(mqo): - return False - -if isBlender24(): - def create_objects(scene, mqo, root, materials, imageMap=None, scale=None): - """ - create blender mesh objects. - """ - # store hierarchy - stack=[root] - - objects=[] - for o in mqo.objects: - #print "%s:v(%d),f(%d)" % (o.name, len(o.vertices), len(o.faces)) - # create mesh - mesh = Blender.Mesh.New() - mesh_object=scene.objects.new(mesh, o.name.encode('utf-8')) - - # add hierarchy - stack_depth=len(stack)-1 - print(o.depth, stack_depth) - if o.depth=16: - print("over 16 materials!") - break - mesh.materials+=[materials[material_index]] - usedMaterials[material_index]=i - - # set face params - for i, f in enumerate(o.faces): - if not type(new_faces[i]) is int: - continue - - face=mesh.faces[new_faces[i]] - - uv_array=[] - for i in xrange(f.index_count): - uv_array.append(Blender.Mathutils.Vector( - f.getUV(i).x, - 1.0-f.getUV(i).y) - ) - try: - face.uv=uv_array - except Exception as msg: - #print msg - #print face.index, uv_array - pass - - if f.material_index in usedMaterials: - face.mat = usedMaterials[f.material_index] - - face.smooth = 1 - - # rmeove dummy 0 vertex - mesh.verts.delete(0) - - mesh.mode |= Blender.Mesh.Modes.AUTOSMOOTH - mesh.maxSmoothAngle = int(o.smoothing) - mesh.smooth() - mesh.calcNormals() - mesh.flipNormals() - mesh.update() - - # mirror modifier - if o.mirror: - mod=mesh_object.modifiers.append(Blender.Modifier.Types.MIRROR) - - return objects - - - 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 e12 > e01 - self.iHead=i1 - self.iTail=i2 - self.iUp=i0 - else: - if sqNorm0 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 + def createMqoMaterial(m): + material = bpy.data.materials.new(m.getName()) + # shader + if m.shader==1: + material.diffuse_shader='FRESNEL' 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() - + material.diffuse_shader='LAMBERT' + # diffuse + material.diffuse_color=[m.color.r, m.color.g, m.color.b] + material.diffuse_intensity=m.diffuse + material.alpha=m.color.a + # other + material.ambient = m.ambient + #material.specular = m.specular + material.emit=m.emit + return material -else: - def create_objects(scene, mqo, parent, materials, imageMap, scale): - for o in mqo.objects: +def has_mikoto(mqo): + #for o in mqo.objects: + # if o.getName().startswith('bone'): + # return True + # if o.getName().startswith('sdef'): + # return True + # if o.getName().startswith('anchor'): + # return True + return False - # create mesh - mesh=bpy.data.meshes.new("Mesh") - meshObject= bpy.data.objects.new(o.getName(), mesh) - scene.objects.link(meshObject) - meshObject.parent=parent - # count triangle and quadrangle - faceCount=0 - for f in o.faces: - if f.index_count==3 or f.index_count==4: - faceCount+=1 - mesh.add_geometry(len(o.vertices), 0, faceCount) - - # add vertex - unpackedVertices=[] - for v in o.vertices: - # convert right-handed y-up to right-handed z-up - unpackedVertices.extend( - (scale*v.x, scale*-v.z, scale*v.y)) - mesh.verts.foreach_set("co", unpackedVertices) - - # add face - unpackedFaces = [] - usedMaterial=set() - - def getFace(f): - face = [] - for i in range(f.index_count): - face.append(f.getIndex(i)) - return face - - for f in o.faces: - face=getFace(f) - if len(face) != 3 and len(face) != 4: - print("{0} vertices in face.".format(len(face))) - continue - - if len(face) == 4: - if face[3] == 0: - # rotate indices if the 4th is 0 - face = [face[3], face[0], face[1], face[2]] - elif len(face) == 3: - if face[2] == 0: - # rotate indices if the 3rd is 0 - face = [face[2], face[0], face[1], 0] - else: - face.append(0) - - unpackedFaces.extend(face) - usedMaterial.add(f.material_index) - try: - mesh.faces.foreach_set("verts_raw", unpackedFaces) - except: - #print([getFace(f) for f in o.faces]) - print("fail to mesh.faces.foreach_set") - return - - # add material - meshMaterialMap={} - materialIndex=0 - for i in usedMaterial: - mesh.add_material(materials[i]) - meshMaterialMap[i]=materialIndex - materialIndex+=1 - - # each face - mesh.add_uv_texture() - for mqo_face, blender_face, uv_face in zip( - o.faces, mesh.faces, mesh.uv_textures[0].data): - if mqo_face.index_count<3: - continue - blender_face.material_index=meshMaterialMap[mqo_face.material_index] - if mqo_face.index_count>=3: - uv_face.uv1=[mqo_face.getUV(0).x, 1.0-mqo_face.getUV(0).y] - uv_face.uv2=[mqo_face.getUV(1).x, 1.0-mqo_face.getUV(1).y] - uv_face.uv3=[mqo_face.getUV(2).x, 1.0-mqo_face.getUV(2).y] - if mqo_face.index_count==4: - uv_face.uv4=[ - mqo_face.getUV(3).x, 1.0-mqo_face.getUV(3).y] - if materials[mqo_face.material_index] in imageMap: - uv_face.image=imageMap[mqo_face.material_index] - uv_face.tex=True - - mesh.update() - - -def __createMaterials(scene, mqo, directory): +def __createMaterials(mqo, directory): """ create blender materials and renturn material list. """ @@ -652,7 +104,7 @@ def __createMaterials(scene, mqo, directory): if len(mqo.materials)>0: for material_index, m in enumerate(mqo.materials): # material - material=bl.createMaterial(m) + material=createMqoMaterial(m) materials.append(material) # texture texture_name=m.getTexture() @@ -670,81 +122,531 @@ def __createMaterials(scene, mqo, directory): # texture if os.path.exists(path): print("create texture:", path) - texture, image=bl.createTexture(path) + texture, image=bl.texture.create(path) textureMap[texture_name]=texture imageMap[material_index]=image else: print("%s not exits" % path) continue - bl.materialAddTexture(material, texture) + bl.material.addTexture(material, texture) else: # default material pass return materials, imageMap -def __execute(filename, scene, scale=1.0): +def __createObjects(mqo, root, materials, imageMap, scale): + """ + create blender mesh objects. + """ + # tree stack + stack=[root] + objects=[] + for o in mqo.objects: + mesh, mesh_object=bl.mesh.create(o.getName()) + + # add hierarchy + stack_depth=len(stack)-1 + #print(o.depth, stack_depth) + if o.depth=16: + # split a mesh ? + print("over 16 materials!") + break + bl.mesh.addMaterial(mesh, materials[material_index]) + materialMap[material_index]=i + + # set face params + assert(len(o.faces)==len(mesh.faces)) + bl.mesh.addUV(mesh) + for i, (f, face) in enumerate(zip(o.faces, mesh.faces)): + uv_array=[] + # ToDo FIX + # flip face + for j in reversed(range(f.index_count)): + uv_array.append((f.getUV(j).x, 1.0-f.getUV(j).y)) + bl.mesh.setFaceUV(mesh, i, face, uv_array, + imageMap.get(f.material_index, None)) + if f.material_index in materialMap: + bl.face.setMaterial(face, materialMap[f.material_index]) + bl.face.setSmooth(face, True) + + # mirror modifier + if o.mirror: + bl.modifier.addMirror(mesh_object) + + # set smoothing + bl.mesh.setSmooth(mesh, o.smoothing) + + # calc normal + bl.mesh.recalcNormals(mesh_object) + + return objects + + +############################################################################### +# 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.getIndex(0) + i1=face.getIndex(1) + i2=face.getIndex(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 e12 > e01 + self.iHead=i1 + self.iTail=i2 + self.iUp=i0 + else: + if sqNorm0 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(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$BJ}<0%\!<%s$N%"%s%+!<%&%'%$%H7W;;MQ!#(B + ($BIT40A4(B) + """ + __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$BJ}<0%9%1%k%H%s$N%"%s%+!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 __execute(filename, scene, scale=0.1): # parse file io=mqo.IO() if not io.read(filename): - print("fail to load",filename) + bl.message("fail to load %s" % filename) return # create materials - materials, imageMap=__createMaterials(scene, io, os.path.dirname(filename)) + materials, imageMap=__createMaterials(io, os.path.dirname(filename)) + if len(materials)==0: + materials.append(bl.material.create('default')) # create objects - root=bl.createEmptyObject(scene, os.path.basename(filename)) - objects=create_objects(scene, io, root, materials, imageMap, scale) + root=bl.object.createEmpty(os.path.basename(filename)) + objects=__createObjects(io, root, materials, imageMap, scale) if has_mikoto(io): # create mikoto bone - armature_object=create_armature(scene, io) + armature_object=create_armature(io) if armature_object: root.makeParent([armature_object]) # create bone weight - create_bone_weight(scene, io, armature_object, objects) + create_bone_weight(io, armature_object, objects) ############################################################################### # register ############################################################################### if isBlender24(): + # for 2.4 def execute_24(filename): - """ - import a mqo file. - """ - filename=filename.decode(bl.INTERNAL_ENCODING) - print("##start mqo_import.py##") - print(bl.INTERNAL_ENCODING, bl.FS_ENCODING) - print("parse mqo file: %s" % (filename)) - - Blender.Window.WaitCursor(1) - t = Blender.sys.time() - - # execute - scene = Blender.Scene.GetCurrent() - __execute(filename, scene) - scene.update(0) - - print('finished in %.2f seconds' % (Blender.sys.time()-t)) - print('') - Blender.Redraw() - Blender.Window.WaitCursor(0) + scene=Blender.Scene.GetCurrent() + bl.initialize('mqo_import', scene) + __execute( + filename.decode(bl.INTERNAL_ENCODING), + scene) + bl.finalize() - # for 2.4 # execute Blender.Window.FileSelector(execute_24, 'Import MQO', '*.mqo') -else: - def execute_25(filename, context, scale): - """ - import a mqo file. - """ - __execute(filename, context.scene, scale) +else: # for 2.5 - # import operator + def execute_25(filename, scene, scale): + bl.initialize('mqo_import', scene) + __execute(filename, scene, scale) + bl.finalize() + + # operator class IMPORT_OT_mqo(bpy.types.Operator): '''Import from Metasequoia file format (.mqo)''' bl_idname = "import_scene.mqo" @@ -768,10 +670,13 @@ else: name="Scale", description="Scale the MQO by this value", min=0.0001, max=1000000.0, - soft_min=0.001, soft_max=100.0, default=1.0) + soft_min=0.001, soft_max=100.0, default=0.1) def execute(self, context): - execute_25(self.properties.path, context, self.properties.scale) + execute_25( + self.properties.path, + context.scene, + self.properties.scale) return 'FINISHED' def invoke(self, context, event): @@ -782,7 +687,8 @@ else: # register menu def menu_func(self, context): - self.layout.operator(IMPORT_OT_mqo.bl_idname, + self.layout.operator( + IMPORT_OT_mqo.bl_idname, text="Metasequoia (.mqo)") def register():