OSDN Git Service

implement vertex attributes and face attributes.
[meshio/pymeshio.git] / blender26-meshio / import_pmx.py
index c317315..d04044d 100644 (file)
@@ -6,6 +6,8 @@ PMXモデルをインポートする。
 """
 import os
 from . import bl
+from .pymeshio import pmx
+from .pymeshio.pmx import reader
 
 
 def convert_coord(pos):
@@ -45,10 +47,11 @@ def __create_a_material(m, name, textures_and_images):
     material.preview_render_type='FLAT'
     material.use_transparency=True
     # texture
-    texture_index=bl.material.addTexture(material, textures_and_images[m.texture_index][0])
+    if m.texture_index!=-1:
+        bl.material.addTexture(material, textures_and_images[m.texture_index][0])
     return material
 
-def __create_armature(bones):
+def __create_armature(bones, display_slots):
     """
     armatureを作成する
 
@@ -58,8 +61,8 @@ def __create_armature(bones):
     """
     armature, armature_object=bl.armature.create()
 
-    bl.armature.makeEditable(armature_object)
     # create bones
+    bl.armature.makeEditable(armature_object)
     def create_bone(b):
         bone=bl.armature.createBone(armature, b.name)
         # bone position
@@ -74,6 +77,7 @@ def __create_armature(bones):
 
     # build skeleton
     for b, bone in zip(bones, bl_bones):
+        assert(b.name==bone.name)
         if b.parent_index!=-1:
             print("%s -> %s" % (bones[b.parent_index].name, b.name))
             parent_bone=bl_bones[b.parent_index]
@@ -85,11 +89,38 @@ def __create_armature(bones):
                 bl.bone.setConnected(tail_bone)
         else:
             print("no parent %s" % b.name)
+    bl.armature.update(armature)
 
-    # fix
+    # create ik constraint
+    bl.enterObjectMode()
+    pose = bl.object.getPose(armature_object)
+    for b, bone in zip(bones, bl_bones):
+        if b.getIkFlag():
+            ik=b.ik
+            assert(len(ik.link)<16)
+            p_bone=pose.bones[bones[ik.target_index].name]
+            assert(p_bone)
+            constraint=bl.armature.createIkConstraint(
+                    armature_object, p_bone, bone.name,
+                    ik.link, ik.limit_radian, ik.loop)
+    bl.armature.makeEditable(armature_object)
     bl.armature.update(armature)
+
+    # create bone group
     bl.enterObjectMode()
+    pose = bl.object.getPose(armature_object)
+    for i, ds in enumerate(display_slots):
+        print(ds)
+        g=bl.object.createBoneGroup(armature_object, ds.name, "THEME%02d" % (i+1))
+        for t, index in ds.references:
+            if t==0:
+                name=bones[index].name
+                try:
+                    pose.bones[name].bone_group=g
+                except KeyError as e:
+                    print("pose %s is not found" % name)
 
+    bl.enterObjectMode()
     return armature_object
 
 def _execute(filepath):
@@ -99,7 +130,6 @@ def _execute(filepath):
     bl.progress_set('load %s' % filepath, 0.0)
     print(filepath)
 
-    from .pymeshio.pmx import reader
     model=reader.read_from_file(filepath)
     if not model:
         print("fail to load %s" % filepath)
@@ -117,7 +147,7 @@ def _execute(filepath):
     root_object[bl.MMD_COMMENT]=model.english_comment
 
     # armatureを作る
-    armature_object=__create_armature(model.bones)
+    armature_object=__create_armature(model.bones, model.display_slots)
     if armature_object:
         bl.object.makeParent(root_object, armature_object)
 
@@ -127,20 +157,17 @@ def _execute(filepath):
             for t in model.textures]
     print(textures_and_images)
 
-    def get_name(name, fmt, *args):
-        if len(name.encode("utf-8"))<16:
-            return name
-        else:
-            return fmt.format(*args)
     index_generator=(i for i in model.indices)
     # 頂点配列。(Left handed y-up) to (Right handed z-up)
     vertices=[convert_coord(pos)
             for pos in (v.position for v in model.vertices)]
+
+    # マテリアル毎にメッシュを作成する
     for i, m in enumerate(model.materials):
-        # マテリアル毎にメッシュを作成する
         print(m.name)
-        #material=__create_a_material(m, get_name(m.name, "material:{0:02}", i), textures_and_images)
+        # material作成
         material=__create_a_material(m, m.name, textures_and_images)
+        # object名はutf-8で21byteまで
         mesh, mesh_object=bl.mesh.create("object:{0:02}".format(i))
         bl.mesh.addMaterial(mesh, material)
         # activate object
@@ -153,12 +180,46 @@ def _execute(filepath):
         bl.mesh.addGeometry(mesh, vertices,
                 [(indices[i], indices[i+1], indices[i+2])
                     for i in range(0, len(indices), 3)])
+        assert(len(model.vertices), len(mesh.vertices))
+
+        # assign material
+        bl.mesh.addUV(mesh)
+        hasTexture=bl.material.hasTexture(material)
+        if hasTexture:
+            index_gen=(i for i in indices)
+            image=(textures_and_images.get[m.texture_index] 
+                    if m.texture_index in textures_and_images
+                    else None)
+        for i, face in enumerate(mesh.faces):
+            bl.face.setMaterial(face, 0)
+            if hasTexture:
+                uv0=model.vertices[next(index_gen)].uv
+                uv1=model.vertices[next(index_gen)].uv
+                uv2=model.vertices[next(index_gen)].uv
+                bl.mesh.setFaceUV(mesh, i, face, [# fix uv
+                    (uv0.x, 1.0-uv0.y),
+                    (uv1.x, 1.0-uv1.y),
+                    (uv2.x, 1.0-uv2.y)
+                    ],
+                    image)
+
         if armature_object:
             # armature modifirer
             bl.modifier.addArmature(mesh_object, armature_object)
-
-        # shape
-
+            # set vertex attributes(normal, bone weights)
+            bl.mesh.useVertexUV(mesh)
+            for i, (v,  mvert) in enumerate(zip(model.vertices, mesh.vertices)):
+                bl.vertex.setNormal(mvert, convert_coord(v.normal))
+                if isinstance(v.deform, pmx.Bdef1):
+                    bl.object.assignVertexGroup(mesh_object,
+                            model.bones[v.deform.index0].name, i, 1.0)
+                elif isinstance(v.deform, pmx.Bdef2):
+                    bl.object.assignVertexGroup(mesh_object,
+                            model.bones[v.deform.index0].name, i, v.deform.weight0)
+                    bl.object.assignVertexGroup(mesh_object,
+                            model.bones[v.deform.index1].name, i, 1.0-v.deform.weight0)
+                else:
+                    raise Exception("unknown deform: %s" % v.deform)
 
     return {'FINISHED'}