improved game soft bodies, works for objects that are using 'set smooth'
authorErwin Coumans <blender@erwincoumans.com>
Thu, 25 Sep 2008 03:02:30 +0000 (03:02 +0000)
committerErwin Coumans <blender@erwincoumans.com>
Thu, 25 Sep 2008 03:02:30 +0000 (03:02 +0000)
use shape matching by default for game soft bodies
store soft body index for game vertices

source/blender/blenkernel/intern/object.c
source/blender/blenloader/intern/readfile.c
source/gameengine/Converter/BL_BlenderDataConversion.cpp
source/gameengine/Ketsji/KX_ConvertPhysicsObject.h
source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
source/gameengine/Physics/Bullet/CcdPhysicsController.h
source/gameengine/Rasterizer/RAS_TexVert.h

index 54908230d88adcc5e04906a2b69424ac37eb0f5a..9f6921fbade1e3ad5989dc7993fb0d5eb280aae6 100644 (file)
@@ -967,7 +967,7 @@ Object *add_only_object(int type, char *name)
        ob->linearStiffness = 1.0f;
        ob->angularStiffness = 1.0f;
        ob->volumePreservation = 1.0f;
-       ob->gamesoftFlag = 0;
+       ob->gamesoftFlag = OB_SOFT_SHAPE_MATCHING;
 
        /* NT fluid sim defaults */
        ob->fluidsimFlag = 0;
index d966d691fddf6c1de3e2b64428f82f75079f1861..f1823de954c209c2b25646c6472f1dfc36a282ff 100644 (file)
@@ -7853,6 +7853,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                        ob->linearStiffness = 1.0f;
                        ob->angularStiffness = 1.0f;
                        ob->volumePreservation = 1.0f;
+                       ob->softflag = OB_SOFT_SHAPE_MATCHING;
                }
        }
 
index 6a5048a9f15f73f047d96efdbc50ccb8d5674dcf..b3df2d7bc8580d8d54f1654e988b222ff32a3265 100644 (file)
@@ -1321,6 +1321,13 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj,
        objprop.m_dyna = (blenderobject->gameflag & OB_DYNAMIC) != 0;
        objprop.m_softbody = (blenderobject->gameflag & OB_SOFT_BODY) != 0;
        objprop.m_angular_rigidbody = (blenderobject->gameflag & OB_RIGID_BODY) != 0;
+       
+       ///for game soft bodies
+       objprop.m_linearStiffness = blenderobject->linearStiffness;
+       objprop.m_angularStiffness = blenderobject->angularStiffness;
+       objprop.m_volumePreservation = blenderobject->volumePreservation;
+       objprop.m_gamesoftFlag = blenderobject->gamesoftFlag;
+
        objprop.m_ghost = (blenderobject->gameflag & OB_GHOST) != 0;
        objprop.m_disableSleeping = (blenderobject->gameflag & OB_COLLISION_RESPONSE) != 0;//abuse the OB_COLLISION_RESPONSE flag
        //mmm, for now, taks this for the size of the dynamicobject
index 2b6c2535878f9004034bafdcc2f5bd24f22447a9..6325c9365fd0b9bc01ad8cc73fd2b78a98778f1d 100644 (file)
@@ -87,6 +87,12 @@ struct KX_ObjectProperties
        bool    m_disableSleeping;
        bool    m_hasCompoundChildren;
        bool    m_isCompoundChild;
+
+       float   m_linearStiffness;
+       float m_angularStiffness;
+       float   m_volumePreservation;
+       int             m_gamesoftFlag;
+       
        double  m_margin;
        KX_BoundBoxClass        m_boundclass;
        union {
index c4411a58856259b08e84f00f90710fec3553962b..5744a860e92707f2e3622d82a1bd860bc4b3cf3a 100644 (file)
@@ -667,6 +667,85 @@ void       KX_ConvertODEEngineObject(KX_GameObject* gameobj,
 #endif //WIN32
 
 
+                                                       
+       class KX_SoftBodyDeformer : public RAS_Deformer
+       {
+               btSoftBody*     m_softBody;
+               class RAS_MeshObject*   m_pMeshObject;
+               class BL_DeformableGameObject*  m_gameobj;
+
+
+       public:
+               KX_SoftBodyDeformer(btSoftBody* softBody,RAS_MeshObject*        pMeshObject,BL_DeformableGameObject*    gameobj)
+                       : m_softBody(softBody),
+                       m_pMeshObject(pMeshObject),
+                       m_gameobj(gameobj)
+               {
+                       //printf("KX_SoftBodyDeformer\n");
+               };
+
+               virtual ~KX_SoftBodyDeformer()
+               {
+                       //printf("~KX_SoftBodyDeformer\n");
+               };
+               virtual void Relink(GEN_Map<class GEN_HashedPtr, void*>*map)
+               {
+                       //printf("relink\n");
+               }
+               virtual bool Apply(class RAS_IPolyMaterial *polymat)
+               {
+                       //printf("apply\n");
+                       RAS_MeshSlot::iterator it;
+                       RAS_MeshMaterial *mmat;
+                       RAS_MeshSlot *slot;
+                       size_t i;
+
+                       // update the vertex in m_transverts
+                       Update();
+
+                       // The vertex cache can only be updated for this deformer:
+                       // Duplicated objects with more than one ploymaterial (=multiple mesh slot per object)
+                       // share the same mesh (=the same cache). As the rendering is done per polymaterial
+                       // cycling through the objects, the entire mesh cache cannot be updated in one shot.
+                       mmat = m_pMeshObject->GetMeshMaterial(polymat);
+                       if(!mmat->m_slots[(void*)m_gameobj])
+                               return true;
+
+                       slot = *mmat->m_slots[(void*)m_gameobj];
+
+                       // for each array
+                       for(slot->begin(it); !slot->end(it); slot->next(it)) 
+                       {
+                               btSoftBody::tNodeArray&   nodes(m_softBody->m_nodes);
+
+                               int index = 0;
+                               for(i=it.startvertex; i<it.endvertex; i++,index++) {
+                                       RAS_TexVert& v = it.vertex[i];
+
+                                       MT_Point3 pt (
+                                               nodes[v.getSoftBodyIndex()].m_x.getX(),
+                                               nodes[v.getSoftBodyIndex()].m_x.getY(),
+                                               nodes[v.getSoftBodyIndex()].m_x.getZ());
+                                       v.SetXYZ(pt);
+                               }
+                       }
+                       return true;
+               }
+               virtual bool Update(void)
+               {
+                       //printf("update\n");
+                       return true;//??
+               }
+               virtual RAS_Deformer *GetReplica()
+               {
+                       //printf("getReplica\n");
+                       return 0;
+               }
+       protected:
+               //class RAS_MeshObject  *m_pMesh;
+       };
+
+
 // forward declarations
 
 void   KX_ConvertBulletObject( class   KX_GameObject* gameobj,
@@ -916,6 +995,11 @@ void       KX_ConvertBulletObject( class   KX_GameObject* gameobj,
        ci.m_angularDamping = 1.f - shapeprops->m_ang_drag;
        //need a bit of damping, else system doesn't behave well
        ci.m_inertiaFactor = shapeprops->m_inertia/0.4f;//defaults to 0.4, don't want to change behaviour
+       ci.m_linearStiffness = objprop->m_linearStiffness;
+       ci.m_angularStiffness= objprop->m_angularStiffness;
+       ci.m_volumePreservation= objprop->m_volumePreservation;
+       ci.m_gamesoftFlag = objprop->m_gamesoftFlag;
+
        ci.m_collisionFilterGroup = (isbulletdyna) ? short(CcdConstructionInfo::DefaultFilter) : short(CcdConstructionInfo::StaticFilter);
        ci.m_collisionFilterMask = (isbulletdyna) ? short(CcdConstructionInfo::AllFilter) : short(CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::StaticFilter);
        ci.m_bRigid = objprop->m_dyna && objprop->m_angular_rigidbody;
@@ -990,107 +1074,15 @@ void    KX_ConvertBulletObject( class   KX_GameObject* gameobj,
 
        physicscontroller->SetObject(gameobj->GetSGNode());
 
-       class KX_SoftBodyDeformer : public RAS_Deformer
-       {
-               btSoftBody*     m_softBody;
-               class BL_SkinMeshObject*        m_pMeshObject;
-               class BL_DeformableGameObject*  m_gameobj;
-
-
-       public:
-               KX_SoftBodyDeformer(btSoftBody* softBody,BL_SkinMeshObject*     pMeshObject,BL_DeformableGameObject*    gameobj)
-                       : m_softBody(softBody),
-                       m_pMeshObject(pMeshObject),
-                       m_gameobj(gameobj)
-               {
-                       //printf("KX_SoftBodyDeformer\n");
-               };
-
-               virtual ~KX_SoftBodyDeformer()
-               {
-                       //printf("~KX_SoftBodyDeformer\n");
-               };
-               virtual void Relink(GEN_Map<class GEN_HashedPtr, void*>*map)
-               {
-                       //printf("relink\n");
-               }
-               virtual bool Apply(class RAS_IPolyMaterial *polymat)
-               {
-                       //printf("apply\n");
-                       RAS_MeshSlot::iterator it;
-                       RAS_MeshMaterial *mmat;
-                       RAS_MeshSlot *slot;
-                       size_t i;
-
-                       // update the vertex in m_transverts
-                       Update();
-
-                       // The vertex cache can only be updated for this deformer:
-                       // Duplicated objects with more than one ploymaterial (=multiple mesh slot per object)
-                       // share the same mesh (=the same cache). As the rendering is done per polymaterial
-                       // cycling through the objects, the entire mesh cache cannot be updated in one shot.
-                       mmat = m_pMeshObject->GetMeshMaterial(polymat);
-                       if(!mmat->m_slots[(void*)m_gameobj])
-                               return true;
-
-                       slot = *mmat->m_slots[(void*)m_gameobj];
-
-                       // for each array
-                       for(slot->begin(it); !slot->end(it); slot->next(it)) 
-                       {
-                               // for each vertex
-                               // copy the untransformed data from the original mvert
-                               int count = 0;
-                               {
-
-                                       for(i=it.startvertex; i<it.endvertex; i++,count++)
-                                       {
-                                       }
-                               }
-                               btSoftBody::tNodeArray&   nodes(m_softBody->m_nodes);
-
-                               if (count == m_softBody->m_userIndexMapping.size())
-                               {
-                                       int index = 0;
-                                       for(i=it.startvertex; i<it.endvertex; i++,index++) {
-                                               RAS_TexVert& v = it.vertex[i];
-
-                                               MT_Point3 pt (
-                                                       nodes[m_softBody->m_userIndexMapping[index]].m_x.getX(),
-                                                       nodes[m_softBody->m_userIndexMapping[index]].m_x.getY(),
-                                                       nodes[m_softBody->m_userIndexMapping[index]].m_x.getZ());
-                                               v.SetXYZ(pt);
-
-                                               //(m_transverts[v.getOrigIndex()]);
-                                       }
-                               }
-
-                       }
-
-                       return true;
-               }
-               virtual bool Update(void)
-               {
-                       //printf("update\n");
-                       return true;//??
-               }
-               virtual RAS_Deformer *GetReplica()
-               {
-                       //printf("getReplica\n");
-                       return 0;
-               }
-       protected:
-               //class RAS_MeshObject  *m_pMesh;
-       };
 
        ///test for soft bodies
        if (objprop->m_softbody && physicscontroller)
        {
                btSoftBody* softBody = physicscontroller->GetSoftBody();
-               if (softBody && gameobj->GetMesh(0))
+               if (softBody && gameobj->GetMesh(0))//only the first mesh, if any
                {
                        //should be a mesh then, so add a soft body deformer
-                       KX_SoftBodyDeformer* softbodyDeformer = new KX_SoftBodyDeformer(softBody, (BL_SkinMeshObject*)gameobj->GetMesh(0),(BL_DeformableGameObject*)gameobj);
+                       KX_SoftBodyDeformer* softbodyDeformer = new KX_SoftBodyDeformer(softBody, gameobj->GetMesh(0),(BL_DeformableGameObject*)gameobj);
                        gameobj->SetDeformer(softbodyDeformer);
                        
                }
index ad79db16dc4509518a2d7cb46083fb78eeef2783..333ecd6ea11faa8be85f56c1c496c82479f6ee30 100644 (file)
@@ -222,14 +222,57 @@ void CcdPhysicsController::CreateRigidbody()
                                        psb->appendFace(idx[0],idx[1],idx[2]);
                                }
                                
+                               ///create a mapping between graphics mesh vertices and soft body vertices
                                {
-                                       for (int i=0;i<hlib.m_vertexIndexMapping.size();i++)
-                                               psb->m_userIndexMapping.push_back(hlib.m_vertexIndexMapping[i]);
-                                               //psb->m_userIndexMapping.push_back(hres.m_Indices[i]);
+                                       RAS_MeshObject* rasMesh= GetShapeInfo()->GetMesh();
+
+                                       if (rasMesh)
+                                       {
+                                               
+                                               //printf("apply\n");
+                                               RAS_MeshSlot::iterator it;
+                                               RAS_MeshMaterial *mmat;
+                                               RAS_MeshSlot *slot;
+                                               size_t i;
+
+                                               //for each material
+                                               for (int m=0;m<rasMesh->NumMaterials();m++)
+                                               {
+                                                       // The vertex cache can only be updated for this deformer:
+                                                       // Duplicated objects with more than one ploymaterial (=multiple mesh slot per object)
+                                                       // share the same mesh (=the same cache). As the rendering is done per polymaterial
+                                                       // cycling through the objects, the entire mesh cache cannot be updated in one shot.
+                                                       mmat = rasMesh->GetMeshMaterial(m);
+
+                                                       slot = mmat->m_baseslot;
+                                                       for(slot->begin(it); !slot->end(it); slot->next(it))
+                                                       {
+                                                               int index = 0;
+                                                               for(i=it.startvertex; i<it.endvertex; i++,index++) 
+                                                               {
+                                                                       RAS_TexVert* vertex = &it.vertex[i];
+                                                                       //search closest index, and store it in vertex
+                                                                       vertex->setSoftBodyIndex(0);
+                                                                       btScalar maxDistSqr = 1e30;
+                                                                       btSoftBody::tNodeArray&   nodes(psb->m_nodes);
+                                                                       btVector3 xyz = trans(btVector3(vertex->getXYZ()[0],vertex->getXYZ()[1],vertex->getXYZ()[2]));
+                                                                       for (int n=0;n<nodes.size();n++)
+                                                                       {
+                                                                               btScalar distSqr = (nodes[n].m_x - xyz).length2();
+                                                                               if (distSqr<maxDistSqr)
+                                                                               {
+                                                                                       maxDistSqr = distSqr;
+                                                                                       vertex->setSoftBodyIndex(n);
+                                                                               }
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
                                }
 
                                hlib.ReleaseResult(hres);
-                               psb->randomizeConstraints();
+
                                
                        }
 
@@ -292,13 +335,42 @@ void CcdPhysicsController::CreateRigidbody()
 
                //psb->m_cfg.collisions =       btSoftBody::fCollision::SDF_RS;//btSoftBody::fCollision::CL_SS+ btSoftBody::fCollision::CL_RS;
                psb->m_cfg.collisions   =       btSoftBody::fCollision::SDF_RS + btSoftBody::fCollision::CL_SS;
+               //psb->m_cfg.collisions =       btSoftBody::fCollision::CL_SS + btSoftBody::fCollision::CL_RS;
                
                //btSoftBody::Material* pm=psb->appendMaterial();
                btSoftBody::Material*   pm=psb->m_materials[0];
-               pm->m_kLST                              =       0.1f;
+               
+               pm->m_kLST                              =       m_cci.m_linearStiffness;
+               pm->m_kAST                              =       m_cci.m_angularStiffness;
+               pm->m_kVST                              =       m_cci.m_volumePreservation;
+               
+
+               
+
                //pm->m_kAST = 0.01f;
                //pm->m_kVST = 0.001f;
                psb->generateBendingConstraints(2,pm);
+               //psb->m_cfg.piterations                =       4;
+               //psb->m_cfg.viterations                =       4;
+               //psb->m_cfg.diterations = 4;
+               //psb->m_cfg.citerations = 4;
+               if (m_cci.m_gamesoftFlag & 1)///OB_SOFT_SHAPE_MATCHING)
+               {
+                       psb->setPose(false,true);//
+               } else
+               {
+                       psb->setPose(true,false);
+               }
+
+               psb->m_cfg.kDF                          =       0.5;
+               psb->m_cfg.kMT                          =       0.05;
+               psb->m_cfg.piterations          =       5;
+               
+               psb->m_cfg.piterations          =       5;
+               //psb->m_cfg.kVC                                =       20;
+
+               psb->randomizeConstraints();
+
 /*
                psb->m_cfg.kDF = 0.1f;//1.f;
                psb->m_cfg.kDP          =       0.0001;
@@ -315,10 +387,10 @@ void CcdPhysicsController::CreateRigidbody()
 //             psb->activate();
 //             psb->setActivationState(1);
 //             psb->setDeactivationTime(1.f);
-               //psb->m_cfg.piterations                =       4;
+               
                //psb->m_materials[0]->m_kLST   =       0.1+(i/(btScalar)(n-1))*0.9;
                psb->setTotalMass(m_cci.m_mass);
-               psb->generateClusters(64);              
+               //psb->generateClusters(8);//(64);              
                psb->setCollisionFlags(0);
 //             m_object->setCollisionShape(rbci.m_collisionShape);
                btTransform startTrans;
@@ -1147,7 +1219,19 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope)
                                {
                                        const float* vtx = poly->GetVertex(i)->getXYZ();
                                        btPoint3 point(vtx[0],vtx[1],vtx[2]);
-                                       m_vertexArray.push_back(point);
+                                       //avoid duplicates (could better directly use vertex offsets, rather than a vertex compare)
+                                       bool found = false;
+                                       for (int j=0;j<m_vertexArray.size();j++)
+                                       {
+                                               if (m_vertexArray[j]==point)
+                                               {
+                                                       found = true;
+                                                       break;
+                                               }
+                                       }
+                                       if (!found)
+                                               m_vertexArray.push_back(point);
+
                                        numvalidpolys++;
                                }
                        } else
index c45f459074946aa90f88533dab52048b52c99223..65c23eb2543f0d976fb1eb84953d65a054901047 100644 (file)
@@ -147,6 +147,10 @@ struct CcdConstructionInfo
                m_linearDamping(0.1f),
                m_angularDamping(0.1f),
                m_margin(0.06f),
+               m_linearStiffness(1.f),
+               m_angularStiffness(1.f),
+               m_volumePreservation(1.f),
+               m_gamesoftFlag(0),
                m_collisionFlags(0),
                m_bRigid(false),
                m_bSoft(false),
@@ -169,6 +173,12 @@ struct CcdConstructionInfo
        btScalar        m_linearDamping;
        btScalar        m_angularDamping;
        btScalar        m_margin;
+
+       btScalar        m_linearStiffness;
+       btScalar        m_angularStiffness;
+       btScalar        m_volumePreservation;
+       int                     m_gamesoftFlag;
+
        int                     m_collisionFlags;
        bool            m_bRigid;
        bool            m_bSoft;
index 4ec4db19e532ad18474706001d1e6f3299210b5b..54da109cbf194b1cd6791c49ae664890a36a0fa2 100644 (file)
@@ -44,15 +44,16 @@ class RAS_TexVert
        float                   m_uv1[2];               // 2*4 =  8
        float                   m_uv2[2];               // 2*4 =  8
        unsigned int    m_rgba;                 //        4
-       float                   m_tangent[4];   // 4*2 =  8
-       float                   m_normal[3];    // 3*2 =  6 
+       float                   m_tangent[4];   // 4*4 =  16
+       float                   m_normal[3];    // 3*4 =  12
        short                   m_flag;                 //        2
+       short                   m_softBodyIndex;                //2
        unsigned int    m_unit;                 //                4
-       unsigned int    m_origindex;            //        4
+       unsigned int    m_origindex;            //    4
                                                                        //---------
-                                                                       //       56
+                                                                       //       56+6+8+2=72
        // 32 bytes total size, fits nice = 56 = not fit nice.
-       // We'll go for 64 bytes total size - 24 bytes left.
+
 public:
        enum {
                FLAT = 1,
@@ -91,6 +92,16 @@ public:
                return m_normal;
        }
        
+       short int getSoftBodyIndex() const
+       {
+               return m_softBodyIndex;
+       }
+       
+       void    setSoftBodyIndex(short int sbIndex)
+       {
+               m_softBodyIndex = sbIndex;
+       }
+
        const float* getTangent() const {
                return m_tangent;
        }