Advertisement
Guest User

Untitled

a guest
Feb 11th, 2015
281
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.51 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.  
  54.         static const CM_MANIFOLD_CONTACT* pcmContacts[MANIFOLD_CACHE_SIZE + 1] {
  55.             &m_cContacts[0],
  56.             &m_cContacts[1],
  57.             &m_cContacts[2],
  58.             &m_cContacts[3],
  59.             &_cNewContact,
  60.         };
  61.  
  62.         const CM_MANIFOLD_CONTACT* pmcDeepest = pcmContacts[0];
  63.         float fMaxPenetration = pmcDeepest->fDistance;
  64.         for ( unsigned int I = 1U; I < MANIFOLD_CACHE_SIZE + 1; ++I ) {
  65.             const CM_MANIFOLD_CONTACT& cContact = *pcmContacts[I];
  66.             if (cContact.fDistance > fMaxPenetration) {
  67.                 fMaxPenetration = cContact.fDistance;
  68.                 pmcDeepest = &cContact;
  69.             }
  70.         }
  71.  
  72.         //Second (furthest).
  73.         const CM_MANIFOLD_CONTACT* pmcFurthest1 = pcmContacts[0];
  74.         float fDistanceSq1 = pmcFurthest1->fDistance;
  75.         for (unsigned int I = 1U; I < MANIFOLD_CACHE_SIZE + 1; ++I) {
  76.             const CM_MANIFOLD_CONTACT& cContact = *pcmContacts[I];
  77.             float fDistance = (cContact.vWorldPointOnA - pmcDeepest->vWorldPointOnA).LenSq();
  78.             if (fDistance > fDistanceSq1) {
  79.                 fDistanceSq1 = fDistance;
  80.                 pmcFurthest1 = &cContact;
  81.             }
  82.         }
  83.  
  84.         //Third (furthest).
  85.         const CM_MANIFOLD_CONTACT* pmcFurthest2 = pcmContacts[0];
  86.         float fDistanceSq2 = pmcFurthest2->fDistance;
  87.         for (unsigned int I = 1U; I < MANIFOLD_CACHE_SIZE + 1; ++I) {
  88.             const CM_MANIFOLD_CONTACT& cContact = *pcmContacts[I];
  89.             float fDistanceToSegment = CDistance::SqDistPointSegment(cContact.vWorldPointOnA, pmcDeepest->vWorldPointOnA, pmcFurthest1->vWorldPointOnA);
  90.             if (fDistanceToSegment > fDistanceSq2) {
  91.                 fDistanceSq2 = fDistanceToSegment;
  92.                 pmcFurthest2 = &cContact;
  93.             }
  94.         }
  95.  
  96.         //Fourth
  97.         const CM_MANIFOLD_CONTACT* pmcFurthest3 = pcmContacts[0];
  98.         float fDistanceSq3 = pmcFurthest3->fDistance;
  99.         for (unsigned int I = 1U; I < MANIFOLD_CACHE_SIZE + 1; ++I) {
  100.             const CM_MANIFOLD_CONTACT& cContact = *pcmContacts[I];
  101.             float fDistanceFromTriangle = CDistance::SqDistPointTriangle(cContact.vWorldPointOnA, pmcDeepest->vWorldPointOnA, pmcFurthest1->vWorldPointOnA, pmcFurthest2->vWorldPointOnA);
  102.             if (fDistanceFromTriangle > fDistanceSq3) {
  103.                 fDistanceSq3 = fDistanceFromTriangle;
  104.                 pmcFurthest3 = &cContact;
  105.             }
  106.         }
  107.  
  108.         //Clear the manifold.
  109.         m_ui32TotalContacts = 0U;
  110.  
  111.         m_cContacts[m_ui32TotalContacts++] = *pmcDeepest;
  112.         m_cContacts[m_ui32TotalContacts++] = *pmcFurthest1;
  113.         m_cContacts[m_ui32TotalContacts++] = *pmcFurthest2;
  114.  
  115.         if (!CIntersect::PointInTriangle(pmcFurthest3->vWorldPointOnA, pmcDeepest->vWorldPointOnA, pmcFurthest1->vWorldPointOnA, pmcFurthest2->vWorldPointOnA)) {
  116.             m_cContacts[m_ui32TotalContacts++] = *pmcFurthest3;
  117.         }
  118.     }
  119.  
  120.     inline void AddContact(const CM_MANIFOLD_CONTACT& _cNewContact) {
  121.         if ( m_ui32TotalContacts == MANIFOLD_CACHE_SIZE ) {
  122.             ReplaceWhenFull( _cNewContact );
  123.         }
  124.         else {
  125.             m_cContacts[m_ui32TotalContacts++] = _cNewContact;
  126.         }
  127.     }
  128.  
  129.     inline void RemoveContact(unsigned int _ui32Index) {
  130.         unsigned int ui32LastIndex = --m_ui32TotalContacts;
  131.         if (ui32LastIndex != _ui32Index) {
  132.             m_cContacts[_ui32Index] = m_cContacts[ui32LastIndex];
  133.         }
  134.     }
  135.  
  136.     inline void ReplaceContact(const CM_MANIFOLD_CONTACT& _cNewContact, unsigned int _ui32Index) {
  137.         CM_MANIFOLD_CONTACT& cContact = m_cContacts[_ui32Index];
  138.  
  139.         unsigned long long ui64Time = cContact.ui64Time;
  140.         float fPN = cContact.fPN;
  141.         float fPNB = cContact.fPNB;
  142.         CVector3 vLambdaT = cContact.vWorldTangents[0] * cContact.fPT[0] + cContact.vWorldTangents[1] * cContact.fPT[1];
  143.  
  144.         cContact = _cNewContact;
  145.  
  146.         cContact.ui64Time = ui64Time;
  147.         cContact.fPN = fPN;
  148.         cContact.fPNB = fPNB;
  149.         cContact.fPT[0] = vLambdaT.Dot(_cNewContact.vWorldTangents[0]);
  150.         cContact.fPT[1] = vLambdaT.Dot(_cNewContact.vWorldTangents[1]);
  151.         //cContact.bWarmStart = true;
  152.     }
  153.  
  154.     inline void ReplaceAdd(const CM_MANIFOLD_CONTACT& _cNewContact) {
  155.         /*
  156.         * We start with the maximum threshold as initial value.
  157.         * If a less distance is found we know that it is
  158.         * less from the threshold and we have an index to replace.
  159.         */
  160.         float fMinDist = CONTACT_POINT_BREAKING_LENGTH_SQ;
  161.         int iReplaceIndex = -1;
  162.         for (unsigned int I = 0U; I < m_ui32TotalContacts; ++I) {
  163.             const CM_MANIFOLD_CONTACT& cContact = m_cContacts[I];
  164.             CVector3 vDiff = cContact.vLocalPointOnA - _cNewContact.vLocalPointOnA;
  165.             float fDist = vDiff.LenSq();
  166.             if (fDist < fMinDist) {
  167.                 fMinDist = fDist;
  168.                 iReplaceIndex = I;
  169.             }
  170.         }
  171.  
  172.         if (iReplaceIndex > -1) {
  173.             ReplaceContact(_cNewContact, iReplaceIndex);
  174.         }
  175.         else {
  176.             AddContact(_cNewContact);
  177.         }
  178.     }
  179.  
  180.     inline void Update(const CMatrix4x4& _mWorldA, const CMatrix4x4& _mWorldB) {
  181.         for ( unsigned int I = 0U; I < m_ui32TotalContacts; ++I ) {
  182.             CM_MANIFOLD_CONTACT& cContact = m_cContacts[I];
  183.  
  184.             CVector3 vWorldA = _mWorldA * cContact.vLocalPointOnA;
  185.             CVector3 vWorldB = _mWorldB * cContact.vLocalPointOnB;
  186.  
  187.             CVector3 vDiffA = vWorldA - cContact.vWorldPointOnA;
  188.             CVector3 vDiffB = vWorldB - cContact.vWorldPointOnB;
  189.             CVector3 vDiff = vWorldB - vWorldA;
  190.            
  191.             cContact.fDistance = vDiff.Dot(cContact.vWorldNormalOnA);
  192.  
  193.             if (cContact.fDistance <= ML_ZERO &&
  194.                 vDiffA.LenSq() < CONTACT_POINT_BREAKING_LENGTH_SQ &&
  195.                 vDiffB.LenSq() < CONTACT_POINT_BREAKING_LENGTH_SQ) {
  196.                 cContact.vWorldPointOnA = vWorldA;
  197.                 cContact.vWorldPointOnB = vWorldB;
  198.                 cContact.fPNB = ML_ZERO;
  199.             }
  200.             else {
  201.                 RemoveContact(I);
  202.             }
  203.         }
  204.     }
  205.  
  206.     //protected :
  207.     CM_MANIFOLD_CONTACT m_cContacts[MANIFOLD_CACHE_SIZE];
  208.     unsigned int m_ui32TotalContacts;
  209. };
  210.  
  211. #endif //#ifndef __CONTACT_MANIFOLD_H__
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement