forked from bartvdbraak/blender
improved game soft bodies, works for objects that are using 'set smooth'
use shape matching by default for game soft bodies store soft body index for game vertices
This commit is contained in:
parent
38a80ff9a5
commit
718e2bf74f
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user