Archived

This topic is now archived and is closed to further replies.

Endemoniada

Embedded Objects ?

Recommended Posts

Hi guys, Sometimes my objects become embedded and mess up my collision detection routines. I''m not sure how they get embedded without first registering a collision but it does happen occasionally. I guess it''s a good idea to first see if an object is embedded but what then ? Where should I replace it ? And then I have to check if the new position is embedded in another object, and so on. Any guidance is appreciated. Thanks.

Share this post


Link to post
Share on other sites
That''s called a relaxation step for contacts, if I''m not mistaken. If objects are embedded, the collision system should return a best approximation of the closest points on the surfaces of the two embedded objects. What you then need to do, is try to make those points ''meet''. Of course, if you have several embedded objects, pushing one will possibly increase the embeddedness on the other contact. You can push the objects slightly from each other, over a few iterations. You need to keep track of the contact planes for a better result.



struct cEmbeddedContact
{
Vector m_vNormal;
Vector m_vPoints[2];
cCollObject *m_pxCollObject[2];

cEmbeddedContact(const Vector& P0, const Vector& P1, cCollObject* pxObj0, cCollObject* pxObj1)
: m_vNormal((P0 - P1).UnitVector())
{
......
}
bool Update(float fRelaxation=0.5f)
{
// how embedded the objects are

float d = (m_vPoints[0] - m_vPoints[1]) * m_vNormal;

// objects no longer in contact

if (d < 0.0001f)
return false;

// Find which object to push the most (i.e. the lighter one)

float fRatio = (m_pxCollObject[1]->GetMass()) / (m_pxCollObject[0]->GetMass() + m_pxCollObject[1]->GetMass());

float d0 = d * fRelaxation * fRatio;
float d1 = d * fRelaxation * (1.0f - fRatio);

// push the objects apart

m_pxCollObject[0]->Push(-d0 * m_vNormal);
m_pxCollObject[1]->Push( d1 * m_vNormal);

return true;
}
};


int m_iNumContacts = 0;

cEmbeddedContact m_xEmbeddedContact[MAX_CONTACTS];

m_iNumContacts = FindEmbeddedContacts(m_xEmbeddedContact, MAX_CONTACTS);

for(int k = 0; k < 5; k ++) // run several times the relaxation loop

{
// process all contacts one by one

for(int i = 0; i < m_iNumContacts; i++)
{
// push the objects appart.

m_xEmbeddedContact[i].Update(0.5f);
}
}


this should push the embedded objects slightly apart. If the objects are deeply embedded, they will gently push apart over a few frames.

You can enforce a full resolution by stopping the relaxation loop only when all contacts are satisfied, but it might cause problems (like two opposite contacts, it would run indefinitely).

Share this post


Link to post
Share on other sites