Would it be enough? Well maybe. You won't have any nice stacking behavior, and you can have some jitter problems. But it is possible to hack around these problems.
3D Manifold Collision Response
I will give it a try, the collision response is an entire subject on it's own, it would take me months of work to get up to speed on it,
cheers
It might not take you months. If you look carefully in the first link, here is the collision response code. It looks nearly identical in 3D.
void Arbiter::PreStep(float inv_dt)
{
const float k_allowedPenetration = 0.01f;
float k_biasFactor = World::positionCorrection ? 0.2f : 0.0f;
for (int i = 0; i < numContacts; ++i)
{
Contact* c = contacts + i;
Vec2 r1 = c->position - body1->position;
Vec2 r2 = c->position - body2->position;
// Precompute normal mass, tangent mass, and bias.
float rn1 = Dot(r1, c->normal);
float rn2 = Dot(r2, c->normal);
float kNormal = body1->invMass + body2->invMass;
kNormal += body1->invI * (Dot(r1, r1) - rn1 * rn1) + body2->invI * (Dot(r2, r2) - rn2 * rn2);
c->massNormal = 1.0f / kNormal;
Vec2 tangent = Cross(c->normal, 1.0f);
float rt1 = Dot(r1, tangent);
float rt2 = Dot(r2, tangent);
float kTangent = body1->invMass + body2->invMass;
kTangent += body1->invI * (Dot(r1, r1) - rt1 * rt1) + body2->invI * (Dot(r2, r2) - rt2 * rt2);
c->massTangent = 1.0f / kTangent;
c->bias = -k_biasFactor * inv_dt * Min(0.0f, c->separation + k_allowedPenetration);
if (World::accumulateImpulses)
{
// Apply normal + friction impulse
Vec2 P = c->Pn * c->normal + c->Pt * tangent;
body1->velocity -= body1->invMass * P;
body1->angularVelocity -= body1->invI * Cross(r1, P);
body2->velocity += body2->invMass * P;
body2->angularVelocity += body2->invI * Cross(r2, P);
}
}
}
void Arbiter::ApplyImpulse()
{
Body* b1 = body1;
Body* b2 = body2;
for (int i = 0; i < numContacts; ++i)
{
Contact* c = contacts + i;
c->r1 = c->position - b1->position;
c->r2 = c->position - b2->position;
// Relative velocity at contact
Vec2 dv = b2->velocity + Cross(b2->angularVelocity, c->r2) - b1->velocity - Cross(b1->angularVelocity, c->r1);
// Compute normal impulse
float vn = Dot(dv, c->normal);
float dPn = c->massNormal * (-vn + c->bias);
if (World::accumulateImpulses)
{
// Clamp the accumulated impulse
float Pn0 = c->Pn;
c->Pn = Max(Pn0 + dPn, 0.0f);
dPn = c->Pn - Pn0;
}
else
{
dPn = Max(dPn, 0.0f);
}
// Apply contact impulse
Vec2 Pn = dPn * c->normal;
b1->velocity -= b1->invMass * Pn;
b1->angularVelocity -= b1->invI * Cross(c->r1, Pn);
b2->velocity += b2->invMass * Pn;
b2->angularVelocity += b2->invI * Cross(c->r2, Pn);
// Relative velocity at contact
dv = b2->velocity + Cross(b2->angularVelocity, c->r2) - b1->velocity - Cross(b1->angularVelocity, c->r1);
Vec2 tangent = Cross(c->normal, 1.0f);
float vt = Dot(dv, tangent);
float dPt = c->massTangent * (-vt);
if (World::accumulateImpulses)
{
// Compute friction impulse
float maxPt = friction * c->Pn;
// Clamp friction
float oldTangentImpulse = c->Pt;
c->Pt = Clamp(oldTangentImpulse + dPt, -maxPt, maxPt);
dPt = c->Pt - oldTangentImpulse;
}
else
{
float maxPt = friction * dPn;
dPt = Clamp(dPt, -maxPt, maxPt);
}
// Apply contact impulse
Vec2 Pt = dPt * tangent;
b1->velocity -= b1->invMass * Pt;
b1->angularVelocity -= b1->invI * Cross(c->r1, Pt);
b2->velocity += b2->invMass * Pt;
b2->angularVelocity += b2->invI * Cross(c->r2, Pt);
}
}
Thanks @Randy Gaul,
I will study this algorithm. What is the purpose of the PreStep function?
Also, my collision detection algorithm does broad phase then narrow phase using sweeps followed by multi-sample SAT, it produces manifolds + collision times
For each collision during a tick should I move the collided objects to first point of collision then perform response or should I not move the collided objects & perform response straight away?
PreStep calculates the "inverse mass" term - basically by how much the relative velocity at contact changes if you apply a unit impulse there. \((JWJ^T)^{-1}\) term (huh, what happened to tex math?). It is done there so you don't have to calculate it in the ApplyImpulse step, which allows you to call it multiple times at less cost.
It also applies accumulated impulses from the previous step, which makes the system more stable. Without those, you won't be able to make things like a stack of boxes without it falling apart.
if I apply impulses to each manifold point, would that not apply the same Linear Impulse several times incorrectly?
You don't apply the same impulse every time. For each iteration at every manifold point you apply equal and opposite impulses such that the relative post velocity at the manifold point will be zero. Here relative post velocity means the relative velocity at the manifold point in the direction of the manifold normal *after* you applied the impulse.