OSDN Git Service

integrate pmd_import for blender25.
[meshio/meshio.git] / swig / blender / bl25.py
index b8a1a50..1415e41 100644 (file)
@@ -1,12 +1,63 @@
+# coding: utf-8
 import bpy
+import mathutils
+
 import os
+import time
+import functools
+
+###############################################################################
+# ProgressBar
+###############################################################################
+class ProgressBar(object):
+    def __init__(self, base):
+        print("#### %s ####" % base)
+        self.base=base
+        self.start=time.time() 
+        self.set('<start>', 0)
+
+    def advance(self, message, progress):
+        self.progress+=float(progress)
+        self._print(message)
+
+    def set(self, message, progress):
+        self.progress=float(progress)
+        self._print(message)
+
+    def _print(self, message):
+        print(message)
+        message="%s: %s" % (self.base, message)
+        #Blender.Window.DrawProgressBar(self.progress, message)
+
+    def finish(self):
+        self.progress=1.0
+        message='finished in %.2f sec' % (time.time()-self.start)
+        self.set(message, 1.0)
+
+
+###############################################################################
+class Writer(object):
+    def __init__(self, path, encoding):
+        self.io=open(path, "wb")
+        self.encoding=encoding
+
+    def write(self, s):
+        self.io.write(s.encode(self.encoding))
+
+    def flush(self):
+        self.io.flush()
+
+    def close(self):
+        self.io.close()
 
+###############################################################################
 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 +66,20 @@ def createMaterial(m):
     material.emit=1.0
     return material
 
+def createPmdMaterial(m):
+    material = bpy.data.materials.new("Material")
+    material.diffuse_shader='TOON'
+    material.specular_shader='TOON'
+    material.diffuse_color=([m.diffuse.r, m.diffuse.g, m.diffuse.b])
+    material.alpha=m.diffuse.a
+    material.specular_hardness=int(m.shinness)
+    material.specular_color=([m.specular.r, m.specular.g, m.specular.b])
+    material.mirror_color=([m.ambient.r, m.ambient.g, m.ambient.b])
+    material.subsurface_scattering.enabled=True if m.flag==1 else False
+    # temporary
+    material.emit=1.0
+    return material
+
 def createTexture(path):
     texture=bpy.data.textures.new(os.path.basename(path))
     texture.type='IMAGE'
@@ -26,7 +91,340 @@ 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 meshAddMaterial(mesh, material):
+    mesh.add_material(material)
+
+
+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()
+
+def getTexture(m, dirname):
+    tex=""
+    aplane=""
+    # texture
+    for slot in m.texture_slots:
+        if slot and slot.texture:
+            texture=slot.texture
+            if  texture.type=="IMAGE":
+                image=texture.image
+                if not image:
+                    continue
+                imagePath=image.filename
+                if len(dirname)>0 and imagePath.startswith(dirname):
+                    # \e$BAjBP%Q%9$KJQ49$9$k\e(B
+                    imagePath=imagePath[len(dirname)+1:len(imagePath)]
+                #imagePath=Blender.sys.expandpath(
+                #        imagePath).replace("\\", '/')
+                if slot.map_colordiff:
+                    tex=" tex(\"%s\")" % imagePath
+                elif slot.map_alpha:
+                    aplane=" aplane(\"%s\")" % imagePath
+    return tex, aplane
+
+def objectDuplicate(scene, obj):
+    bpy.ops.object.select_all(action='DESELECT')
+    obj.selected=True
+    scene.objects.active=obj
+    bpy.ops.object.duplicate()
+    dumy=scene.objects.active
+    bpy.ops.object.rotation_apply()
+    bpy.ops.object.scale_apply()
+    bpy.ops.object.location_apply()
+    return dumy.data, dumy
+
+def objectDelete(scene, obj):
+    scene.objects.unlink(obj)
+
+def faceVertexCount(face):
+    return len(face.verts)
+
+def faceVertices(face):
+    return face.verts[:]
+
+def meshHasUV(mesh):
+    return mesh.active_uv_texture
+
+def faceHasUV(mesh, i, face):
+    return mesh.active_uv_texture.data[i]
+
+def faceGetUV(mesh, i, faces, count):
+    uvFace=mesh.active_uv_texture.data[i]
+    if count==3:
+        return (uvFace.uv1, uvFace.uv2, uvFace.uv3)
+    elif count==4:
+        return (uvFace.uv1, uvFace.uv2, uvFace.uv3, uvFace.uv4)
+    else:
+        print(count)
+        assert(False)
+
+def materialToMqo(m):
+    return "\"%s\" shader(3) col(%f %f %f %f)" % (
+            m.name, 
+            m.diffuse_color[0], m.diffuse_color[1], m.diffuse_color[2], 
+            m.alpha)
+
+def faceMaterialIndex(face):
+    return face.material_index
+
+def objectGetData(o):
+    return o.data
+
+def objectAddArmatureModifier(o, armature_object):
+    mod=o.modifiers.new("Modifier", "ARMATURE")
+    mod.object = armature_object
+    mod.use_bone_envelopes=False
+
+def objectSelect(o):
+    o.selected=True
+
+def objectGetPose(o):
+    return o.pose
+
+def poseBoneLimit(n, b):
+    if n.endswith("_t"):
+        return
+    if n.startswith("knee_"):
+        b.ik_dof_y=False
+        b.ik_dof_z=False
+        b.ik_dof_x=True
+        b.ik_limit_x=True
+        b.ik_min_x=0
+        b.ik_max_x=180
+    elif n.startswith("ankle_"):
+        #b.ik_dof_y=False
+        pass
+
+def enterEditMode():
+    bpy.ops.object.mode_set(mode='EDIT', toggle=False)
+
+def exitEditMode():
+    bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+
+def objectDeselectAll():
+    bpy.ops.object.select_all(action='DESELECT')
+
+def objectActivate(scene, o):
+    o.selected=True 
+    scene.objects.active=o
+
+def meshAddVertexGroup(meshObject, name):
+    meshObject.add_vertex_group(name)
+
+def vertexSetNormal(mvert, normal):
+    mvert.normal=mathutils.Vector(normal)
+
+def meshUseVertexUv(mesh):
+    pass
+
+def vertexSetUv(mvert, uv):
+    pass
+
+def meshAssignVertexGroup(meshObject, name, index, weight):
+    meshObject.add_vertex_to_group(index, 
+                meshObject.vertex_groups[name], weight, 'ADD')
+
+def meshCreateVerteicesAndFaces(mesh, vertices, faces):
+    vertexCount=int(len(vertices)/3)
+    faceCount=int(len(faces)/4)
+    mesh.add_geometry(vertexCount, 0, faceCount)
+    mesh.verts.foreach_set("co", vertices)
+    mesh.faces.foreach_set("verts_raw", faces)
+    assert(len(mesh.verts)==vertexCount)
+
+def meshAddUV(mesh):
+    mesh.add_uv_texture()
+
+def meshVertsDelete(mesh, remove_vertices):
+    enterEditMode()
+    bpy.ops.mesh.select_all(action='DESELECT')
+    for i in remove_vertices:
+        mesh.verts[i].selected=True
+    bpy.ops.mesh.delete(type='VERT')
+    exitEditMode()
+
+def createArmature(scene):
+    armature = bpy.data.armatures.new('Armature')
+    armature_object=bpy.data.objects.new('Armature', armature)
+    scene.objects.link(armature_object)
+
+    armature_object.x_ray=True
+    armature.draw_names=True
+    armature.drawtype='OCTAHEDRAL'
+    armature.deform_envelope=False
+    armature.deform_vertexgroups=True
+    armature.x_axis_mirror=True
+
+    return armature, armature_object
+
+def armatureMakeEditable(scene, armature_object):
+    # select only armature object and set edit mode
+    scene.objects.active=armature_object
+    bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+    bpy.ops.object.mode_set(mode='EDIT', toggle=False)
+
+def createIkConstraint(armature_object, p_bone, effector_name, ik):
+    constraint = p_bone.constraints.new('IK')
+    constraint.chain_length=len(ik.children)
+    constraint.target=armature_object
+    constraint.subtarget=effector_name
+    constraint.use_tail=False
+    return constraint
+
+def createArmatureBone(armature, name):
+    return armature.edit_bones.new(name)
+
+def boneSetConnected(bone):
+    bone.connected=True
+
+def createVector(x, y, z):
+    return mathutils.Vector([x, y, z])
+
+def armatureUpdate(armature):
+    pass
+
+def boneLayerMask(bone, layers):
+    layer=[]
+    for i in range(32):
+        try:
+            layer.append(True if layers[i]!=0 else False)
+        except IndexError:
+            layer.append(False)
+    bone.layer=layer
+
+def objectPinShape(o):
+    o.shape_key_lock=True
+
+def objectAddShapeKey(o, name):
+    return o.add_shape_key(name)
+
+def objectActivateShapeKey(o, index):
+    o.active_shape_key_index=index
+
+def shapeKeyAssign(shapeKey, index, pos):
+    shapeKey.data[index].co=pos
+
+def objectIsVisible(obj):
+    return obj.restrict_view
+
+def meshVertexGroupNames(meshObject):
+    for g in meshObject.vertex_groups:
+        yield g.name
+
+def faceNormal(face):
+    return face.normal
+
+def meshFaceUv(mesh, i, face):
+    return mesh.uv_textures[0].data[i].uv
+
+def armatureModifierGetObject(m):
+    return m.object
+
+def objectHasShapeKey(o):
+    return o.data.shape_keys
+
+def objectShapeKeys(o):
+    return o.data.shape_keys.keys
+
+def meshVertexGroup(meshObject, name):
+    for i, v in enumerate(meshObject.data.verts):
+        for g in v.groups:
+            if meshObject.vertex_groups[g.group].name==name:
+                yield(i)
+
+def materialGet(scene, material_name):
+    return bpy.data.materials[material_name]
+