Now I've got friction working. here's the latest code for applyimpulse and prestep. Apart from logging the code, I'm setting up to visualize the vectors. Could pls pls look at my code and tell if there's an error? pls
void Arbiter::PreStep(float inv_dt)
{
char cStr[2048];
for (int i = 0; i < contacts.size(); ++i)
{
Contact& c = contacts[i];
{
sprintf_s(cStr, "[ARBITER] Restituition %.10f Friction %.10f", restituition, friction);
string str(cStr);
RELog::GetInstance()->WriteMessage(str);
}
XMVECTOR ContactPos = c.point;
{
sprintf_s(cStr, "[ARBITER] [PRESTEP] ContactPos %.10f %.10f %.10f", ContactPos.m128_f32[0], ContactPos.m128_f32[1], ContactPos.m128_f32[2]);
string str(cStr);
RELog::GetInstance()->WriteMessage(str);
}
XMVECTOR rA = XMVector3Transform((ContactPos - body1->GetPosition()), body1->GetOrientation());
XMVECTOR rB = XMVector3Transform((ContactPos - body2->GetPosition()), body2->GetOrientation());
{
sprintf_s(cStr, "[ARBITER] [PRESTEP] rA %.10f %.10f %.10f rB %.10f %.10f %.10f", rA.m128_f32[0], rA.m128_f32[1], rA.m128_f32[2], rB.m128_f32[0], rB.m128_f32[1], rB.m128_f32[2]);
string str(cStr);
RELog::GetInstance()->WriteMessage(str);
}
XMVECTOR VelocityA = body1->GetMass() > 0 ? (body1->GetVelocityAtCM() + XMVector3Cross(body1->GetAngularVelocity(), rA)) : XMVectorSet(0,0,0,1);
XMVECTOR VelocityB = body2->GetMass() > 0 ? (body2->GetVelocityAtCM() + XMVector3Cross(body2->GetAngularVelocity(), rB)) : XMVectorSet(0,0,0,1);
XMVECTOR dVel = VelocityB - VelocityA;
{
sprintf_s(cStr, "[ARBITER] [PRESTEP] VelocityA %.10f VelocityB %.10f dVel %.10f %.10f %.10f", XMVector3Length(VelocityA).m128_f32[0], XMVector3Length(VelocityB).m128_f32[0], dVel.m128_f32[0], dVel.m128_f32[1], dVel.m128_f32[2]);
string str(cStr);
RELog::GetInstance()->WriteMessage(str);
}
XMVECTOR ContactNormal = c.normal;
ContactNormal = XMVector3Transform(ContactNormal, body1->GetOrientation());
{
sprintf_s(cStr, "[ARBITER] [PRESTEP] ContactNormal %.10f %.10f %.10f", ContactNormal.m128_f32[0], ContactNormal.m128_f32[1], ContactNormal.m128_f32[2]);
string str(cStr);
RELog::GetInstance()->WriteMessage(str);
}
float Val = XMVector3Dot((body2->GetPosition() - body1->GetPosition()), ContactNormal).m128_f32[0];
if (Val < 0.0f)
ContactNormal *= -1;
{
sprintf_s(cStr, "[ARBITER] [PRESTEP] Val %.10f ContactNormal %.10f %.10f %.10f", Val, ContactNormal.m128_f32[0], ContactNormal.m128_f32[1], ContactNormal.m128_f32[2]);
string str(cStr);
RELog::GetInstance()->WriteMessage(str);
}
ContactNormal = XMVector3Normalize(ContactNormal);
c.bias += -BAUMGARTE * inv_dt * min(0.0f, c.separation + LINEAR_SLOP);
{
sprintf_s(cStr, "[ARBITER] [PRESTEP] BG Bias %.10f", c.bias);
string str(cStr);
RELog::GetInstance()->WriteMessage(str);
}
float Cdot = XMVector3Dot(dVel, ContactNormal).m128_f32[0];
if (Cdot < -VELOCITY_THRESHOLD)
c.bias += -restituition * Cdot;
{
sprintf_s(cStr, "[ARBITER] [PRESTEP] Cdot %.10f BG Bias after restituition %.10f", Cdot, c.bias);
string str(cStr);
RELog::GetInstance()->WriteMessage(str);
}
float term1 = body1->GetMass()>0.0f ? (1.0f / body1->GetMass()) : 0.0f;
float term2 = body2->GetMass()>0.0f ? (1.0f / body2->GetMass()) : 0.0f;
{
sprintf_s(cStr, "[ARBITER] [PRESTEP] Body1 inv mass %.10f Body2 inv mass %.10f", term1, term2);
string str(cStr);
RELog::GetInstance()->WriteMessage(str);
}
XMVECTOR rnA = XMVector3Cross(rA, ContactNormal);
XMVECTOR rnB = XMVector3Cross(rB, ContactNormal);
{
sprintf_s(cStr, "[ARBITER] [PRESTEP] rnA %.10f %.10f %.10f rnB %.10f %.10f %.10f", rnA.m128_f32[0], rnA.m128_f32[1], rnA.m128_f32[2], rnB.m128_f32[0], rnB.m128_f32[1], rnB.m128_f32[2]);
string str(cStr);
RELog::GetInstance()->WriteMessage(str);
}
float K = term1 + term2 + XMVector3Dot(rnA, XMVector4Transform(rnA, body1->GetIInverse())).m128_f32[0] + XMVector3Dot(rnB, XMVector4Transform(rnB, body2->GetIInverse())).m128_f32[0];
c.massNormal = K > 0.0f ? 1.0f / K : 0.0f;
{
sprintf_s(cStr, "[ARBITER] [PRESTEP] Mass Normal %.10f", c.massNormal);
string str(cStr);
RELog::GetInstance()->WriteMessage(str);
}
c.tangents[0] = XMVector3Orthogonal(ContactNormal);
c.tangents[1] = XMVector3Cross(c.tangents[0], ContactNormal);;
{
sprintf_s(cStr, "[ARBITER] [PRESTEP] ContactTangent 0 %.10f %.10f %.10f ContactTangent 1 %.10f %.10f %.10f", c.tangents[0].m128_f32[0], c.tangents[0].m128_f32[1], c.tangents[0].m128_f32[2], c.tangents[1].m128_f32[0], c.tangents[1].m128_f32[1], c.tangents[1].m128_f32[2]);
string str(cStr);
RELog::GetInstance()->WriteMessage(str);
}
XMVECTOR rt1A = XMVector3Cross(rA, c.tangents[0]);
XMVECTOR rt1B = XMVector3Cross(rB, c.tangents[0]);
XMVECTOR rt2A = XMVector3Cross(rA, c.tangents[1]);
XMVECTOR rt2B = XMVector3Cross(rB, c.tangents[1]);
float K1 = term1 + term2 + XMVector3Dot(rt1A, XMVector4Transform(rt1A, body1->GetIInverse())).m128_f32[0] + XMVector3Dot(rt1B, XMVector4Transform(rt1B, body2->GetIInverse())).m128_f32[0];
float K2 = term1 + term2 + XMVector3Dot(rt2A, XMVector4Transform(rt2A, body1->GetIInverse())).m128_f32[0] + XMVector3Dot(rt2B, XMVector4Transform(rt2B, body2->GetIInverse())).m128_f32[0];
c.massTangent[0] = K1 > 0.0f ? 1.0f / K1 : 0.0f;
c.massTangent[1] = K2 > 0.0f ? 1.0f / K2 : 0.0f;
{
sprintf_s(cStr, "[ARBITER] [PRESTEP] Mass Tangent 0 %.10f Mass Tangent 1 %.10f", c.massTangent[0], c.massTangent[1]);
string str(cStr);
RELog::GetInstance()->WriteMessage(str);
}
XMVECTOR P = c.Pn * ContactNormal + c.Pt[0] * c.tangents[0] + c.Pt[1] * c.tangents[1];
{
sprintf_s(cStr, "[ARBITER] [PRESTEP] P %.10f %.10f %.10f Pn %.10f Pt[0] %.10f Pt[1] %.10f", P.m128_f32[0], P.m128_f32[1], P.m128_f32[2], c.Pn, c.Pt[0], c.Pt[1]);
string str(cStr);
RELog::GetInstance()->WriteMessage(str);
}
body1->AddImpulse(-P);
body1->AddImpulsiveTorque(-XMVector3Cross(rA, P));
body2->AddImpulse(P);
body2->AddImpulsiveTorque(XMVector3Cross(rB, P));
}
}
float Clamp(float a, float low, float high)
{
return max(low, min(a, high));
}
void Arbiter::ApplyImpulse()
{
char cStr[2048];
for (int i = 0; i < contacts.size(); ++i)
{
Contact& c = contacts[i];
{
XMVECTOR ContactPos = c.point;
XMVECTOR rA = XMVector3Transform((ContactPos - body1->GetPosition()), body1->GetOrientation());
XMVECTOR rB = XMVector3Transform((ContactPos - body2->GetPosition()), body2->GetOrientation());
XMVECTOR VelocityA = body1->GetMass() > 0 ? (body1->GetVelocityAtCM() + XMVector3Cross(body1->GetAngularVelocity(), rA)) : XMVectorSet(0,0,0,1);
XMVECTOR VelocityB = body2->GetMass() > 0 ? (body2->GetVelocityAtCM() + XMVector3Cross(body2->GetAngularVelocity(), rB)) : XMVectorSet(0,0,0,1);
XMVECTOR dVel = VelocityB - VelocityA;
XMVECTOR ContactNormal = c.normal;
ContactNormal = XMVector3Transform(ContactNormal, body1->GetOrientation());
float Val = XMVector3Dot((body2->GetPosition() - body1->GetPosition()), ContactNormal).m128_f32[0];
if (Val < 0.0f)
ContactNormal *= -1;
ContactNormal = XMVector3Normalize(ContactNormal);
{
sprintf_s(cStr, "[ARBITER] [APPLYIMPULSE] Normal Impulse Start");
string str(cStr);
RELog::GetInstance()->WriteMessage(str);
}
float Cdot = XMVector3Dot(dVel, ContactNormal).m128_f32[0];
float dPn = c.massNormal * (-Cdot + c.bias);
{
sprintf_s(cStr, "[ARBITER] [APPLYIMPULSE] Cdot %.10f Before dPn %.10f", Cdot, dPn);
string str(cStr);
RELog::GetInstance()->WriteMessage(str);
}
float Pn0 = c.Pn;
c.Pn = max(Pn0 + dPn, 0.0f);
dPn = c.Pn - Pn0;
{
sprintf_s(cStr, "[ARBITER] [APPLYIMPULSE] After dPn %.10f c.Pn %.10f", dPn, c.Pn);
string str(cStr);
RELog::GetInstance()->WriteMessage(str);
}
XMVECTOR P = dPn * ContactNormal;
{
sprintf_s(cStr, "[ARBITER] [APPLYIMPULSE] P %.10f %.10f %.10f", P.m128_f32[0], P.m128_f32[1], P.m128_f32[2]);
string str(cStr);
RELog::GetInstance()->WriteMessage(str);
}
body1->AddImpulse(-P);
body1->AddImpulsiveTorque(-XMVector3Cross(rA, P));
body2->AddImpulse(P);
body2->AddImpulsiveTorque(XMVector3Cross(rB, P));
{
sprintf_s(cStr, "[ARBITER] [APPLYIMPULSE] Normal Impulse End");
string str(cStr);
RELog::GetInstance()->WriteMessage(str);
}
}
{
{
sprintf_s(cStr, "[ARBITER] [APPLYIMPULSE] Friction Impulse Start");
string str(cStr);
RELog::GetInstance()->WriteMessage(str);
}
for (int z=0;z<2;z++)
{
XMVECTOR ContactPos = c.point;
XMVECTOR rA = XMVector3Transform((ContactPos - body1->GetPosition()), body1->GetOrientation());
XMVECTOR rB = XMVector3Transform((ContactPos - body2->GetPosition()), body2->GetOrientation());
XMVECTOR VelocityA = body1->GetMass() > 0 ? (body1->GetVelocityAtCM() + XMVector3Cross(body1->GetAngularVelocity(), rA)) : XMVectorSet(0,0,0,1);
XMVECTOR VelocityB = body2->GetMass() > 0 ? (body2->GetVelocityAtCM() + XMVector3Cross(body2->GetAngularVelocity(), rB)) : XMVectorSet(0,0,0,1);
XMVECTOR dVel = VelocityB - VelocityA;
float vt = XMVector3Dot(dVel, c.tangents[z]).m128_f32[0];
float dPt = c.massTangent[z] * (-vt);
{
sprintf_s(cStr, "[ARBITER] [APPLYIMPULSE] vt %.10f Before dPt %.10f", vt, dPt);
string str(cStr);
RELog::GetInstance()->WriteMessage(str);
}
float maxPt = friction * c.Pn;
{
sprintf_s(cStr, "[ARBITER] [APPLYIMPULSE] maxPt %.10f c.Pn %.10f", maxPt, c.Pn);
string str(cStr);
RELog::GetInstance()->WriteMessage(str);
}
float oldTangentImpulse = c.Pt[z];
c.Pt[z] = Clamp(oldTangentImpulse + dPt, -maxPt, maxPt);
dPt = c.Pt[z] - oldTangentImpulse;
{
sprintf_s(cStr, "[ARBITER] [APPLYIMPULSE] After dPt %.10f", dPt);
string str(cStr);
RELog::GetInstance()->WriteMessage(str);
}
XMVECTOR Pt = dPt * c.tangents[z];
{
sprintf_s(cStr, "[ARBITER] [APPLYIMPULSE] Pt %.10f %.10f %.10f", Pt.m128_f32[0], Pt.m128_f32[1], Pt.m128_f32[2]);
string str(cStr);
RELog::GetInstance()->WriteMessage(str);
}
body1->AddImpulse(-Pt);
body1->AddImpulsiveTorque(-XMVector3Cross(rA, Pt));
body2->AddImpulse(Pt);
body2->AddImpulsiveTorque(XMVector3Cross(rB, Pt));
}
{
sprintf_s(cStr, "[ARBITER] [APPLYIMPULSE] Friction Impulse End");
string str(cStr);
RELog::GetInstance()->WriteMessage(str);
}
}
}
}