From: ousttrue Date: Sun, 6 Jun 2010 06:33:50 +0000 (+0900) Subject: implement mqo_import.py. X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=0710cd5d240c27f020a27dae7ed3faae54f8cdb1;p=meshio%2Fmeshio.git implement mqo_import.py. --- diff --git a/swig/blender/bl24.py b/swig/blender/bl24.py index a9ee110..fb180c1 100644 --- a/swig/blender/bl24.py +++ b/swig/blender/bl24.py @@ -2,6 +2,8 @@ import sys import os import Blender +from Blender import Mathutils + # $B%U%!%$%k%7%9%F%`$NJ8;z%3!<%I(B # $B2~B$HG$H$N6&MQ$N$?$a(B @@ -11,12 +13,14 @@ if os.path.exists(os.path.dirname(sys.argv[0])+"/utf8"): else: INTERNAL_ENCODING=FS_ENCODING + def createEmptyObject(scene, name): empty=scene.objects.new("Empty") empty.setName(name) return empty -def createMaterial(m): + +def createMqoMaterial(m): material = Blender.Material.New(m.getName().encode(INTERNAL_ENCODING)) material.mode |= Blender.Material.Modes.SHADELESS material.rgbCol = [m.color.r, m.color.g, m.color.b] @@ -26,6 +30,7 @@ def createMaterial(m): material.hard = int(255 * m.power) return material + def createTexture(path): image = Blender.Image.Load(path.encode(INTERNAL_ENCODING)) texture = Blender.Texture.New(path.encode(INTERNAL_ENCODING)) @@ -33,7 +38,476 @@ def createTexture(path): texture.image = image return texture, image + def materialAddTexture(material, texture): material.mode = material.mode | Blender.Material.Modes.TEXFACE material.setTexture(0, texture, Blender.Texture.TexCo.UV) + +def createMesh(scene, name): + mesh = Blender.Mesh.New() + mesh_object=scene.objects.new(mesh, name.encode(INTERNAL_ENCODING)) + return mesh, mesh_object + + +def objectMakeParent(parent, child): + parent.makeParent([child]) + + +def meshAddMqoGeometry(mesh, o, materials, imageMap, scale): + # add vertices + mesh.verts.extend(Mathutils.Vector(0, 0, 0)) # dummy + mesh.verts.extend([(v.x, -v.z, v.y) for v in o.vertices]) + # add faces + mesh_faces=[] + for face in o.faces: + face_indices=[] + for i in xrange(face.index_count): + face_indices.append(face.getIndex(i)+1) + mesh_faces.append(face_indices) + #new_faces=mesh.faces.extend([face.indices for face in o.faces], + new_faces=mesh.faces.extend(mesh_faces, + #ignoreDups=True, + indexList=True) + mesh.update() + + # gather used materials + materialMap = {} + if new_faces: + for i in new_faces: + if type(i) is int: + materialMap[o.faces[i].material_index]=True + + # blender limits 16 materials per mesh + # separate mesh ? + for i, material_index in enumerate(materialMap.keys()): + if i>=16: + print("over 16 materials!") + break + mesh.materials+=[materials[material_index]] + materialMap[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 materialMap: + face.mat = materialMap[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) + +############################################################################### +# 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 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 + 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() + diff --git a/swig/blender/bl25.py b/swig/blender/bl25.py index b8a1a50..e344c8e 100644 --- a/swig/blender/bl25.py +++ b/swig/blender/bl25.py @@ -1,12 +1,14 @@ import bpy import os + def createEmptyObject(scene, name): empty=bpy.data.objects.new(name, None) scene.objects.link(empty) return empty -def createMaterial(m): + +def createMqoMaterial(m): material = bpy.data.materials.new(m.getName()) material.diffuse_color=[m.color.r, m.color.g, m.color.b] material.alpha=m.color.a @@ -15,6 +17,7 @@ def createMaterial(m): material.emit=1.0 return material + def createTexture(path): texture=bpy.data.textures.new(os.path.basename(path)) texture.type='IMAGE' @@ -26,7 +29,101 @@ def createTexture(path): texture.use_alpha = True return texture, image + def materialAddTexture(material, texture): #material.add_texture(texture, "UV", {"COLOR", "ALPHA"}) material.add_texture(texture, "UV", "COLOR") + +def createMesh(scene, name): + mesh=bpy.data.meshes.new("Mesh") + mesh_object= bpy.data.objects.new(name, mesh) + scene.objects.link(mesh_object) + return mesh, mesh_object + + +def objectMakeParent(parent, child): + child.parent=parent + + +def meshAddMqoGeometry(mesh, o, materials, imageMap, scale): + # 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() + + diff --git a/swig/blender/mqo_import.py b/swig/blender/mqo_import.py index 038ddf0..34334bd 100644 --- a/swig/blender/mqo_import.py +++ b/swig/blender/mqo_import.py @@ -54,593 +54,9 @@ else: 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 - 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() - - - -else: - def create_objects(scene, mqo, parent, materials, imageMap, scale): - for o in mqo.objects: - - # 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): """ @@ -652,7 +68,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=bl.createMqoMaterial(m) materials.append(material) # texture texture_name=m.getTexture() @@ -683,6 +99,40 @@ def __createMaterials(scene, mqo, directory): return materials, imageMap +def __createObjects(scene, mqo, root, materials, imageMap, scale=1.0): + """ + create blender mesh objects. + """ + # store hierarchy + stack=[root] + objects=[] + for o in mqo.objects: + mesh, mesh_object=bl.createMesh(scene, o.getName()) + + # add hierarchy + stack_depth=len(stack)-1 + print(o.depth, stack_depth) + if o.depth