In our system we set up a height field for our dynamic ground, but we offset the height field so that the origin of the height field is at the centre.
We then use a "ghost object" to determine if something is in contact with the dynamic ground. In the ghost object I use the ContactSolver's CalculateContacts to determine if the ghost object shape is intersecting with the height field. But I noticed that it misses a lot of the "collisions".
I them noticed that if I changed
- Code: Select all
void ndContactSolver::CalculateContacts(
const ndShapeInstance* const instanceA, const ndMatrix& matrixA, const ndVector& velocA,
const ndShapeInstance* const instanceB, const ndMatrix& matrixB, const ndVector& velocB,
ndFixSizeArray<ndContactPoint, 16>& contactOut, ndContactNotify* const contactNotify)
{
ndContact contact;
ndBodyKinematic bodyA;
ndBodyKinematic bodyB;
ndContactPoint contactBuffer[D_MAX_CONTATCS];
ndShape* const shapeA = (ndShape*)(instanceA->GetShape());
ndShape* const shapeB = (ndShape*)(instanceB->GetShape());
m_instance0.SetShape(shapeA);
m_instance0.SetMaterial(instanceA->GetMaterial());
m_instance0.SetGlobalMatrix(matrixA);
m_instance1.SetShape(shapeB);
m_instance1.SetMaterial(instanceB->GetMaterial());
m_instance1.SetGlobalMatrix(matrixB);
bodyA.SetCollisionShape(m_instance0);
bodyB.SetCollisionShape(m_instance1);
bodyA.SetMatrix(matrixA);
bodyB.SetMatrix(matrixB);
bodyA.SetVelocity(velocA);
bodyB.SetVelocity(velocB);
if (!shapeA->GetAsShapeStaticMesh())
{
bodyA.SetMassMatrix(ndFloat32(1.0f), ndFloat32(1.0f), ndFloat32(1.0f), ndFloat32(1.0f));
}
if (!shapeB->GetAsShapeStaticMesh())
{
bodyB.SetMassMatrix(ndFloat32(1.0f), ndFloat32(1.0f), ndFloat32(1.0f), ndFloat32(1.0f));
}
contact.SetBodies(&bodyA, &bodyB);
m_closestPoint0 = ndVector::m_zero;
m_closestPoint1 = ndVector::m_zero;
m_separatingVector = ndVector(ndFloat32(0.0f), ndFloat32(1.0f), ndFloat32(0.0f), ndFloat32(0.0f));
m_contact = &contact;
m_freeFace = nullptr;
m_notification = contactNotify;
m_contactBuffer = contactBuffer;
m_timestep = ndFloat32 (1.0f);
m_skinMargin = ndFloat32(0.0f);
m_separationDistance = ndFloat32(1.0e10f);
m_maxCount = D_MAX_CONTATCS;
m_vertexIndex = 0;
m_pruneContacts = 1;
m_intersectionTestOnly = 0;
const ndInt32 count = dMin (CalculateContactsDiscrete(), contactOut.GetCapacity());
for (ndInt32 i = 0; i < count; ++i)
{
ndContactPoint& contactPoint = contactBuffer[i];
contactPoint.m_body0 = nullptr;
contactPoint.m_body1 = nullptr;
contactPoint.m_shapeInstance0 = instanceA;
contactPoint.m_shapeInstance1 = instanceB;
contactOut.PushBack(contactPoint);
}
}
to this
- Code: Select all
void ndContactSolver::CalculateContacts(
const ndShapeInstance* const instanceA, const ndMatrix& matrixA, const ndVector& velocA,
const ndShapeInstance* const instanceB, const ndMatrix& matrixB, const ndVector& velocB,
ndFixSizeArray<ndContactPoint, 16>& contactOut, ndContactNotify* const contactNotify)
{
ndContact contact;
ndBodyKinematic bodyA;
ndBodyKinematic bodyB;
ndContactPoint contactBuffer[D_MAX_CONTATCS];
ndShape* const shapeA = (ndShape*)(instanceA->GetShape());
ndShape* const shapeB = (ndShape*)(instanceB->GetShape());
m_instance0.SetShape(shapeA);
m_instance0.SetMaterial(instanceA->GetMaterial());
m_instance0.SetGlobalMatrix(instanceA->GetLocalMatrix() * matrixA);
m_instance1.SetShape(shapeB);
m_instance1.SetMaterial(instanceB->GetMaterial());
m_instance1.SetGlobalMatrix(instanceB->GetLocalMatrix() * matrixB);
bodyA.SetCollisionShape(m_instance0);
bodyB.SetCollisionShape(m_instance1);
bodyA.SetMatrix(matrixA);
bodyB.SetMatrix(matrixB);
bodyA.SetVelocity(velocA);
bodyB.SetVelocity(velocB);
if (!shapeA->GetAsShapeStaticMesh())
{
bodyA.SetMassMatrix(ndFloat32(1.0f), ndFloat32(1.0f), ndFloat32(1.0f), ndFloat32(1.0f));
}
if (!shapeB->GetAsShapeStaticMesh())
{
bodyB.SetMassMatrix(ndFloat32(1.0f), ndFloat32(1.0f), ndFloat32(1.0f), ndFloat32(1.0f));
}
contact.SetBodies(&bodyA, &bodyB);
m_closestPoint0 = ndVector::m_zero;
m_closestPoint1 = ndVector::m_zero;
m_separatingVector = ndVector(ndFloat32(0.0f), ndFloat32(1.0f), ndFloat32(0.0f), ndFloat32(0.0f));
m_contact = &contact;
m_freeFace = nullptr;
m_notification = contactNotify;
m_contactBuffer = contactBuffer;
m_timestep = ndFloat32 (1.0f);
m_skinMargin = ndFloat32(0.0f);
m_separationDistance = ndFloat32(1.0e10f);
m_maxCount = D_MAX_CONTATCS;
m_vertexIndex = 0;
m_pruneContacts = 1;
m_intersectionTestOnly = 0;
const ndInt32 count = dMin (CalculateContactsDiscrete(), contactOut.GetCapacity());
for (ndInt32 i = 0; i < count; ++i)
{
ndContactPoint& contactPoint = contactBuffer[i];
contactPoint.m_body0 = nullptr;
contactPoint.m_body1 = nullptr;
contactPoint.m_shapeInstance0 = instanceA;
contactPoint.m_shapeInstance1 = instanceB;
contactOut.PushBack(contactPoint);
}
}
the collisions are detected correctly.
Notice the
- Code: Select all
m_instance0.SetGlobalMatrix(instanceA->GetLocalMatrix() * matrixA);
and
- Code: Select all
m_instance1.SetGlobalMatrix(instanceB->GetLocalMatrix() * matrixB);
change.