Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

156 lines
5.4 KiB

  1. //========= Copyright � Valve Corporation, All rights reserved. ============//
  2. // This is analogous to RnWorld from source2, but only for softbodies
  3. //
  4. #include "mathlib/softbodyenvironment.h"
  5. //-----------------------------------------------------------------------------------------------------------------------------
  6. CSoftbodyCollisionFilter::CSoftbodyCollisionFilter()
  7. {
  8. V_memset( m_GroupPairs, 0, sizeof( m_GroupPairs ) );
  9. // Allow default-default shape collision by default to avoid confusion,
  10. // in test worlds that won't set up their own collision filtering.
  11. // INTERSECTION_COLLISION_GROUP_ALWAYS is the default collision group
  12. InitGroup( COLLISION_GROUP_ALWAYS, INTERSECTION_PAIR_DEFAULT_COLLISION );
  13. }
  14. //-----------------------------------------------------------------------------------------------------------------------------
  15. uint16 CSoftbodyCollisionFilter::TestSimulation( const RnCollisionAttr_t &left, const RnCollisionAttr_t &right )const
  16. {
  17. Assert( left.m_nCollisionGroup < MAX_GROUPS && right.m_nCollisionGroup < MAX_GROUPS );
  18. uint16 nIntersectionFlags = 0;
  19. if ( left.IsSolidContactEnabled() && right.IsSolidContactEnabled() )
  20. {
  21. // Return value from a table of PxPairFlags.
  22. nIntersectionFlags = m_GroupPairs[ left.m_nCollisionGroup ][ right.m_nCollisionGroup ];
  23. }
  24. if ( ( ( left.m_nInteractsAs & right.m_nInteractsExclude ) | ( left.m_nInteractsExclude & right.m_nInteractsAs ) ) != 0 )
  25. {
  26. nIntersectionFlags = 0;
  27. }
  28. else if ( ( ( left.m_nInteractsAs & right.m_nInteractsWith ) | ( left.m_nInteractsWith & right.m_nInteractsAs ) ) != 0 )
  29. {
  30. nIntersectionFlags |= INTERSECTION_PAIR_TRIGGER;
  31. }
  32. else if ( left.m_nCollisionGroup == COLLISION_GROUP_CONDITIONALLY_SOLID || right.m_nCollisionGroup == COLLISION_GROUP_CONDITIONALLY_SOLID )
  33. {
  34. nIntersectionFlags = 0;
  35. }
  36. if ( !left.IsTouchEventEnabled() || !right.IsTouchEventEnabled() )
  37. {
  38. nIntersectionFlags &= ~INTERSECTION_PAIR_TRIGGER;
  39. }
  40. // no interactions within the same hierarchy
  41. // 0xFFFF is a special case because entindex() is -1 for all client-side-only entities
  42. if ( left.m_nHierarchyId != 0 && left.m_nHierarchyId != 0xFFFF && left.m_nHierarchyId == right.m_nHierarchyId )
  43. {
  44. nIntersectionFlags = 0;
  45. }
  46. return nIntersectionFlags;
  47. }
  48. //-----------------------------------------------------------------------------------------------------------------------------
  49. void CSoftbodyCollisionFilter::InitGroup( int nGroup, CollisionGroupPairFlags defaultFlags )
  50. {
  51. for ( int i = 0; i < MAX_GROUPS; ++i )
  52. {
  53. m_GroupPairs[ i ][ nGroup ] = m_GroupPairs[ nGroup ][ i ] = defaultFlags;
  54. }
  55. m_GroupPairs[ COLLISION_GROUP_ALWAYS ][ nGroup ] = m_GroupPairs[ nGroup ][ COLLISION_GROUP_ALWAYS ] = INTERSECTION_PAIR_DEFAULT_COLLISION;
  56. m_GroupPairs[ COLLISION_GROUP_TRIGGER ][ nGroup ] = m_GroupPairs[ nGroup ][ COLLISION_GROUP_TRIGGER ] = 0;
  57. }
  58. AABB_t CSoftbodyCollisionSphere::GetBbox()const
  59. {
  60. AABB_t aabb;
  61. aabb.m_vMinBounds = m_vCenter - Vector( m_flRadius, m_flRadius, m_flRadius );
  62. aabb.m_vMaxBounds = m_vCenter + Vector( m_flRadius, m_flRadius, m_flRadius );
  63. return aabb;
  64. }
  65. AABB_t CSoftbodyCollisionCapsule::GetBbox()const
  66. {
  67. AABB_t aabb;
  68. aabb.m_vMinBounds = VectorMin( m_vCenter[ 0 ], m_vCenter[ 1 ] ) - Vector( m_flRadius, m_flRadius, m_flRadius );
  69. aabb.m_vMaxBounds = VectorMax( m_vCenter[ 0 ], m_vCenter[ 1 ] ) + Vector( m_flRadius, m_flRadius, m_flRadius );
  70. return aabb;
  71. }
  72. void CSoftbodyEnvironment::Add( CSoftbodyCollisionShape * pShape )
  73. {
  74. if ( pShape->GetProxyId() >= 0 )
  75. return; // already added
  76. AABB_t bbox = pShape->GetBbox();
  77. // bbox.Expand( 8 ); // when we add the shape for the first time, we might not know if it's going to move at all - so a good heuristic might be to NOT expand the proxy bounds at first
  78. int32 nProxyId = m_BroadphaseTree.CreateProxy( bbox, pShape );
  79. pShape->SetProxyId( nProxyId );
  80. }
  81. void CSoftbodyEnvironment::Update( CSoftbodyCollisionShape * pShape )
  82. {
  83. int32 nProxyId = pShape->GetProxyId();
  84. if ( nProxyId < 0 )
  85. return; // proxy not added to the broadphase
  86. // Did the bbox move enough to warrant moving the proxy?
  87. AABB_t bbox = pShape->GetBbox();
  88. if ( !m_BroadphaseTree.GetBounds( nProxyId).Contains( bbox ) )
  89. {
  90. bbox.Expand( 8 ); // we moved the proxy... maybe a good heuristic here would be to keep track of movements and expand adaptively, depending on how much the proxy moves
  91. m_BroadphaseTree.MoveProxy( nProxyId, bbox );
  92. }
  93. }
  94. void CSoftbodyEnvironment::AddOrUpdate( CSoftbodyCollisionShape * pShape )
  95. {
  96. int32 nProxyId = pShape->GetProxyId();
  97. // Did the bbox move enough to warrant moving the proxy?
  98. AABB_t bbox = pShape->GetBbox();
  99. if ( nProxyId < 0 )
  100. {
  101. int32 nProxyId = m_BroadphaseTree.CreateProxy( bbox, pShape );
  102. pShape->SetProxyId( nProxyId );
  103. }
  104. else if ( !m_BroadphaseTree.GetBounds( nProxyId ).Contains( bbox ) )
  105. {
  106. bbox.Expand( 8 ); // we moved the proxy... maybe a good heuristic here would be to keep track of movements and expand adaptively, depending on how much the proxy moves
  107. m_BroadphaseTree.MoveProxy( nProxyId, bbox );
  108. }
  109. }
  110. void CSoftbodyEnvironment::Remove( CSoftbodyCollisionShape * pShape )
  111. {
  112. int nProxyId = pShape->GetProxyId();
  113. if ( nProxyId >= 0 )
  114. {
  115. m_BroadphaseTree.DestroyProxy( pShape->GetProxyId() );
  116. pShape->SetProxyId( -1 );
  117. }
  118. }
  119. void CSoftbodyEnvironment::SetWind( const Vector & vWind )
  120. {
  121. float flStrength = vWind.Length();
  122. if ( fabsf( m_vWindDesc.w ) < FLT_EPSILON )
  123. {
  124. SetNoWind();
  125. }
  126. else
  127. {
  128. m_vWindDesc.Init( vWind / flStrength, flStrength );
  129. }
  130. }