Advertisement
Guest User

Untitled

a guest
Feb 10th, 2015
295
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.26 KB | None | 0 0
  1. #ifndef __CONTACT_MANIFOLD_H__
  2. #define __CONTACT_MANIFOLD_H__
  3.  
  4. #define MANIFOLD_CACHE_SIZE 4U
  5. #define CONTACT_POINT_BREAKING_LENGTH 0.08f
  6. #define CONTACT_POINT_BREAKING_LENGTH_SQ CONTACT_POINT_BREAKING_LENGTH * CONTACT_POINT_BREAKING_LENGTH
  7.  
  8. #include "CIntersect.h"
  9. #include "CDistance.h"
  10.  
  11. class CContactManifold {
  12.     friend class CContactConstraint;
  13. public:
  14.     struct CM_MANIFOLD_CONTACT {
  15.         unsigned long long ui64Time;
  16.         CVector3 vLocalPointOnA;
  17.         CVector3 vLocalPointOnB;
  18.  
  19.         CVector3 vWorldPointOnA;
  20.         CVector3 vWorldPointOnB;
  21.  
  22.         CVector3 vWorldNormalOnA;
  23.         CVector3 vWorldTangents[2];
  24.  
  25.         float fDistance;
  26.  
  27.         float fNormalMass;
  28.         float fTangentMasses[2];
  29.  
  30.         float fPN;
  31.         float fPT[2];
  32.  
  33.         float fPNB;
  34.         float fBias;
  35.         bool bWarmStart;
  36.  
  37.         inline CM_MANIFOLD_CONTACT() :
  38.             ui64Time(0ULL),
  39.             fPN(ML_ZERO),
  40.             fBias(ML_ZERO),
  41.             fPNB(ML_ZERO),
  42.             fDistance(ML_ZERO),
  43.             bWarmStart(false) {
  44.             fNormalMass = fTangentMasses[0] = fTangentMasses[1] = fPT[0] = fPT[1] = ML_ZERO;
  45.         }
  46.     };
  47.  
  48.     inline CContactManifold() : m_ui32TotalContacts(0U) {
  49.     }
  50.  
  51.     inline void ReplaceWhenFull(const CM_MANIFOLD_CONTACT& _cNewContact) {
  52.         //First (deepest).
  53.         const CM_MANIFOLD_CONTACT* pmcDeepest = &m_cContacts[0];
  54.         float fMaxPenetration = pmcDeepest->fDistance;
  55.         for (unsigned int I = 1U; I < MANIFOLD_CACHE_SIZE; ++I) {
  56.             const CM_MANIFOLD_CONTACT& cContact = m_cContacts[I];
  57.             if (cContact.fDistance > fMaxPenetration) {
  58.                 fMaxPenetration = cContact.fDistance;
  59.                 pmcDeepest = &cContact;
  60.             }
  61.         }
  62.  
  63.         //Second (furthest).
  64.         const CM_MANIFOLD_CONTACT* pmcFurthest1 = &m_cContacts[0];
  65.         float fDistanceSq1 = pmcFurthest1->fDistance;
  66.         for (unsigned int I = 1U; I < MANIFOLD_CACHE_SIZE; ++I) {
  67.             const CM_MANIFOLD_CONTACT& cContact = m_cContacts[I];
  68.             float fDistance = (cContact.vWorldPointOnA - pmcDeepest->vWorldPointOnA).LenSq();
  69.             if (fDistance > fDistanceSq1) {
  70.                 fDistanceSq1 = fDistance;
  71.                 pmcFurthest1 = &cContact;
  72.             }
  73.         }
  74.  
  75.         //Third (furthest).
  76.         const CM_MANIFOLD_CONTACT* pmcFurthest2 = &m_cContacts[0];
  77.         float fDistanceSq2 = pmcFurthest2->fDistance;
  78.         for (unsigned int I = 1U; I < MANIFOLD_CACHE_SIZE; ++I) {
  79.             const CM_MANIFOLD_CONTACT& cContact = m_cContacts[I];
  80.             float fDistanceToSegment = CDistance::SqDistPointSegment(cContact.vWorldPointOnA, pmcDeepest->vWorldPointOnA, pmcFurthest1->vWorldPointOnA);
  81.             if (fDistanceToSegment > fDistanceSq2) {
  82.                 fDistanceSq2 = fDistanceToSegment;
  83.                 pmcFurthest2 = &cContact;
  84.             }
  85.         }
  86.  
  87.         //Fourth
  88.         const CM_MANIFOLD_CONTACT* pmcFurthest3 = &m_cContacts[0];
  89.         float fDistanceSq3 = pmcFurthest3->fDistance;
  90.         for (unsigned int I = 1U; I < MANIFOLD_CACHE_SIZE; ++I) {
  91.             const CM_MANIFOLD_CONTACT& cContact = m_cContacts[I];
  92.             float fDistanceFromTriangle = CDistance::SqDistPointTriangle(cContact.vWorldPointOnA, pmcDeepest->vWorldPointOnA, pmcFurthest1->vWorldPointOnA, pmcFurthest2->vWorldPointOnA);
  93.             if (fDistanceFromTriangle > fDistanceSq3) {
  94.                 fDistanceSq3 = fDistanceFromTriangle;
  95.                 pmcFurthest3 = &cContact;
  96.             }
  97.         }
  98.  
  99.         //Clear the manifold.
  100.         m_ui32TotalContacts = 0U;
  101.  
  102.         m_cContacts[m_ui32TotalContacts++] = *pmcDeepest;
  103.         m_cContacts[m_ui32TotalContacts++] = *pmcFurthest1;
  104.         m_cContacts[m_ui32TotalContacts++] = *pmcFurthest2;
  105.  
  106.         if (!CIntersect::PointInTriangle(pmcFurthest3->vWorldPointOnA, pmcDeepest->vWorldPointOnA, pmcFurthest1->vWorldPointOnA, pmcFurthest2->vWorldPointOnA)) {
  107.             m_cContacts[m_ui32TotalContacts++] = *pmcFurthest3;
  108.         }
  109.     }
  110.  
  111.     inline void AddContact(const CM_MANIFOLD_CONTACT& _cNewContact) {
  112.         if (m_ui32TotalContacts == MANIFOLD_CACHE_SIZE) {
  113.             ReplaceWhenFull(_cNewContact);
  114.         }
  115.         else {
  116.             m_cContacts[m_ui32TotalContacts++] = _cNewContact;
  117.         }
  118.     }
  119.  
  120.     inline void RemoveContact(unsigned int _ui32Index) {
  121.         unsigned int ui32LastIndex = --m_ui32TotalContacts;
  122.         if (ui32LastIndex != _ui32Index) {
  123.             m_cContacts[_ui32Index] = m_cContacts[ui32LastIndex];
  124.         }
  125.     }
  126.  
  127.     inline void ReplaceContact(const CM_MANIFOLD_CONTACT& _cNewContact, unsigned int _ui32Index) {
  128.         CM_MANIFOLD_CONTACT& cContact = m_cContacts[_ui32Index];
  129.  
  130.         unsigned long long ui64Time = cContact.ui64Time;
  131.         float fPN = cContact.fPN;
  132.         float fPNB = cContact.fPNB;
  133.         CVector3 vLambdaT = cContact.vWorldTangents[0] * cContact.fPT[0] + cContact.vWorldTangents[1] * cContact.fPT[1];
  134.  
  135.         cContact = _cNewContact;
  136.  
  137.         cContact.ui64Time = ui64Time;
  138.         cContact.fPN = fPN;
  139.         cContact.fPNB = fPNB;
  140.         cContact.fPT[0] = vLambdaT.Dot(_cNewContact.vWorldTangents[0]);
  141.         cContact.fPT[1] = vLambdaT.Dot(_cNewContact.vWorldTangents[1]);
  142.     }
  143.  
  144.     inline void Update(const CMatrix4x4& _mWorldA, const CMatrix4x4& _mWorldB) {
  145.         for (unsigned int I = 0U; I < m_ui32TotalContacts; ++I) {
  146.             CM_MANIFOLD_CONTACT& cContact = m_cContacts[I];
  147.             ++cContact.ui64Time;
  148.  
  149.             CVector3 vWorldA = _mWorldA * cContact.vLocalPointOnA;
  150.             CVector3 vWorldB = _mWorldB * cContact.vLocalPointOnB;
  151.  
  152.             CVector3 vDiffA = vWorldA - cContact.vWorldPointOnA;
  153.             CVector3 vDiffB = vWorldB - cContact.vWorldPointOnB;
  154.             CVector3 vDiff = vWorldB - vWorldA;
  155.  
  156.             cContact.vWorldPointOnA = vWorldA;
  157.             cContact.vWorldPointOnB = vWorldB;
  158.             cContact.fDistance = vDiff.Dot(cContact.vWorldNormalOnA);
  159.             cContact.fPNB = ML_ZERO;
  160.  
  161.             bool bStillPenetrating = cContact.fDistance < ML_ZERO;
  162.             bool bRACloseEnough = vDiffA.LenSq() < CONTACT_POINT_BREAKING_LENGTH_SQ;
  163.             bool bRBCloseEnough = vDiffB.LenSq() < CONTACT_POINT_BREAKING_LENGTH_SQ;
  164.  
  165.             if (bRACloseEnough && bRBCloseEnough) {
  166.                 cContact.bWarmStart = true;
  167.             }
  168.             else {
  169.                 RemoveContact(I);
  170.             }
  171.         }
  172.     }
  173.  
  174.     inline bool LookUpAndReplace(const CM_MANIFOLD_CONTACT& _cNewContact) {
  175.         for (unsigned int I = 0U; I < m_ui32TotalContacts; ++I) {
  176.             CM_MANIFOLD_CONTACT& cContact = m_cContacts[I];
  177.  
  178.             CVector3 vDiffA = _cNewContact.vWorldPointOnA - cContact.vWorldPointOnA;
  179.             CVector3 vDiffB = _cNewContact.vWorldPointOnB - cContact.vWorldPointOnB;
  180.  
  181.             bool bRAFarEnough = vDiffA.LenSq() > CONTACT_POINT_BREAKING_LENGTH_SQ;
  182.             bool bRBFarEnough = vDiffB.LenSq() > CONTACT_POINT_BREAKING_LENGTH_SQ;
  183.  
  184.             if (bRAFarEnough && bRBFarEnough) {
  185.                 ReplaceContact(_cNewContact, I);
  186.                 return true;
  187.             }
  188.         }
  189.         return false;
  190.     }
  191.  
  192. //protected :
  193.     CM_MANIFOLD_CONTACT m_cContacts[MANIFOLD_CACHE_SIZE];
  194.     unsigned int m_ui32TotalContacts;
  195. };
  196.  
  197. #endif //#ifndef __CONTACT_MANIFOLD_H__
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement