OSDN Git Service

fix normal
[meshio/pymeshio.git] / blender25-meshio / export_pmd.py
index 8fb08a5..6d31f67 100644 (file)
@@ -7,7 +7,7 @@
  Tooltip: 'Export PMD file for MikuMikuDance.'
 """
 __author__= ["ousttrue"]
-__version__= "2.4"
+__version__= "2.5"
 __url__=()
 __bpydoc__="""
 pmd Importer
@@ -29,6 +29,7 @@ This script exports a pmd model.
 2.2 20101005: update for Blender2.54.
 2.3 20101228: update for Blender2.55.
 2.4 20110429: update for Blender2.57b.
+2.5 20110522: implement RigidBody and Constraint.
 """
 
 bl_addon_info = {
@@ -116,7 +117,7 @@ def setMaterialParams(material, m):
     # flag
     material.flag=1 if m.subsurface_scattering.use else 0
     # toon
-    material.toon_index=7
+    material.toon_index=0
 
 def toCP932(s):
     return s.encode('cp932')
@@ -303,6 +304,29 @@ class IKSolver(object):
         self.weight=weight
 
 
+class SSS(object):
+    def __init__(self):
+        self.use=1
+
+
+class DefaultMatrial(object):
+    def __init__(self):
+        self.name='default'
+        # diffuse
+        self.diffuse_color=[1, 1, 1]
+        self.alpha=1
+        # specular
+        self.specular_toon_size=0
+        self.specular_hardness=5
+        self.specular_color=[1, 1, 1]
+        # ambient
+        self.mirror_color=[1, 1, 1]
+        # flag
+        self.subsurface_scattering=SSS()
+        # texture
+        self.texture_slots=[]
+
+
 class OneSkinMesh(object):
     __slots__=['vertexArray', 'morphList', 'rigidbodies', 'constraints', ]
     def __init__(self):
@@ -357,7 +381,11 @@ class OneSkinMesh(object):
                 for g in v.groups:
                     setWeight(i, obj.vertex_groups[g.group].name, g.weight)
             else:
-                setWeight(i, obj.vertex_groups[0].name, 1)
+                try:
+                    setWeight(i, obj.vertex_groups[0].name, 1)
+                except:
+                    # no vertex_groups
+                    pass
 
         # 合計値が1になるようにする
         for i in xrange(len(mesh.vertices)):
@@ -374,10 +402,14 @@ class OneSkinMesh(object):
         return weightMap, secondWeightMap
 
     def __processFaces(self, obj_name, mesh, weightMap, secondWeightMap):
+        default_material=DefaultMatrial()
         # 各面の処理
         for i, face in enumerate(mesh.faces):
             faceVertexCount=bl.face.getVertexCount(face)
-            material=mesh.materials[bl.face.getMaterialIndex(face)]
+            try:
+                material=mesh.materials[bl.face.getMaterialIndex(face)]
+            except IndexError as e:
+                material=default_material
             v=[mesh.vertices[index] for index in bl.face.getVertices(face)]
             uv=bl.mesh.getFaceUV(
                     mesh, i, face, bl.face.getVertexCount(face))
@@ -465,21 +497,32 @@ class OneSkinMesh(object):
         if CONSTRAINT_A in obj:
             return
 
-        #if not bl.modifier.hasType(obj, 'ARMATURE'):
-        #    return
-
         bl.message("export: %s" % obj.name)
 
         # メッシュのコピーを生成してオブジェクトの行列を適用する
         copyMesh, copyObj=bl.object.duplicate(obj)
         if len(copyMesh.vertices)>0:
             # apply transform
-            copyObj.scale=obj.scale
-            bpy.ops.object.transform_apply(scale=True)
-            copyObj.rotation_euler=obj.rotation_euler
-            bpy.ops.object.transform_apply(rotation=True)
-            copyObj.location=obj.location
-            bpy.ops.object.transform_apply(location=True)
+            """
+            try:
+                # svn 36722
+                copyObj.scale=obj.scale
+                bpy.ops.object.transform_apply(scale=True)
+                copyObj.rotation_euler=obj.rotation_euler
+                bpy.ops.object.transform_apply(rotation=True)
+                copyObj.location=obj.location
+                bpy.ops.object.transform_apply(location=True)
+            except AttributeError as e:
+                # 2.57b
+                copyObj.scale=obj.scale
+                bpy.ops.object.scale_apply()
+                copyObj.rotation_euler=obj.rotation_euler
+                bpy.ops.object.rotation_apply()
+                copyObj.location=obj.location
+                bpy.ops.object.location_apply()
+            """
+            copyMesh.transform(obj.matrix_world)
+
             # apply modifier
             for m in [m for m in copyObj.modifiers]:
                 if m.type=='SOLIDFY':
@@ -533,7 +576,7 @@ class OneSkinMesh(object):
 
                 break
         assert(basis)
-        print(basis.name, len(baseMorph.offsets))
+        #print(basis.name, len(baseMorph.offsets))
 
         if len(baseMorph.offsets)==0:
             return
@@ -543,7 +586,7 @@ class OneSkinMesh(object):
             if b.name==BASE_SHAPE_NAME:
                 continue
 
-            print(b.name)
+            #print(b.name)
             morph=self.__getOrCreateMorph(b.name, 4)
             used=set()
             for index, src, dst in zip(
@@ -568,7 +611,7 @@ class OneSkinMesh(object):
             for i, v in enumerate(englishmap.skinMap):
                 if v[0]==morph.name:
                     return i
-            print(morph)
+            #print(morph)
             return len(englishmap.skinMap)
         self.morphList.sort(key=getIndex)
 
@@ -785,11 +828,14 @@ class BoneBuilder(object):
         if name=='':
             return 0
         else:
-            return self.getIndex(self.__boneByName(name))
+            try:
+                return self.getIndex(self.__boneByName(name))
+            except:
+                return 0
 
     def __boneByName(self, name):
         return self.boneMap[name]
-                    
+
     def __getBone(self, parent, b):
         if len(b.children)==0:
             parent.type=7
@@ -889,9 +935,10 @@ class PmdExporter(object):
             v.pos.x=pos[0]
             v.pos.y=pos[2]
             v.pos.z=pos[1]
+            # convert right-handed z-up to left-handed y-up
             v.normal.x=attribute.nx
-            v.normal.y=attribute.ny
-            v.normal.z=attribute.nz
+            v.normal.y=attribute.nz
+            v.normal.z=attribute.ny
             v.uv.x=attribute.u
             v.uv.y=1.0-attribute.v # reverse vertical
             v.bone0=self.skeleton.indexByName(b0)
@@ -903,15 +950,24 @@ class PmdExporter(object):
         vertexCount=self.oneSkinMesh.getVertexCount()
         for material_name, indices in self.oneSkinMesh.vertexArray.each():
             #print('material:', material_name)
-            m=bl.material.get(material_name)
+            try:
+                m=bl.material.get(material_name)
+            except KeyError as e:
+                m=DefaultMatrial()
             # マテリアル
             material=io.addMaterial()
             setMaterialParams(material, m)
 
             material.vertex_count=len(indices)
-            material.toon_index=0
-            textures=[os.path.basename(path) 
+            def get_texture_name(texture):
+                pos=texture.replace("\\", "/").rfind("/")
+                if pos==-1:
+                    return texture
+                else:
+                    return texture[pos+1:]
+            textures=[get_texture_name(path)
                 for path in bl.material.eachEnalbeTexturePath(m)]
+            print(textures)
             if len(textures)>0:
                 material.texture='*'.join(textures)
             else:
@@ -940,7 +996,9 @@ class PmdExporter(object):
 
             # english name
             bone_english_name=toCP932(b.name)
-            assert(len(bone_english_name)<20)
+            if len(bone_english_name)>=20:
+                print(bone_english_name)
+                #assert(len(bone_english_name)<20)
             bone.english_name=bone_english_name
 
             if len(v)>=3:
@@ -1047,12 +1105,12 @@ class PmdExporter(object):
             for i in range(10):
                 t=bl.material.getTexture(toonMaterial, i)
                 if t:
-                    io.toon_textures[i]=pmd.encode_string(t.name)
+                    io.toon_textures[i]="%s" % t.name
                 else:
-                    io.toon_textures[i]=pmd.encode_string("toon%02d.bmp\n" % i)
+                    io.toon_textures[i]="toon%02d.bmp" % (i+1)
         else:
             for i in range(10):
-                io.toon_textures[i]=pmd.encode_string("toon%02d.bmp\n" % i)
+                io.toon_textures[i]="toon%02d.bmp" % (i+1)
 
         # rigid body
         rigidNameMap={}