Advertisement
Guest User

Untitled

a guest
Feb 9th, 2015
38
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.86 KB | None | 0 0
  1. //Contact Manager:
  2.  
  3. #ifndef __CONTACT_MANAGER_H__
  4. #define __CONTACT_MANAGER_H__
  5.  
  6. #define SEQUENTIAL_ITERATIONS 10U
  7.  
  8. #include <vector>
  9. #include "CContactConstraint.h"
  10.  
  11. class CContactManager {
  12. public :
  13.         inline void AddContact(CRigidBody* _prbBody0, CRigidBody* _prbBody1, const CContactManifold::CM_MANIFOLD_CONTACT& _cContact) {
  14.                 for ( unsigned int I = 0U; I < m_vContactConstraints.size(); ++I ) {
  15.                         CContactConstraint& ccContactConstraint = m_vContactConstraints[I];
  16.  
  17.                         CContactManifold& cmContactManifold = ccContactConstraint.m_cmContactManifold;
  18.                         if (_prbBody0 == ccContactConstraint.m_prbRigidBody0 &&
  19.                                 _prbBody1 == ccContactConstraint.m_prbRigidBody1) {
  20.                                
  21.                                 if ( cmContactManifold.LookUpAndReplace(_cContact) ) {
  22.                                         return;
  23.                                 }
  24.                                 else {
  25.                                         cmContactManifold.AddContact(_cContact);
  26.                                         return;
  27.                                 }
  28.                         }
  29.                 }
  30.  
  31.                 m_vContactConstraints.push_back( CContactConstraint() );
  32.  
  33.                 CContactConstraint& ccContactConstraint = m_vContactConstraints.back();
  34.                 CContactManifold& cmContactManifold = ccContactConstraint.m_cmContactManifold;
  35.                 ccContactConstraint.m_prbRigidBody0 = _prbBody0;
  36.                 ccContactConstraint.m_prbRigidBody1 = _prbBody1;
  37.                 cmContactManifold.AddContact(_cContact);
  38.         }
  39.        
  40.         inline void PreStep(float _fInvDt) {
  41.                 for (unsigned int I = 0U; I < m_vContactConstraints.size(); ++I) {
  42.                         m_vContactConstraints[I].PreStep(_fInvDt);
  43.                 }
  44.         }
  45.  
  46.         inline void WarmStart() {
  47.                 for (unsigned int I = 0U; I < m_vContactConstraints.size(); ++I) {
  48.                         m_vContactConstraints[I].WarmStart();
  49.                 }
  50.         }
  51.  
  52.         inline void ApplyImpulses() {
  53.                 for (unsigned int I = 0UL; I < SEQUENTIAL_ITERATIONS; ++I) {
  54.                         for (unsigned int J = 0UL; J < m_vContactConstraints.size(); ++J) {
  55.                                 m_vContactConstraints[J].ApplyImpulse();
  56.                         }
  57.                 }
  58.         }
  59.  
  60.         inline void UpdateContacts() {
  61.                 for ( unsigned int I = 0U; I < m_vContactConstraints.size(); ++I ) {
  62.                         CContactConstraint& ccContactConstraint = m_vContactConstraints[I];
  63.                         ccContactConstraint.m_cmContactManifold.Update(ccContactConstraint.m_prbRigidBody0->GetTransform(), ccContactConstraint.m_prbRigidBody1->GetTransform());
  64.                 }
  65.         }
  66. //protected :
  67.         std::vector<CContactConstraint> m_vContactConstraints;
  68. };
  69.  
  70.  
  71. #endif //#ifndef __CONTACT_MANAGER_H__
  72.  
  73. //Contact Manifold (each constraint has one):
  74.  
  75. #ifndef __CONTACT_MANIFOLD_H__
  76. #define __CONTACT_MANIFOLD_H__
  77.  
  78. #define MANIFOLD_CACHE_SIZE 4U
  79. #define CONTACT_POINT_BREAKING_LENGTH 0.2f
  80. #define CONTACT_POINT_BREAKING_LENGTH_SQ CONTACT_POINT_BREAKING_LENGTH * CONTACT_POINT_BREAKING_LENGTH
  81.  
  82. #include "CIntersect.h"
  83. #include "CDistance.h"
  84.  
  85. class CContactManifold {
  86.         friend class CContactConstraint;
  87. public:
  88.         struct CM_MANIFOLD_CONTACT {
  89.                 unsigned long long ui64Time;
  90.                 CVector3 vLocalPointOnA;
  91.                 CVector3 vLocalPointOnB;
  92.  
  93.                 CVector3 vWorldPointOnA;
  94.                 CVector3 vWorldPointOnB;
  95.  
  96.                 CVector3 vWorldNormalOnB;
  97.                 CVector3 vWorldTangents[2];
  98.                
  99.                 float fDistance;
  100.  
  101.                 float fNormalMass;
  102.                 float fTangentMasses[2];
  103.  
  104.                 float fPN;
  105.                 float fPT[2];
  106.                
  107.                 float fPNB;
  108.                 float fBias;
  109.                 bool bWarmStart;
  110.  
  111.                 inline CM_MANIFOLD_CONTACT() :
  112.                         ui64Time(0ULL),
  113.                         fPN(ML_ZERO),
  114.                         fBias(ML_ZERO),
  115.                         fPNB(ML_ZERO),
  116.                         fDistance(ML_ZERO),
  117.                         bWarmStart(false) {
  118.                         fNormalMass = fTangentMasses[0] = fTangentMasses[1] = fPT[0] = fPT[1] = ML_ZERO;
  119.                 }
  120.         };
  121.  
  122.         inline CContactManifold() :     m_ui32TotalContacts(0U) {
  123.         }
  124.  
  125.         inline void ReplaceWhenFull(const CM_MANIFOLD_CONTACT& _cNewContact) {
  126.                 //First (deepest).
  127.                 const CM_MANIFOLD_CONTACT* pmcDeepest = &m_cContacts[0];
  128.                 float fMaxPenetration = pmcDeepest->fDistance;
  129.                 for ( unsigned int I = 1U; I < MANIFOLD_CACHE_SIZE; ++I ) {
  130.                         const CM_MANIFOLD_CONTACT& cContact = m_cContacts[I];
  131.                         if (cContact.fDistance > fMaxPenetration) {
  132.                                 fMaxPenetration = cContact.fDistance;
  133.                                 pmcDeepest = &cContact;
  134.                         }
  135.                 }
  136.                
  137.                 //Second (furthest).
  138.                 const CM_MANIFOLD_CONTACT* pmcFurthest1 = &m_cContacts[0];
  139.                 float fDistanceSq1 = pmcFurthest1->fDistance;
  140.                 for ( unsigned int I = 1U; I < MANIFOLD_CACHE_SIZE; ++I ) {
  141.                         const CM_MANIFOLD_CONTACT& cContact = m_cContacts[I];
  142.                         float fDistance = (cContact.vWorldPointOnA - pmcDeepest->vWorldPointOnA).LenSq();
  143.                         if (fDistance > fDistanceSq1) {
  144.                                 fDistanceSq1 = fDistance;
  145.                                 pmcFurthest1 = &cContact;
  146.                         }
  147.                 }
  148.                
  149.                 //Third (furthest).
  150.                 const CM_MANIFOLD_CONTACT* pmcFurthest2 = &m_cContacts[0];
  151.                 float fDistanceSq2 = pmcFurthest2->fDistance;
  152.                 for (unsigned int I = 1U; I < MANIFOLD_CACHE_SIZE; ++I) {
  153.                         const CM_MANIFOLD_CONTACT& cContact = m_cContacts[I];
  154.                         float fDistanceToSegment = CDistance::SqDistPointSegment(cContact.vWorldPointOnA, pmcDeepest->vWorldPointOnA, pmcFurthest1->vWorldPointOnA);
  155.                         if (fDistanceToSegment > fDistanceSq2) {
  156.                                 fDistanceSq2 = fDistanceToSegment;
  157.                                 pmcFurthest2 = &cContact;
  158.                         }
  159.                 }
  160.  
  161.                 //Fourth
  162.                 const CM_MANIFOLD_CONTACT* pmcFurthest3 = &m_cContacts[0];
  163.                 float fDistanceSq3 = pmcFurthest3->fDistance;
  164.                 for (unsigned int I = 1U; I < MANIFOLD_CACHE_SIZE; ++I) {
  165.                         const CM_MANIFOLD_CONTACT& cContact = m_cContacts[I];
  166.                         float fDistanceFromTriangle = CDistance::SqDistPointTriangle(cContact.vWorldPointOnA, pmcDeepest->vWorldPointOnA, pmcFurthest1->vWorldPointOnA, pmcFurthest2->vWorldPointOnA);
  167.                         if (fDistanceFromTriangle > fDistanceSq3) {
  168.                                 fDistanceSq3 = fDistanceFromTriangle;
  169.                                 pmcFurthest3 = &cContact;
  170.                         }
  171.                 }
  172.  
  173.                 //Clear the manifold.
  174.                 m_ui32TotalContacts = 0U;
  175.  
  176.                 m_cContacts[m_ui32TotalContacts++] = *pmcDeepest;
  177.                 m_cContacts[m_ui32TotalContacts++] = *pmcFurthest1;
  178.                 m_cContacts[m_ui32TotalContacts++] = *pmcFurthest2;
  179.  
  180.                 if ( !CIntersect::PointInTriangle(pmcFurthest3->vWorldPointOnA, pmcDeepest->vWorldPointOnA, pmcFurthest1->vWorldPointOnA, pmcFurthest2->vWorldPointOnA) ) {
  181.                         m_cContacts[m_ui32TotalContacts++] = *pmcFurthest3;
  182.                 }
  183.         }
  184.  
  185.         inline void AddContact(const CM_MANIFOLD_CONTACT& _cNewContact) {
  186.                 if (m_ui32TotalContacts == MANIFOLD_CACHE_SIZE) {
  187.                         ReplaceWhenFull( _cNewContact );
  188.                 }
  189.                 else {
  190.                         m_cContacts[m_ui32TotalContacts++] = _cNewContact;
  191.                 }
  192.         }
  193.  
  194.         inline void RemoveContact(unsigned int _ui32Index) {
  195.                 unsigned int ui32LastIndex = --m_ui32TotalContacts;
  196.                 if (ui32LastIndex != _ui32Index) {
  197.                         m_cContacts[_ui32Index] = m_cContacts[ui32LastIndex];
  198.                         EmptyContact(ui32LastIndex);
  199.                 }
  200.         }
  201.  
  202.         inline void ReplaceContact(const CM_MANIFOLD_CONTACT& _cNewContact, unsigned int _ui32Index) {
  203.                 CM_MANIFOLD_CONTACT& cContact = m_cContacts[_ui32Index];
  204.  
  205.                 unsigned long long ui64Time = cContact.ui64Time;
  206.                 float fPN = cContact.fPN;
  207.                 CVector3 vLambdaT = cContact.vWorldTangents[0] * cContact.fPT[0] + cContact.vWorldTangents[1] * cContact.fPT[1];
  208.  
  209.                 cContact = _cNewContact;
  210.  
  211.                 cContact.ui64Time = ui64Time;
  212.                 cContact.fPN = fPN;
  213.                 cContact.fPT[0] = vLambdaT.Dot(_cNewContact.vWorldTangents[0]);
  214.                 cContact.fPT[1] = vLambdaT.Dot(_cNewContact.vWorldTangents[1]);
  215.         }
  216.  
  217.         inline void EmptyContact(unsigned int _ui32Index) {
  218.                 m_cContacts[_ui32Index] = CM_MANIFOLD_CONTACT();
  219.         }
  220.  
  221.         inline void Update(const CMatrix4x4& _mWorldA, const CMatrix4x4& _mWorldB) {
  222.                 for (unsigned int I = 0U; I < m_ui32TotalContacts; ++I) {
  223.                         CM_MANIFOLD_CONTACT& cContact = m_cContacts[I];
  224.                         ++cContact.ui64Time;
  225.  
  226.                         CVector3 vWorldA = _mWorldA * cContact.vLocalPointOnA;
  227.                         CVector3 vWorldB = _mWorldB * cContact.vLocalPointOnB;
  228.  
  229.                         CVector3 vDiffA = vWorldA - cContact.vWorldPointOnA;
  230.                         CVector3 vDiffB = vWorldB - cContact.vWorldPointOnB;
  231.                         CVector3 vDiff = vWorldB - vWorldA;
  232.  
  233.                         cContact.vWorldPointOnA = vWorldA;
  234.                         cContact.vWorldPointOnB = vWorldB;
  235.                         cContact.fDistance = vDiff.Dot(cContact.vWorldNormalOnB);
  236.                         cContact.fPNB = ML_ZERO;
  237.  
  238.                         bool bStillPenetrating = cContact.fDistance <= ML_ZERO;
  239.                         bool bRACloseEnough = vDiffA.LenSq() < CONTACT_POINT_BREAKING_LENGTH_SQ;
  240.                         bool bRBCloseEnough = vDiffB.LenSq() < CONTACT_POINT_BREAKING_LENGTH_SQ;
  241.  
  242.                         if (!(bRACloseEnough && bRBCloseEnough)) {
  243.                                 RemoveContact(I);
  244.                         }
  245.                 }
  246.         }
  247.  
  248.         inline bool LookUpAndReplace(const CM_MANIFOLD_CONTACT& _cNewContact) {
  249.                 for (unsigned int I = 0U; I < m_ui32TotalContacts; ++I) {
  250.                         CM_MANIFOLD_CONTACT& cContact = m_cContacts[I];
  251.                        
  252.                         CVector3 vDiffA = _cNewContact.vWorldPointOnA - cContact.vWorldPointOnA;
  253.                         CVector3 vDiffB = _cNewContact.vWorldPointOnB - cContact.vWorldPointOnB;
  254.  
  255.                         bool bRAFarEnough = vDiffA.LenSq() > CONTACT_POINT_BREAKING_LENGTH_SQ;
  256.                         bool bRBFarEnough = vDiffB.LenSq() > CONTACT_POINT_BREAKING_LENGTH_SQ;
  257.  
  258.                         if ( bRAFarEnough && bRBFarEnough ) {
  259.                                 ReplaceContact(_cNewContact, I);
  260.                                 return true;
  261.                         }
  262.                 }
  263.                 return false;
  264.         }
  265.  
  266. //protected :
  267.         CM_MANIFOLD_CONTACT m_cContacts[MANIFOLD_CACHE_SIZE];
  268.         unsigned int m_ui32TotalContacts;
  269. };
  270.  
  271. #endif //#ifndef __CONTACT_MANIFOLD_H__
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement