OSDN Git Service

fix.
authorousttrue <ousttrue@gmail.com>
Fri, 9 Jul 2010 16:07:05 +0000 (01:07 +0900)
committerousttrue <ousttrue@gmail.com>
Fri, 9 Jul 2010 16:07:05 +0000 (01:07 +0900)
include/pmd.h
src/pmd.cpp
swig/blender/bl25.py
swig/blender/mqo_export.py
swig/blender/pmd_export.py
swig/blender/pmd_import.py

index 2f60e00..f251728 100644 (file)
@@ -176,6 +176,7 @@ struct Bone
                {}
        std::wstring getName()const;
        void setName(const char *src);
+       void setEnglishName(const char *src);
 };
 inline std::ostream &operator<<(std::ostream &os,
                const Bone &rhs)
index 6155e13..8367902 100755 (executable)
@@ -793,6 +793,11 @@ void Bone::setName(const char *src)
        strncpy(name, src, 20);
 }
 
+void Bone::setEnglishName(const char *src)
+{
+       strncpy(english_name, src, 20);
+}
+
 void BoneGroup::setName(const char *src)
 {
        strncpy(name, src, 20);
index 2389b80..dc66b7b 100755 (executable)
@@ -378,18 +378,21 @@ class mesh:
 
     @staticmethod
     def hasFaceUV(mesh, i, face):
-        return mesh.active_uv_texture.data[i]
+        return mesh.active_uv_texture and mesh.active_uv_texture.data[i]
 
     @staticmethod
     def getFaceUV(mesh, i, faces, count=3):
-        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)
+        if mesh.active_uv_texture and mesh.active_uv_texture.data[i]:
+            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)
         else:
-            print(count)
-            assert(False)
+            return ((0, 0), (0, 0), (0, 0), (0, 0))
 
     @staticmethod
     def setFaceUV(mesh, i, face, uv_array, image):
index 1c5b1f2..9b87a10 100644 (file)
@@ -183,58 +183,64 @@ class MqoExporter(object):
             print(obj.type)\r
             return\r
 \r
-        ############################################################\r
-        # write\r
-        ############################################################\r
         io.write("Object \""+obj.name+"\" {\r\n")\r
 \r
         # depth\r
         io.write("\tdepth %d\r\n" % info.depth)\r
 \r
+        # mirror\r
         if bl.modifier.hasType(obj, 'MIRROR'):\r
                 io.write("\tmirror 1\r\n")\r
                 io.write("\tmirror_axis 1\r\n")\r
 \r
         if obj.type.upper()=='MESH':\r
             # duplicate and applyMatrix\r
-            mesh, dumy=bl.object.duplicate(obj)\r
-\r
-            # vertices\r
-            io.write("\tvertex %d {\r\n" % len(mesh.verts))\r
-            for vert in mesh.verts:\r
-                x, y, z = convert_to_mqo(vert.co)\r
-                io.write("\t\t%f %f %f\r\n" % \r
-                        (x*self.scale, y*self.scale, z*self.scale)) # rotate to y-up\r
-            io.write("\t}\r\n")\r
-\r
-            # faces\r
-            io.write("\tface %d {\r\n" % len(mesh.faces))\r
-            for i, face in enumerate(mesh.faces):\r
-                count=bl.face.getVertexCount(face)\r
-                # V\r
-                io.write("\t\t%d V(" % count)\r
-                for j in reversed(bl.face.getVertices(face)):\r
-                    io.write("%d " % j)\r
-                io.write(")")\r
-                # mat\r
-                if len(mesh.materials):\r
-                    io.write(" M(%d)" % \r
-                            info.material_map[bl.face.getMaterialIndex(face)])\r
-                # UV\r
-                if bl.mesh.hasUV(mesh) and bl.mesh.hasFaceUV(mesh, i, face):\r
-                    io.write(" UV(")\r
-                    for uv in reversed(bl.mesh.getFaceUV(mesh, i, face, count)):\r
-                        # reverse vertical value\r
-                        io.write("%f %f " % (uv[0], 1.0-uv[1])) \r
-                    io.write(")")\r
-                io.write("\r\n")\r
-            io.write("\t}\r\n") # end of faces\r
-\r
-            # 削除する\r
-            bl.object.delete(dumy)\r
+            copyMesh, copyObj=bl.object.duplicate(obj)\r
+            # apply transform\r
+            copyObj.scale=obj.scale\r
+            bpy.ops.object.scale_apply()\r
+            copyObj.rotation_euler=obj.rotation_euler\r
+            bpy.ops.object.rotation_apply()\r
+            copyObj.location=obj.location\r
+            bpy.ops.object.location_apply()\r
+            # write mesh\r
+            self.__write_mesh(io, copyMesh, info.material_map)\r
+            bl.object.delete(copyObj)\r
 \r
         io.write("}\r\n") # end of object\r
 \r
+    def __write_mesh(self, io, mesh, material_map):\r
+        # vertices\r
+        io.write("\tvertex %d {\r\n" % len(mesh.verts))\r
+        for vert in mesh.verts:\r
+            x, y, z = convert_to_mqo(vert.co)\r
+            io.write("\t\t%f %f %f\r\n" % \r
+                    (x*self.scale, y*self.scale, z*self.scale)) # rotate to y-up\r
+        io.write("\t}\r\n")\r
+\r
+        # faces\r
+        io.write("\tface %d {\r\n" % len(mesh.faces))\r
+        for i, face in enumerate(mesh.faces):\r
+            count=bl.face.getVertexCount(face)\r
+            # V\r
+            io.write("\t\t%d V(" % count)\r
+            for j in reversed(bl.face.getVertices(face)):\r
+                io.write("%d " % j)\r
+            io.write(")")\r
+            # mat\r
+            if len(mesh.materials):\r
+                io.write(" M(%d)" % \r
+                        material_map[bl.face.getMaterialIndex(face)])\r
+            # UV\r
+            if bl.mesh.hasUV(mesh) and bl.mesh.hasFaceUV(mesh, i, face):\r
+                io.write(" UV(")\r
+                for uv in reversed(bl.mesh.getFaceUV(mesh, i, face, count)):\r
+                    # reverse vertical value\r
+                    io.write("%f %f " % (uv[0], 1.0-uv[1])) \r
+                io.write(")")\r
+            io.write("\r\n")\r
+        io.write("\t}\r\n") # end of faces\r
+\r
 \r
 def __execute(filename, scene, scale=10):\r
     if not scene.objects.active:\r
index 8e9b4bd..43fc7f9 100644 (file)
@@ -119,6 +119,8 @@ else:
         material.ambient.b=m.mirror_color[2]
         # flag
         material.flag=1 if m.subsurface_scattering.enabled else 0
+        # toon
+        material.toon_index=7
 
     def toCP932(s):
         return s.encode('cp932')
@@ -256,13 +258,12 @@ class VertexArray(object):
             b1_0, b1_1, b1_2,
             weight0, weight1, weight2
             ):
-        if not material in self.indexArrays:
-            self.indexArrays[material]=[]
-
         index0=self.__getIndex(obj, base_index0, pos0, n0, uv0, b0_0, b1_0, weight0)
         index1=self.__getIndex(obj, base_index1, pos1, n1, uv1, b0_1, b1_1, weight1)
         index2=self.__getIndex(obj, base_index2, pos2, n2, uv2, b0_2, b1_2, weight2)
 
+        if not material in self.indexArrays:
+            self.indexArrays[material]=[]
         self.indexArrays[material]+=[index0, index1, index2]
 
 
@@ -315,24 +316,16 @@ class OneSkinMesh(object):
 
     def addMesh(self, obj):
         if bl.object.isVisible(obj):
-            # 非表示
+            return
+        if not bl.modifier.hasType(obj, 'ARMATURE'):
             return
         self.__mesh(obj)
         self.__skin(obj)
         self.__rigidbody(obj)
         self.__constraint(obj)
 
-    def __mesh(self, obj):
-        if isBlender24():
-            pass
-        else:
-            if RIGID_SHAPE_TYPE in obj:
-                return
-            if CONSTRAINT_A in obj:
-                return
-
-        print("export", obj.name)
-        mesh=bl.object.getData(obj)
+    def __getWeightMap(self, obj, mesh):
+        # bone weight
         weightMap={}
         secondWeightMap={}
         def setWeight(i, name, w):
@@ -340,9 +333,9 @@ class OneSkinMesh(object):
                 if i in weightMap:
                     if i in secondWeightMap:
                         # 上位2つのweightを採用する
-                        if w<secondWeightMap[i]:
+                        if w<secondWeightMap[i][1]:
                             pass
-                        elif w<weightMap[i]:
+                        elif w<weightMap[i][1]:
                             # 2つ目を入れ替え
                             secondWeightMap[i]=(name, w)
                         else:
@@ -364,8 +357,11 @@ class OneSkinMesh(object):
                     setWeight(i, name, w)
         else:
             for i, v in enumerate(mesh.verts):
-                for g in v.groups:
-                    setWeight(i, obj.vertex_groups[g.group].name, g.weight)
+                if len(v.groups)>0:
+                    for g in v.groups:
+                        setWeight(i, obj.vertex_groups[g.group].name, g.weight)
+                else:
+                    setWeight(i, obj.vertex_groups[0].name, 1)
 
         # 合計値が1になるようにする
         for i in xrange(len(mesh.verts)):
@@ -380,16 +376,16 @@ class OneSkinMesh(object):
                 weightMap[i]=("", 0)
                 secondWeightMap[i]=("", 0)
 
-        # メッシュのコピーを生成してオブジェクトの行列を適用する
-        copyMesh, copyObj=bl.object.duplicate(obj)
-        if len(copyMesh.verts)==0:
-            return
+        return weightMap, secondWeightMap
 
-        for i, face in enumerate(copyMesh.faces):
+    def __processFaces(self, mesh, weightMap, secondWeightMap):
+        # 各面の処理
+        for i, face in enumerate(mesh.faces):
             faceVertexCount=bl.face.getVertexCount(face)
-            material=copyMesh.materials[bl.face.getMaterialIndex(face)]
-            v=[copyMesh.verts[index] for index in bl.face.getVertices(face)]
-            uv=bl.mesh.getFaceUV(copyMesh, i, face)
+            material=mesh.materials[bl.face.getMaterialIndex(face)]
+            v=[mesh.verts[index] for index in bl.face.getVertices(face)]
+            uv=bl.mesh.getFaceUV(
+                    mesh, i, face, bl.face.getVertexCount(face))
             # flip triangle
             if faceVertexCount==3:
                 # triangle
@@ -471,9 +467,44 @@ class OneSkinMesh(object):
                         weightMap[v[3].index][1],
                         weightMap[v[2].index][1]
                         )
+
+    def __mesh(self, obj):
+        if isBlender24():
+            pass
+        else:
+            if RIGID_SHAPE_TYPE in obj:
+                return
+            if CONSTRAINT_A in obj:
+                return
+
+        print("export", obj.name)
+
+        # メッシュのコピーを生成してオブジェクトの行列を適用する
+        copyMesh, copyObj=bl.object.duplicate(obj)
+        if len(copyMesh.verts)==0:
+            return
+        # apply transform
+        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()
+        # apply modifier
+        for m in [m for m in copyObj.modifiers]:
+            if m.type=='SOLIDFY':
+                continue
+            bpy.ops.object.modifier_apply(modifier=m.name)
+
+        weightMap, secondWeightMap=self.__getWeightMap(copyObj, copyMesh)
+        self.__processFaces(copyMesh, weightMap, secondWeightMap)
+
         bl.object.delete(copyObj)
         self.obj_index+=1
 
+    def createEmptyBasicSkin(self):
+        self.__getOrCreateMorph('base', 0)
+
     def __skin(self, obj):
         if not bl.object.hasShapeKey(obj):
             return
@@ -797,6 +828,10 @@ class PmdExporter(object):
         self.oneSkinMesh=OneSkinMesh(scene)
         self.__createOneSkinMesh(root)
         print(self.oneSkinMesh)
+        if len(self.oneSkinMesh.morphList)==0:
+            # create emtpy skin
+            self.oneSkinMesh.createEmptyBasicSkin()
+
         self.name=root.o.name
 
         # skeleton
@@ -839,7 +874,7 @@ class PmdExporter(object):
             v.normal.y=normal[2]
             v.normal.z=normal[1]
             v.uv.x=uv[0]
-            v.uv.y=uv[1]
+            v.uv.y=1.0-uv[1] # reverse vertical
             v.bone0=self.builder.indexByName(b0)
             v.bone1=self.builder.indexByName(b1)
             v.weight0=int(100*weight)
@@ -848,6 +883,7 @@ 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)
             # マテリアル
             material=io.addMaterial()
@@ -859,6 +895,8 @@ class PmdExporter(object):
                 for path in bl.material.eachTexturePath(m)]
             if len(textures)>0:
                 material.setTexture(toCP932('*'.join(textures)))
+            else:
+                material.setTexture(toCP932(""))
             # 面
             for i in indices:
                 assert(i<vertexCount)
@@ -884,9 +922,9 @@ class PmdExporter(object):
             bone.setName(cp932)
 
             # english name
-            bone_english_name=b.name
+            bone_english_name=toCP932(b.name)
             assert(len(bone_english_name)<20)
-            bone.english_name=bone_english_name
+            bone.setEnglishName(bone_english_name)
 
             if len(v)>=3:
                 # has type
@@ -954,14 +992,14 @@ class PmdExporter(object):
 
         # ボーン表示枠
         def createBoneDisplayName(name, english):
-            boneDisplayName=io.addBoneDisplayName()
+            boneDisplayName=io.addBoneGroup()
             if isBlender24():
                 boneDisplayName.name=name.decode('utf-8').encode('cp932')
                 boneDisplayName.english_name=english
             else:
                 boneDisplayName.setName(name.encode('cp932'))
                 boneDisplayName.setEnglishName(english.encode('cp932'))
-        boneDisplayName=createBoneDisplayName("IK\n", "IK\n")
+        boneDisplayName=createBoneDisplayName("IK\n", "IK\n")
         boneDisplayName=createBoneDisplayName("体(上)\n", "Body[u]\n")
         boneDisplayName=createBoneDisplayName("髪\n", "Hair\n")
         boneDisplayName=createBoneDisplayName("腕\n", "Arms\n")
index 074a898..fe03acd 100755 (executable)
@@ -339,7 +339,7 @@ def __build(armature, b, p, parent):
         __build(armature, c, b, bone)
 
 
-def __importArmature(scene, l):
+def __importArmature(l):
     armature, armature_object=bl.armature.create()
 
     # build bone
@@ -568,7 +568,7 @@ def __import16MaerialAndMesh(meshObject, l,
     return vertex_map
 
 
-def __importMesh(scene, io, tex_dir):
+def __importMaterialAndMesh(io, tex_dir):
     """
     @param l[in] mmd.PMDLoader
     @param filename[in]
@@ -650,7 +650,7 @@ def __importMesh(scene, io, tex_dir):
     return mesh_objects
 
 
-def __importConstraints(scene, io):
+def __importConstraints(io):
     if isBlender24():
         return
     print("create constraint")
@@ -672,7 +672,7 @@ def __importConstraints(scene, io):
                 location=(c.pos.x, c.pos.z, c.pos.y),
                 layer=layer
                 )
-        meshObject=scene.objects.active
+        meshObject=bl.object.getActive()
         constraintMeshes.append(meshObject)
         mesh=bl.object.getData(meshObject)
         bl.mesh.addMaterial(mesh, material)
@@ -699,7 +699,7 @@ def __importConstraints(scene, io):
     return container
 
 
-def __importRigidBodies(scene, io):
+def __importRigidBodies(io):
     if isBlender24():
         return
     print("create rigid bodies")
@@ -745,7 +745,7 @@ def __importRigidBodies(scene, io):
         else:
             assert(False)
 
-        meshObject=scene.objects.active
+        meshObject=bl.object.getActive()
         mesh=bl.object.getData(meshObject)
         rigidMeshes.append(meshObject)
         bl.mesh.addMaterial(mesh, material)
@@ -779,7 +779,7 @@ def __importRigidBodies(scene, io):
     return container
 
 
-def __execute(filename, scene):
+def _execute(filename):
     """
     load pmd file to context.
     """
@@ -799,13 +799,16 @@ def __execute(filename, scene):
         model_name=io.getName()
     root=bl.object.createEmpty(model_name)
 
+    # toon textures
+    #__importToonTextures(io)
+
     # import mesh
-    mesh_objects=__importMesh(scene, io, os.path.dirname(filename))
+    mesh_objects=__importMaterialAndMesh(io, os.path.dirname(filename))
     for o in mesh_objects:
         bl.object.makeParent(root, o)
 
     # import armature
-    armature_object=__importArmature(scene, io)
+    armature_object=__importArmature(io)
     if armature_object:
         bl.object.makeParent(root, armature_object)
         armature = bl.object.getData(armature_object) 
@@ -819,12 +822,12 @@ def __execute(filename, scene):
             poseBoneLimit(n, b)
 
     # import rigid bodies
-    rigidBodies=__importRigidBodies(scene, io)
+    rigidBodies=__importRigidBodies(io)
     if rigidBodies:
         bl.object.makeParent(root, rigidBodies)
 
     # import constraints
-    constraints=__importConstraints(scene, io)
+    constraints=__importConstraints(io)
     if constraints:
         bl.object.makeParent(root, constraints)
 
@@ -834,11 +837,8 @@ def __execute(filename, scene):
 if isBlender24():
     # for 2.4
     def execute_24(filename):
-        scene=bpy.data.scenes.active
-        bl.initialize('pmd_import', scene)
-        __execute(
-                filename.decode(bl.INTERNAL_ENCODING), 
-                scene)
+        bl.initialize('pmd_import', bpy.data.scenes.active)
+        _execute(filename.decode(bl.INTERNAL_ENCODING))
         bl.finalize()
 
     Blender.Window.FileSelector(
@@ -847,12 +847,6 @@ if isBlender24():
             Blender.sys.makename(ext='.pmd'))
 
 else:
-    # for 2.5
-    def execute_25(filename, scene):
-        bl.initialize('pmd_import', scene)
-        __execute(filename, scene)
-        bl.finalize()
-
     # import operator
     class IMPORT_OT_pmd(bpy.types.Operator):
         bl_idname = "import_scene.pmd"
@@ -873,7 +867,9 @@ else:
                 description="Directory of the file.")
 
         def execute(self, context):
-            execute_25(self.properties.path, context.scene)
+            bl.initialize('pmd_import', context.scene)
+            _execute(self.properties.path)
+            bl.finalize()
             return 'FINISHED'
 
         def invoke(self, context, event):