OSDN Git Service

add constraint.
authorousttrue <ousttrue@gmail.com>
Wed, 16 Jun 2010 20:55:03 +0000 (05:55 +0900)
committerousttrue <ousttrue@gmail.com>
Wed, 16 Jun 2010 20:55:03 +0000 (05:55 +0900)
include/pmd.h
src/pmd.cpp [changed mode: 0644->0755]
swig/blender/bl24.py
swig/blender/bl25.py
swig/blender/pmd_export.py
swig/blender/pmd_import.py
swig/pmd.i

index ac706b3..75e4f47 100644 (file)
@@ -333,6 +333,9 @@ struct RigidBody
        float friction;
        //! \8d\84\91Ì\83^\83C\83v
        PROCESS_TYPE processType;
+
+       std::wstring getName()const;
+       void setName(const char *src);
 };
 
 //! Joint(\95¨\97\9d\89\89\8eZ\82Å\82ÌJoint\82ÆConstraint\82Í\93¯\82\88Ó\96¡)
@@ -357,6 +360,9 @@ struct Constraint
        //! \82Î\82Ë
        Vector3 springPos;
        Vector3 springRot;
+
+       std::wstring getName()const;
+       void setName(const char *src);
 };
 
 
old mode 100644 (file)
new mode 100755 (executable)
index 17397b6..23059ab
@@ -47,6 +47,20 @@ std::wstring
                                        std::string(english_name, english_name+20)));
        }
 
+std::wstring 
+       RigidBody::getName()const
+       {
+               return text::trim(text::to_WideChar(CP_OEMCP, 
+                                       std::string(name, name+20)));
+       }
+
+std::wstring 
+       Constraint::getName()const
+       {
+               return text::trim(text::to_WideChar(CP_OEMCP, 
+                                       std::string(name, name+20)));
+       }
+
 // 38bytes
 template<class READER>
        void
@@ -684,6 +698,69 @@ bool IO::write(binary::IWriter &w)
                w.writeArray<char>(toon_textures[i].name, 100);
        }
 
+       ////////////////////////////////////////////////////////////
+       // rigid bodies
+       ////////////////////////////////////////////////////////////
+       w.writeValue<DWORD>(rigidbodies.size());
+       for(size_t i=0; i<rigidbodies.size(); ++i){
+               RigidBody &rb=rigidbodies[i];
+               w.writeArray<char>(rb.name, 20);
+               w.writeValue<WORD>(rb.boneIndex);
+               w.writeValue<BYTE>(rb.group);
+               w.writeValue<WORD>(rb.target);
+               w.writeValue<BYTE>(rb.shapeType);
+               w.writeValue<float>(rb.w);
+               w.writeValue<float>(rb.h);
+               w.writeValue<float>(rb.d);
+               w.writeValue<float>(rb.position.x);
+               w.writeValue<float>(rb.position.y);
+               w.writeValue<float>(rb.position.z);
+               w.writeValue<float>(rb.rotation.x);
+               w.writeValue<float>(rb.rotation.y);
+               w.writeValue<float>(rb.rotation.z);
+               w.writeValue<float>(rb.weight);
+               w.writeValue<float>(rb.linearDamping);
+               w.writeValue<float>(rb.angularDamping);
+               w.writeValue<float>(rb.restitution);
+               w.writeValue<float>(rb.friction);
+               w.writeValue<BYTE>(rb.processType);
+       }
+
+       ////////////////////////////////////////////////////////////
+       // constraints
+       ////////////////////////////////////////////////////////////
+       w.writeValue<DWORD>(constraints.size());
+       for(size_t i=0; i<constraints.size(); ++i){
+               Constraint &c=constraints[i];
+               w.writeArray<char>(c.name, 20);
+               w.writeValue<DWORD>(c.rigidA);
+               w.writeValue<DWORD>(c.rigidB);
+               w.writeValue<float>(c.pos.x);
+               w.writeValue<float>(c.pos.y);
+               w.writeValue<float>(c.pos.z);
+               w.writeValue<float>(c.rot.x);
+               w.writeValue<float>(c.rot.y);
+               w.writeValue<float>(c.rot.z);
+               w.writeValue<float>(c.constraintPosMin.x);
+               w.writeValue<float>(c.constraintPosMin.y);
+               w.writeValue<float>(c.constraintPosMin.z);
+               w.writeValue<float>(c.constraintPosMax.x);
+               w.writeValue<float>(c.constraintPosMax.y);
+               w.writeValue<float>(c.constraintPosMax.z);
+               w.writeValue<float>(c.constraintRotMin.x);
+               w.writeValue<float>(c.constraintRotMin.y);
+               w.writeValue<float>(c.constraintRotMin.z);
+               w.writeValue<float>(c.constraintRotMax.x);
+               w.writeValue<float>(c.constraintRotMax.y);
+               w.writeValue<float>(c.constraintRotMax.z);
+               w.writeValue<float>(c.springPos.x);
+               w.writeValue<float>(c.springPos.y);
+               w.writeValue<float>(c.springPos.z);
+               w.writeValue<float>(c.springRot.x);
+               w.writeValue<float>(c.springRot.y);
+               w.writeValue<float>(c.springRot.z);
+       }
+
        return true;
 }
 
@@ -729,6 +806,17 @@ void Morph::setEnglishName(const char *src)
        strncpy(english_name, src, 20);
 }
 
+void RigidBody::setName(const char *src)
+{
+       strncpy(name, src, 20);
+}
+
+void Constraint::setName(const char *src)
+{
+       strncpy(name, src, 20);
+}
+
+
 } // namespace
 } // namespace
 
index a1a5133..f75052c 100644 (file)
@@ -455,6 +455,9 @@ def createEmptyObject(scene, name):
     empty.setName(name)
     return empty
 
+def createMaterial(name):
+    material = Blender.Material.New(name)
+    return material
 
 def createMqoMaterial(m):
     material = Blender.Material.New(m.getName().encode(INTERNAL_ENCODING))
index 85284f3..f842242 100644 (file)
@@ -66,6 +66,9 @@ def createEmptyObject(scene, name):
     scene.objects.link(empty)
     return empty
 
+def createMaterial(name):
+    material = bpy.data.materials.new(name)
+    return material
 
 def createMqoMaterial(m):
     material = bpy.data.materials.new(m.getName())
index 998e76c..f5a599b 100644 (file)
@@ -7,7 +7,7 @@
  Tooltip: 'Export PMD file for MikuMikuDance.'
 """
 __author__= ["ousttrue"]
-__version__= "1.0"
+__version__= "1.2"
 __url__=()
 __bpydoc__="""
 pmd Importer
@@ -16,13 +16,18 @@ This script exports a pmd model.
 
 0.1 20100318: first implementation.
 0.2 20100519: refactoring. use C extension.
-1.0 20100530: implement, basic features.
+1.0 20100530: implement basic features.
 1.1 20100612: integrate 2.4 and 2.5.
+1.2 20100616: implement rigid body.
 """
 
 MMD_SHAPE_GROUP_NAME='_MMD_SHAPE'
 BASE_SHAPE_NAME='Basis'
-
+RIGID_SHAPE_TYPE='rigid_shape_type'
+RIGID_PROCESS_TYPE='rigid_process_type'
+RIGID_BONE_NAME='rigid_bone_name'
+CONSTRAINT_A='constraint_a'
+CONSTRAINT_B='constraint_b'
 
 ###############################################################################
 # import
@@ -224,10 +229,15 @@ class IKSolver(object):
 
 
 class OneSkinMesh(object):
-    __slots__=['obj_index', 'scene', 'vertexArray', 'morphList']
+    __slots__=['obj_index', 'scene', 'vertexArray', 'morphList', 
+            'rigidbodies',
+            'constraints',
+            ]
     def __init__(self, scene):
         self.vertexArray=VertexArray()
         self.morphList=[]
+        self.rigidbodies=[]
+        self.constraints=[]
         self.scene=scene
         self.obj_index=0
 
@@ -240,16 +250,21 @@ class OneSkinMesh(object):
         if bl.objectIsVisible(obj):
             # 非表示
             return
-
-        print("export", obj.name)
-
-        # bone weight
-        weightMap=self.__mesh(obj)
-
-        # skin
+        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.objectGetData(obj)
         weightMap={}
         secondWeightMap={}
@@ -447,6 +462,20 @@ class OneSkinMesh(object):
         else:
             self.morphList.sort(key=getIndex)
 
+    def __rigidbody(self, obj):
+        if isBlender24():
+            return
+        if not RIGID_SHAPE_TYPE in obj:
+            return
+        self.rigidbodies.append(obj)
+
+    def __constraint(self, obj):
+        if isBlender24():
+            return
+        if not CONSTRAINT_A in obj:
+            return
+        self.constraints.append(obj)
+
     def __getOrCreateMorph(self, name, type):
         for m in self.morphList:
             if m.name==name:
@@ -629,7 +658,9 @@ class PmdExporter(object):
         object_node_map={}
         for o in scene.objects:
             object_node_map[o]=Node(o)
-        for node in object_node_map.values():
+        for o in scene.objects:
+        #for node in object_node_map.values():
+            node=object_node_map[o]
             if node.o.parent:
                 object_node_map[node.o.parent].children.append(node)
 
@@ -657,7 +688,6 @@ class PmdExporter(object):
             self.builder.ik_list.sort(key=getIndex)
 
     def __createOneSkinMesh(self, node):
-        print(node)
         ############################################################
         # search armature modifier
         ############################################################
@@ -667,7 +697,8 @@ class PmdExporter(object):
                 if not self.armatureObj:
                     self.armatureObj=armatureObj
                 elif self.armatureObj!=armatureObj:
-                    print("warning! found multiple armature. ignored.", armatureObj.name)
+                    print("warning! found multiple armature. ignored.", 
+                            armatureObj.name)
 
         if node.o.type.upper()=='MESH':
             self.oneSkinMesh.addMesh(node.o)
@@ -745,16 +776,12 @@ class PmdExporter(object):
                 io.indices.append(indices[i+2])
 
         # bones
-        for b in self.builder.bones:
-            if b.name.endswith("_t"):
-                if b.name.startswith("arm twist1_") or b.name.startswith("arm twist2_"):
-                    # skip
-                    print("skip %s" % b.name)
-                    continue
-
+        boneNameMap={}
+        for i, b in enumerate(self.builder.bones):
             bone=io.addBone()
 
             # name
+            boneNameMap[b.name]=i
             v=englishmap.getUnicodeBoneName(b.name)
             assert(v)
             cp932=v[1].encode('cp932')
@@ -865,10 +892,56 @@ class PmdExporter(object):
         io.english_name="blender export"
         io.english_coment="blender export"
 
+        # toon
         for i in range(10):
             io.getToonTexture(i).name="toon%02d.bmp\n" % i
 
+        # rigid body
+        rigidNameMap={}
+        for i, obj in enumerate(self.oneSkinMesh.rigidbodies):
+            rigidBody=io.addRigidBody()
+            rigidBody.setName(obj.name.encode('cp932'))
+            rigidNameMap[obj.name]=i
+            boneIndex=boneNameMap[obj[RIGID_BONE_NAME]]
+            if boneIndex==0:
+                boneIndex=0xFFFF
+            rigidBody.boneIndex=boneIndex
+            rigidBody.position.x=obj.location[0]
+            rigidBody.position.y=obj.location[2]
+            rigidBody.position.z=obj.location[1]
+            rigidBody.rotation.x=-obj.rotation_euler[0]
+            rigidBody.rotation.y=-obj.rotation_euler[2]
+            rigidBody.rotation.z=-obj.rotation_euler[1]
+            rigidBody.processType=obj[RIGID_PROCESS_TYPE]
+            rigidBody.group=0
+            rigidBody.target=0
+            rigidBody.weight=1
+            rigidBody.linearDamping=0
+            rigidBody.angularDamping=0
+            rigidBody.restitution=0
+            rigidBody.friction=0
+            if obj[RIGID_SHAPE_TYPE]==0:
+                rigidBody.shapeType=pmd.SHAPE_SPHERE
+                rigidBody.w=obj.scale[0]
+            elif obj[RIGID_SHAPE_TYPE]==1:
+                rigidBody.shapeType=pmd.SHAPE_CAPSULE
+                rigidBody.w=obj.scale[0]
+                rigidBody.h=obj.scale[2]
+            elif obj[RIGID_SHAPE_TYPE]==2:
+                rigidBody.shapeType=pmd.SHAPE_BOX
+                rigidBody.w=obj.scale[0]
+                rigidBody.d=obj.scale[1]
+                rigidBody.h=obj.scale[2]
+
+        # constraint
+        for obj in self.oneSkinMesh.constraints:
+            constraint=io.addConstraint()
+            constraint.setName(obj.name[1:].encode('cp932'))
+            constraint.rigidA=rigidNameMap[obj[CONSTRAINT_A]]
+            constraint.rigidB=rigidNameMap[obj[CONSTRAINT_B]]
+
         # 書き込み
+        print('write', path)
         return io.write(path)
 
 
index 8b0463f..3a7050e 100644 (file)
@@ -7,7 +7,7 @@
  Tooltip: 'Import PMD file for MikuMikuDance.'
 """
 __author__= ["ousttrue"]
-__version__= "1.1"
+__version__= "1.2"
 __url__=()
 __bpydoc__="""
 pmd Importer
@@ -24,11 +24,16 @@ This script imports a pmd into Blender for editing.
 0.8: 20100521: add shape_key group.
 1.0: 20100530: add invisilbe bone tail(armature layer 2).
 1.1: 20100608: integrate 2.4 and 2.5.
+1.2: 20100616: implement rigid body.
 """
 
 MMD_SHAPE_GROUP_NAME='_MMD_SHAPE'
 BASE_SHAPE_NAME='Basis'
-
+RIGID_SHAPE_TYPE='rigid_shape_type'
+RIGID_PROCESS_TYPE='rigid_process_type'
+RIGID_BONE_NAME='rigid_bone_name'
+CONSTRAINT_A='constraint_a'
+CONSTRAINT_B='constraint_b'
 
 ###############################################################################
 # import
@@ -560,6 +565,120 @@ def __importMesh(scene, io, tex_dir):
     return mesh_objects
 
 
+def __importConstraints(scene, io):
+    if isBlender24():
+        return
+    print("create constrains")
+    container=bl.createEmptyObject(scene, 'Constraints')
+    layer=[
+            True, False, False, False, False, False, False, False,
+            False, False, False, False, False, False, False, False,
+            False, False, False, False, False, False, False, False,
+            False, False, False, False, False, False, False, False,
+            ]
+    material=bl.createMaterial('constraint')
+    material.diffuse_color=(1, 0, 0)
+    constraintMeshes=[]
+    for c in io.constraints:
+        bpy.ops.mesh.primitive_uv_sphere_add(
+                segments=8,
+                rings=4,
+                size=0.1,
+                location=(c.pos.x, c.pos.z, c.pos.y),
+                layer=layer
+                )
+        meshObject=scene.objects.active
+        constraintMeshes.append(meshObject)
+        mesh=bl.objectGetData(meshObject)
+        bl.meshAddMaterial(mesh, material)
+        meshObject.name='c'+c.getName()
+        #meshObject.draw_transparent=True
+        #meshObject.draw_wire=True
+        meshObject.max_draw_type='SOLID'
+        rot=c.rot
+        meshObject.rotation_euler=(-rot.x, -rot.z, -rot.y)
+
+        meshObject[CONSTRAINT_A]=io.rigidbodies[c.rigidA].getName()
+        meshObject[CONSTRAINT_B]=io.rigidbodies[c.rigidB].getName()
+
+    for meshObject in reversed(constraintMeshes):
+        bl.objectMakeParent(container, meshObject)
+
+    return container
+
+
+def __importRigidBodies(scene, io):
+    if isBlender24():
+        return
+    print("create rigid bodies")
+
+    container=bl.createEmptyObject(scene, 'RigidBodies')
+    layer=[
+            True, False, False, False, False, False, False, False,
+            False, False, False, False, False, False, False, False,
+            False, False, False, False, False, False, False, False,
+            False, False, False, False, False, False, False, False,
+            ]
+    material=bl.createMaterial('rigidBody')
+    rigidMeshes=[]
+    for rigid in io.rigidbodies:
+        if rigid.boneIndex==0xFFFF:
+            # no reference bone
+            bone=io.bones[0]
+        else:
+            bone=io.bones[rigid.boneIndex]
+        pos=bone.pos+rigid.position
+
+        if rigid.shapeType==pmd.SHAPE_SPHERE:
+            bpy.ops.mesh.primitive_ico_sphere_add(
+                    location=(pos.x, pos.z, pos.y),
+                    layer=layer
+                    )
+            bpy.ops.transform.resize(
+                    value=(rigid.w, rigid.w, rigid.w))
+        elif rigid.shapeType==pmd.SHAPE_BOX:
+            bpy.ops.mesh.primitive_cube_add(
+                    location=(pos.x, pos.z, pos.y),
+                    layer=layer
+                    )
+            bpy.ops.transform.resize(
+                    value=(rigid.w, rigid.d, rigid.h))
+        elif rigid.shapeType==pmd.SHAPE_CAPSULE:
+            bpy.ops.mesh.primitive_tube_add(
+                    location=(pos.x, pos.z, pos.y),
+                    layer=layer
+                    )
+            bpy.ops.transform.resize(
+                    value=(rigid.w, rigid.w, rigid.h))
+        else:
+            assert(False)
+
+        meshObject=scene.objects.active
+        mesh=bl.objectGetData(meshObject)
+        rigidMeshes.append(meshObject)
+        bl.meshAddMaterial(mesh, material)
+        meshObject.name=rigid.getName()
+        #meshObject.draw_transparent=True
+        #meshObject.draw_wire=True
+        meshObject.max_draw_type='WIRE'
+        rot=rigid.rotation
+        meshObject.rotation_euler=(-rot.x, -rot.z, -rot.y)
+
+        # custom properties
+        meshObject[RIGID_SHAPE_TYPE]=rigid.shapeType
+        meshObject[RIGID_PROCESS_TYPE]=rigid.processType
+
+        bone_name = englishmap.getEnglishBoneName(bone.getName())
+        if not bone_name:
+            bone_name=bone.getName()
+        meshObject[RIGID_BONE_NAME]=bone_name
+
+    for meshObject in reversed(rigidMeshes):
+        bl.objectMakeParent(container, meshObject)
+
+    return container
+
+
 def __execute(filename, scene):
     """
     load pmd file to context.
@@ -598,6 +717,16 @@ def __execute(filename, scene):
         for n, b in bl.objectGetPose(armature_object).bones.items():
             bl.poseBoneLimit(n, b)
 
+    # import rigid bodies
+    rigidBodies=__importRigidBodies(scene, io)
+    if rigidBodies:
+        bl.objectMakeParent(root, rigidBodies)
+
+    # import constraints
+    constraints=__importConstraints(scene, io)
+    if constraints:
+        bl.objectMakeParent(root, constraints)
+
     # select objects
     bl.objectSelect(root)
     for o in mesh_objects:
index c07ce3a..d2325f8 100644 (file)
@@ -130,5 +130,17 @@ meshio::pmd::ToonTexture *getToonTexture(int index)
     return &($self->toon_textures[index]);
 }
 
+meshio::pmd::RigidBody *addRigidBody()
+{
+    $self->rigidbodies.push_back(meshio::pmd::RigidBody());
+    return &($self->rigidbodies.back());
+}
+
+meshio::pmd::Constraint *addConstraint()
+{
+    $self->constraints.push_back(meshio::pmd::Constraint());
+    return &($self->constraints.back());
+}
+
 }