OSDN Git Service

pmd. sort material order.
[meshio/meshio.git] / swig / blender24 / pmd_import.py
index 5141ff9..3c85823 100644 (file)
@@ -7,7 +7,7 @@
  Tooltip: 'Import PMD file for MikuMikuDance.'
 """
 __author__= ["ousttrue"]
-__version__= "0.8"
+__version__= "1.0"
 __url__=()
 __bpydoc__="""
 0.1: 20091126
@@ -18,6 +18,7 @@ __bpydoc__="""
 0.6: 20100416 fix fornt face. texture load fail safe. add progress.
 0.7: 20100506 C extension.
 0.8: 20100521 add shape_key group.
+1.0: 20100530 add invisilbe bone tail(armature layer 2).
 """
 import Blender
 from Blender import Mathutils
@@ -41,6 +42,9 @@ else:
 MMD_SHAPE_GROUP_NAME='_MMD_SHAPE'
 
 
+###############################################################################
+# ProgressBar
+###############################################################################
 class ProgressBar(object):
     def __init__(self, base):
         print "#### %s ####" % base
@@ -60,7 +64,7 @@ class ProgressBar(object):
         print message
         message="%s: %s" % (self.base, message)
         if message.__class__ is unicode:
-            message=message.encode(INTERNAL_ENCODING)
+            message=message.encode(FS_ENCODING)
         Blender.Window.DrawProgressBar(self.progress, message)
 
     def finish(self):
@@ -85,6 +89,9 @@ def progress_set(message, progress):
     progressBar.set(message, progress)
 
 
+###############################################################################
+# functions
+###############################################################################
 def convert_coord(pos):
     """
     Left handed y-up to Right handed z-up
@@ -211,10 +218,10 @@ def import16MaerialAndMesh(mesh, l, material_order, face_map, tex_dir):
         material=createMaterial()
         material.setRGBCol([m.diffuse.r, m.diffuse.g, m.diffuse.b])
         material.setAlpha(m.diffuse.a)
-        print(m.shinness)
-        material.setHardness(int(m.shinness))
+        material.setSpec(m.shinness*0.1)
         material.setSpecCol([m.specular.r, m.specular.g, m.specular.b])
         material.setMirCol([m.ambient.r, m.ambient.g, m.ambient.b])
+        material.enableSSS=True if m.flag==1 else False
         # set texture
         if m.getTexture()!='':
             tex_file=re.compile('\*.*.spa$').sub('', m.getTexture())
@@ -269,6 +276,10 @@ def import16MaerialAndMesh(mesh, l, material_order, face_map, tex_dir):
     mesh_face_indices=[]
     mesh_face_materials=[]
     used_vertices=set()
+
+    def degenerate(i0, i1, i2):
+        return i0==i1 or i1==i2 or i2==i0
+
     for material_index in material_order:
         face_offset=face_map[material_index]
         m=l.materials[material_index]
@@ -277,13 +288,16 @@ def import16MaerialAndMesh(mesh, l, material_order, face_map, tex_dir):
             i0=material_faces[j]
             i1=material_faces[j+1]
             i2=material_faces[j+2]
-            mesh_face_indices.append([i0, i1, i2])
+            triangle=[i0, i1, i2]
+            if degenerate(*triangle):
+                continue
+            mesh_face_indices.append(triangle)
             mesh_face_materials.append(material_index)
             used_vertices.add(i0)
             used_vertices.add(i1)
             used_vertices.add(i2)
+
     mesh.faces.extend(mesh_face_indices, ignoreDups=True)
-    assert(len(mesh.faces)==len(mesh_face_indices))
 
     # face params
     used_map={}
@@ -324,36 +338,56 @@ def import16MaerialAndMesh(mesh, l, material_order, face_map, tex_dir):
     return vertex_map
 
 
-def build_bone(armature, b, parent=None):
-    if b.tail_index==0:
-        return
+class Builder(object):
+    def __init__(self):
+        self.boneMap={}
+
+    def build(self, armature, bones):
+        for b in bones:
+            if not b.parent:
+                self.__build(armature, b, None, None)
+        armature.update()
+
+    def __build(self, armature, b, p, parent):
+        name=englishmap.getEnglishBoneName(b.getName())
+        if not name:
+            name=b.getName().encode(INTERNAL_ENCODING)
+        self.boneMap[name]=b
+
+        bone=Blender.Armature.Editbone()
+        bone.name=name
+        armature.bones[name]=bone
+
+        if b.tail_index==0:
+            # 先端
+            assert(b.type==6 or b.type==7)
+            bone.head = Mathutils.Vector(*convert_coord(b.pos))
+            bone.tail=bone.head+Mathutils.Vector(0, 1, 0)
+            assert(parent)
+            bone.parent=parent
+            if bone.name=="center_t":
+                # センターボーンは(0, 1, 0)の方向を向いていないと具合が悪い
+                parent.tail=parent.head+Mathutils.Vector(0, 1, 0)
+                bone.head=parent.tail
+                bone.tail=bone.head+Mathutils.Vector(0, 1, 0)
+            else:
+                assert(parent.tail==bone.head)
+            bone.options=[Blender.Armature.CONNECTED]
+            # armature layer 2
+            bone.layerMask = (1<<1)
+        else:
+            bone.head = Mathutils.Vector(*convert_coord(b.pos))
+            bone.tail = Mathutils.Vector(*convert_coord(b.tail))
+            if parent:
+                bone.parent=parent
+                if parent.tail==bone.head:
+                    bone.options=[Blender.Armature.CONNECTED]
 
-    bone = Blender.Armature.Editbone()
-    name=englishmap.getEnglishBoneName(b.getName())
-    bone.name = name if name else b.getName().encode(
-            INTERNAL_ENCODING)
-    armature.bones[bone.name] = bone
-    if parent:
-        bone.head = Mathutils.Vector(*convert_coord(b.pos))
-        bone.parent=parent
-        options=[]
-        if parent.tail==bone.head:
-            options.append(Blender.Armature.CONNECTED)
-        bone.options=options
-        bone.tail = Mathutils.Vector(*convert_coord(b.tail))
         if bone.head==bone.tail:
-            bone.tail=bone.head-Mathutils.Vector(0, 1, 0)
-    elif b.__class__ is pmd.BONE_IK:
-        bone.head = Mathutils.Vector(*convert_coord(b.pos))
-        bone.tail = Mathutils.Vector(*convert_coord(b.tail))
-    else:
-        # center
-        tail=Mathutils.Vector(*convert_coord(b.pos))
-        bone.tail = tail
-        bone.head = tail-Mathutils.Vector(0, 1, 0)
+            bone.tail=bone.head+Mathutils.Vector(0, 1, 0)
 
-    for child in b.children:
-        build_bone(armature, child, bone)
+        for c in b.children:
+            self.__build(armature, c, b, bone)
 
 
 def importArmature(scene, l):
@@ -369,16 +403,19 @@ def importArmature(scene, l):
             armature_object.drawMode | Blender.Object.DrawModes.XRAY)
     # armature settings
     armature.drawType = Blender.Armature.OCTAHEDRON
+    armature.drawNames=True
     armature.envelopes = False
     armature.vertexGroups = True
     armature.mirrorEdit = True
 
     # create armature
     armature.makeEditable()
-    for b in l.bones:
-        if not b.parent:
-            build_bone(armature, b)
-    armature.update()
+
+    ############################################################
+    # build bone
+    ############################################################
+    builder=Builder()
+    builder.build(armature, l.bones)
 
     ############################################################
     # IK
@@ -388,8 +425,7 @@ def importArmature(scene, l):
     for ik in l.ik_list:
         # IKtarget->parent(=IK).name
         target=l.bones[ik.target]
-        parent=l.bones[target.parent_index]
-        name = englishmap.getEnglishBoneName(parent.getName())
+        name = englishmap.getEnglishBoneName(target.getName())
         p_bone = pose.bones[name]
         if not p_bone:
             print 'not found', name
@@ -398,20 +434,21 @@ def importArmature(scene, l):
             print 'over MAX_CHAINLEN', ik, len(ik.children)
             continue
         # IK solver
-        ik_const = p_bone.constraints.append(Blender.Constraint.Type.IKSOLVER)
-        ik_const[cSetting.CHAINLEN] = len(ik.children)
-        ik_const[cSetting.TARGET] = armature_object
-        ik_const[cSetting.BONE] = englishmap.getEnglishBoneName(
+        ik_solver = p_bone.constraints.append(Blender.Constraint.Type.IKSOLVER)
+        ik_solver[cSetting.CHAINLEN]=len(ik.children)
+        ik_solver[cSetting.TARGET]=armature_object
+        ik_solver[cSetting.USETIP]=False
+
+        effector_name=englishmap.getEnglishBoneName(
                 l.bones[ik.index].getName())
-        # Limit ROT
-        lrot_const = p_bone.constraints.append(Blender.Constraint.Type.LIMITROT)
-        lrot_const.influence = ik.weight
-        lrot_const[cSetting.OWNERSPACE] = cSetting.SPACE_LOCAL
-        lrot_const[cSetting.LIMIT] = (cSetting.LIMIT_XROT | cSetting.LIMIT_ZROT)
-        lrot_const[cSetting.XMIN] = ik.iterations
-        lrot_const[cSetting.XMAX] = 180
-        lrot_const[cSetting.ZMIN] = 180 - ik.iterations
-        lrot_const[cSetting.ZMAX] = 0
+        if not effector_name:
+            effector_name=l.bones[ik.index].getName()
+
+        ik_solver[cSetting.BONE]=effector_name
+        #ik_solver.influence=ik.weight
+        # not used. place folder when export.
+        ik_solver[cSetting.ROTWEIGHT]=ik.weight
+        ik_solver[cSetting.ITERATIONS]=ik.iterations * 10
 
     armature.makeEditable()
     armature.update()
@@ -519,9 +556,6 @@ def run(filename):
     # load pmd
     progress_set('load %s' % filename, 0.0)
 
-    import locale
-    locale.setlocale(locale.LC_ALL, '')
-
     l=pmd.IO()
     if not l.read(filename):
         print "fail to load %s" % filename
@@ -538,7 +572,7 @@ def run(filename):
     # import objects container
     root=scene.objects.new("Empty")
     root.setName(
-            l.english_model_name if len(l.english_model_name)>0 else l.getName().encode(INTERNAL_ENCODING))
+            l.english_name if len(l.english_name)>0 else l.getName().encode(INTERNAL_ENCODING))
 
     # import mesh
     mesh_objects=importMesh(scene, l, tex_dir)
@@ -548,7 +582,6 @@ def run(filename):
     armature_object=importArmature(scene, l)
     if armature_object:
         armature = armature_object.getData()
-        armature.drawNames=True
         root.makeParent([armature_object])
 
         # add armature modifier
@@ -556,8 +589,24 @@ def run(filename):
             mod=o.modifiers.append(Blender.Modifier.Types.ARMATURE)
             mod[Blender.Modifier.Settings.OBJECT] = armature_object
             mod[Blender.Modifier.Settings.ENVELOPES] = False
-            o.makeDisplayList()
+            #o.makeDisplayList()
+
+        ############################################################
+        # Limitation
+        ############################################################
+        for n, b in armature_object.getPose().bones.items():
+            if n.endswith("_t"):
+                continue
+
+            if n.startswith("knee_"):
+                b.lockYRot=True
+                b.lockZRot=True
+                b.limitX=True
+                b.limitMin=[0, 0, 0]
+                b.limitMax=[180, 0, 0]
+            elif n.startswith("ankle_"):
+                b.lockYRot=True
+
     # redraw
     scene.update(0)