OSDN Git Service

fix IK.
[meshio/meshio.git] / swig / blender24 / pmd_import.py
index a13cc4a..5af4cec 100644 (file)
@@ -41,6 +41,9 @@ else:
 MMD_SHAPE_GROUP_NAME='_MMD_SHAPE'
 
 
+###############################################################################
+# ProgressBar
+###############################################################################
 class ProgressBar(object):
     def __init__(self, base):
         print "#### %s ####" % base
@@ -60,7 +63,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 +88,9 @@ def progress_set(message, progress):
     progressBar.set(message, progress)
 
 
+###############################################################################
+# functions
+###############################################################################
 def convert_coord(pos):
     """
     Left handed y-up to Right handed z-up
@@ -331,16 +337,6 @@ def import16MaerialAndMesh(mesh, l, material_order, face_map, tex_dir):
     return vertex_map
 
 
-def validParent(parent):
-    if parent==None:
-        return False
-    if parent.name.startswith("arm twist"):
-        return False
-    if parent.name.startswith("wrist twist"):
-        return False
-    return True
-
-
 class Builder(object):
     def __init__(self):
         self.boneMap={}
@@ -349,6 +345,7 @@ class Builder(object):
         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())
@@ -356,54 +353,39 @@ class Builder(object):
             name=b.getName().encode(INTERNAL_ENCODING)
         self.boneMap[name]=b
 
-        if b.tail_index==0:
-            return
-
         bone=Blender.Armature.Editbone()
         bone.name=name
-        armature.bones[name] = bone
+        armature.bones[name]=bone
 
-        if bone.name=='center':
-            # center
-            pos=Mathutils.Vector(*convert_coord(b.pos))
-            bone.tail = pos
-            bone.head = pos-Mathutils.Vector(0, 0.01, 0)
+        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)
+            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 validParent(parent):
+            if parent:
                 bone.parent=parent
                 if parent.tail==bone.head:
-                    bone.parent=parent
                     bone.options=[Blender.Armature.CONNECTED]
 
-            if bone.head==bone.tail:
-                bone.tail=bone.head-Mathutils.Vector(0, 1, 0)
+        if bone.head==bone.tail:
+            bone.tail=bone.head+Mathutils.Vector(0, 1, 0)
 
         for c in b.children:
             self.__build(armature, c, b, bone)
 
-    def connect(self, armature):
-        def getKey(index):
-            for key, value in self.boneMap.items():
-                if index==value.index:
-                    return key
-
-        for k, b in self.boneMap.items():
-            if b.tail_index==0:
-                continue
-            bone=armature.bones[k]
-            key=getKey(b.tail_index)
-            if not key:
-                return
-            try:
-                tail=armature.bones[key]
-                # connect
-                tail.parent=bone
-                tail.options=[Blender.Armature.CONNECTED]
-            except:
-                pass
 
 def importArmature(scene, l):
     # create armature
@@ -418,6 +400,7 @@ 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
@@ -425,11 +408,11 @@ def importArmature(scene, l):
     # create armature
     armature.makeEditable()
 
+    ############################################################
+    # build bone
+    ############################################################
     builder=Builder()
     builder.build(armature, l.bones)
-    builder.connect(armature)
-
-    armature.update()
 
     ############################################################
     # IK
@@ -439,8 +422,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
@@ -449,26 +431,18 @@ 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_solver = p_bone.constraints.append(Blender.Constraint.Type.IKSOLVER)
+        ik_solver[cSetting.CHAINLEN] = len(ik.children)
+        ik_solver[cSetting.TARGET] = armature_object
 
         effector_name=englishmap.getEnglishBoneName(
                 l.bones[ik.index].getName())
         if not effector_name:
             effector_name=l.bones[ik.index].getName()
 
-        ik_const[cSetting.BONE] = effector_name
-        ik_const[cSetting.ITERATIONS]=ik.iterations
-        ik_const.influence = ik.weight
-        # Limit ROT
-        #lrot_const = p_bone.constraints.append(Blender.Constraint.Type.LIMITROT)
-        #lrot_const[cSetting.OWNERSPACE] = cSetting.SPACE_LOCAL
-        #lrot_const[cSetting.LIMIT] = (cSetting.LIMIT_XROT | cSetting.LIMIT_ZROT)
-        #lrot_const[cSetting.XMIN] = 0.1
-        #lrot_const[cSetting.XMAX] = 180
-        #lrot_const[cSetting.ZMIN] = 180 - 0.1
-        #lrot_const[cSetting.ZMAX] = 0
+        ik_solver[cSetting.BONE]=effector_name
+        #ik_solver.influence=ik.weight
+        ik_solver[cSetting.USETIP]=False
 
     armature.makeEditable()
     armature.update()
@@ -576,9 +550,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
@@ -605,7 +576,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
@@ -613,18 +583,23 @@ 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)