Zgragselus

ResolveContact

Apr 21st, 2026
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.98 KB | None | 0 0
  1. /// <summary>
  2. /// Resolve single contact
  3. ///
  4. /// Performs contact resolution by applying forces to bodies and nudging them back a bit (in case they penetrate)
  5. /// </summary>
  6. /// <param name="contact">Contact (collision) to resolve</param>
  7. void Scene::ResolveContact(Contact& contact)
  8. {
  9.     Body* bodyA = contact.mBodyA;
  10.     Body* bodyB = contact.mBodyB;
  11.  
  12.     const float3 pointOnA = bodyA->ModelToWorldSpace(contact.mPointOnA_ModelSpace);
  13.     const float3 pointOnB = bodyB->ModelToWorldSpace(contact.mPointOnB_ModelSpace);
  14.  
  15.     const float elasticity = bodyA->mResitution * bodyB->mResitution;
  16.  
  17.     const float invMassA = bodyA->mInvMass;
  18.     const float invMassB = bodyB->mInvMass;
  19.  
  20.     const mat3 invWorldInertiaA = bodyA->GetInverseInertiaTensorWorldSpace();
  21.     const mat3 invWorldInertiaB = bodyB->GetInverseInertiaTensorWorldSpace();
  22.  
  23.     const float3 normal = contact.mNormal;
  24.  
  25.     const float3 radiusA = pointOnA - bodyA->GetCenterOfMassWorldSpace();
  26.     const float3 radiusB = pointOnB - bodyB->GetCenterOfMassWorldSpace();
  27.  
  28.     const float3 angularImpulseA = cross(invWorldInertiaA * cross(radiusA, normal), radiusA);
  29.     const float3 angularImpulseB = cross(invWorldInertiaB * cross(radiusB, normal), radiusB);
  30.     const float angularFactor = dot(angularImpulseA + angularImpulseB, normal);
  31.  
  32.     // Obtain world space velocity of the motion and rotation
  33.     const float3 velocityA = bodyA->mLinearVelocity + cross(bodyA->mAngularVelocity, radiusA);
  34.     const float3 velocityB = bodyB->mLinearVelocity + cross(bodyB->mAngularVelocity, radiusB);
  35.  
  36.     // Calculate collision impulse
  37.     const float3 velocityAB = velocityA - velocityB;
  38.     const float impulse = (1.0f + elasticity) * dot(velocityAB, normal) / (bodyA->mInvMass + bodyB->mInvMass + angularFactor);
  39.     const float3 impulseVec = normal * impulse;
  40.  
  41.     bodyA->ApplyImpulse(pointOnA, impulseVec * -1.0f);
  42.     bodyB->ApplyImpulse(pointOnB, impulseVec * 1.0f);
  43.  
  44.     // Calculate the impulse caused by friction
  45.     const float friction = bodyA->mFriction * bodyB->mFriction;
  46.  
  47.     // Find normal direction of the velocity (respecting normal of the collision)
  48.     const float3 velocityNormal = normal * dot(normal, velocityAB);
  49.     // Find tangent direction of the velocity (respecting normal of the collision)
  50.     const float3 velocityTangent = velocityAB - velocityNormal;
  51.    
  52.     // Get tangential velocities direction to the other body
  53.     float velocityTangentMagnitude = length(velocityTangent);
  54.     // Static friction under certain threshold???
  55.     if (velocityTangentMagnitude < 0.01f)
  56.     {
  57.         /*bodyA->mAngularVelocity *= 0.9f;
  58.         bodyB->mAngularVelocity *= 0.9f;
  59.  
  60.         bodyA->mLinearVelocity *= 0.9f;
  61.         bodyB->mLinearVelocity *= 0.9f;*/
  62.     }
  63.     else
  64.     {
  65.         float3 tangentVec = velocityTangent / velocityTangentMagnitude;
  66.  
  67.         const float3 inertiaA = cross(invWorldInertiaA * cross(radiusA, tangentVec), radiusA);
  68.         const float3 inertiaB = cross(invWorldInertiaB * cross(radiusB, tangentVec), radiusB);
  69.         const float inverseInertia = dot(inertiaA + inertiaB, tangentVec);
  70.  
  71.         // Calculate tangential impulse for friction
  72.         const float reducedMass = 1.0f / (bodyA->mInvMass + bodyB->mInvMass + inverseInertia);
  73.         const float3 impulseFriction = velocityTangent * reducedMass * friction;
  74.  
  75.         // Apply friction
  76.         bodyA->ApplyImpulse(pointOnA, impulseFriction * -1.0f);
  77.         bodyB->ApplyImpulse(pointOnB, impulseFriction * 1.0f);
  78.     }
  79.  
  80.     // Move colliding objects to just outside of each otehr
  81. #ifdef CCD
  82.     if (contact.mTimeOfImpact == 0.0f)
  83.     {
  84.         // Resolve by moving collision objects to just outside of each other
  85.         const float tA = bodyA->mInvMass / (bodyA->mInvMass + bodyB->mInvMass);
  86.         const float tB = bodyB->mInvMass / (bodyA->mInvMass + bodyB->mInvMass);
  87.  
  88.         const float3 ds = pointOnB - pointOnA;
  89.  
  90.         bodyA->mPosition += ds * tA;
  91.         bodyB->mPosition -= ds * tB;
  92.     }
  93. #else
  94.     const float tA = bodyA->mInvMass / (bodyA->mInvMass + bodyB->mInvMass);
  95.     const float tB = bodyB->mInvMass / (bodyA->mInvMass + bodyB->mInvMass);
  96.  
  97.     const float3 ds = pointOnB - pointOnA;
  98.  
  99.     bodyA->mPosition += ds * tA;
  100.     bodyB->mPosition -= ds * tB;
  101. #endif
  102. }
Advertisement
Add Comment
Please, Sign In to add comment