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.

158 lines
4.7 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //===========================================================================//
  7. #include "cbase.h"
  8. #include "pvs_extender.h"
  9. #include "util_shared.h"
  10. #include "tier1/utlvector.h"
  11. // memdbgon must be the last include file in a .cpp file!!!
  12. #include "tier0/memdbgon.h"
  13. static CUtlVector<CPVS_Extender *> s_AllExtenders;
  14. CPVS_Extender::CPVS_Extender( void )
  15. {
  16. s_AllExtenders.AddToTail( this );
  17. }
  18. CPVS_Extender::~CPVS_Extender( void )
  19. {
  20. s_AllExtenders.FindAndFastRemove( this );
  21. }
  22. void CPVS_Extender::ComputeExtendedPVS( const CBaseEntity *pViewEntity, const Vector &vVisOrigin, unsigned char *outputPVS, int pvssize, int iMaxRecursions )
  23. {
  24. int iAllExtenderCount = s_AllExtenders.Count();
  25. if( iAllExtenderCount == 0 )
  26. return;
  27. static CThreadFastMutex s_PVSExtenderMutex;
  28. AUTO_LOCK_FM( s_PVSExtenderMutex );
  29. CPVS_Extender **pAllExtenders = s_AllExtenders.Base();
  30. int iExtenderCount = 0;
  31. CPVS_Extender **pExtenders = (CPVS_Extender **)stackalloc( sizeof( CPVS_Extender * ) * iAllExtenderCount );
  32. //filter out portals that can't possibly extend visibility up-front. So we don't have to do so in our recursions
  33. for( int i = 0; i != iAllExtenderCount; ++i )
  34. {
  35. CPVS_Extender *pExtender = pAllExtenders[i];
  36. Assert( pExtender );
  37. if ( pExtender->IsExtenderValid() )
  38. {
  39. if ( pExtender->GetExtenderNetworkProp()->AreaNum() < 0 )
  40. {
  41. Assert( false );
  42. continue;
  43. }
  44. pExtenders[iExtenderCount] = pExtender;
  45. ++iExtenderCount;
  46. }
  47. }
  48. if( iExtenderCount == 0 )
  49. return;
  50. int iAreasNetworked[MAX_MAP_AREAS];
  51. iAreasNetworked[0] = pViewEntity->NetworkProp()->AreaNum(); //safe assumption?
  52. for( int i = 1; i != MAX_MAP_AREAS; ++i )
  53. {
  54. iAreasNetworked[i] = -1;
  55. }
  56. //unsigned char *viewEntPVS = (unsigned char *)stackalloc( sizeof( unsigned char ) * pvssize );
  57. //memcpy( viewEntPVS, outputPVS, sizeof( unsigned char ) * pvssize );
  58. unsigned char viewEntPVS[MAX_MAP_LEAFS/8];
  59. engine->GetPVSForCluster( engine->GetClusterForOrigin( vVisOrigin ), sizeof( viewEntPVS ), viewEntPVS );
  60. //do we OR that into the output PVS?
  61. //grab the local pvs of every extender up front to avoid repeating it in recursions
  62. //unsigned char *pExtenderPVSs = (unsigned char *)stackalloc( sizeof( unsigned char ) * (MAX_MAP_LEAFS/8) * iPortalCount );
  63. ExtenderInstanceData_t *pExtenderData = (ExtenderInstanceData_t *)stackalloc( sizeof( ExtenderInstanceData_t ) * iExtenderCount );
  64. for( int i = 0; i != iExtenderCount; ++i )
  65. {
  66. pExtenders[i]->m_pExtenderData = &pExtenderData[i];
  67. engine->GetPVSForCluster( engine->GetClusterForOrigin( pExtenders[i]->GetExtensionPVSOrigin() ), sizeof( unsigned char ) * (MAX_MAP_LEAFS/8), pExtenderData[i].iPVSBits );
  68. pExtenders[i]->m_pExtenderData->bAddedToPVSAlready = false;
  69. }
  70. VisExtensionChain_t chainRoot;
  71. chainRoot.m_nArea = iAreasNetworked[0];
  72. chainRoot.pParentChain = NULL;
  73. const edict_t *viewEdict = pViewEntity->edict();
  74. for( int i = 0; i != iExtenderCount; ++i )
  75. {
  76. CPVS_Extender *pExtender = pExtenders[i];
  77. if ( pExtender->GetExtenderEdict() == viewEdict )
  78. continue;
  79. if ( pExtender->GetExtenderNetworkProp()->IsInPVS( viewEdict, viewEntPVS, pvssize ) ) //test against pViewEntity PVS, not aggregate PVS
  80. {
  81. chainRoot.pExtender = pExtender;
  82. pExtender->ComputeSubVisibility( pExtenders, iExtenderCount, outputPVS, pvssize, vVisOrigin, NULL, 0, &chainRoot, iAreasNetworked, iMaxRecursions );
  83. }
  84. }
  85. for( int i = 0; i != iExtenderCount; ++i )
  86. {
  87. pExtenders[i]->m_pExtenderData = NULL;
  88. }
  89. }
  90. //does the grunt work of checking if the data has already been added, and if not, adding it
  91. /*void CPVS_Extender::AddToPVS( unsigned char *outputPVS, int pvssize, int iAreasNetworked[MAX_MAP_AREAS] )
  92. {
  93. if( !m_pExtenderData->bAddedToPVSAlready )
  94. {
  95. bool bFound = false;
  96. for( int i = 0; i != MAX_MAP_AREAS; ++i )
  97. {
  98. if( iAreasNetworked[i] == iLinkedArea )
  99. {
  100. bFound = true;
  101. break;
  102. }
  103. if( iAreasNetworked[i] == -1 )
  104. {
  105. bFound = true; //we found it by adding it
  106. iAreasNetworked[i] = iLinkedArea;
  107. int iOutputPVSIntSize = pvssize / sizeof( unsigned int );
  108. for( int j = 0; j != iOutputPVSIntSize; ++j )
  109. {
  110. ((unsigned int *)outputPVS)[j] |= ((unsigned int *)pLinkedPVS)[j];
  111. }
  112. for( int j = iOutputPVSIntSize * sizeof( unsigned int ); j != pvssize; ++j )
  113. {
  114. outputPVS[j] |= pLinkedPVS[j];
  115. }
  116. break;
  117. }
  118. }
  119. if( !bFound )
  120. return;
  121. AddPortalCornersToEnginePVS( pLinkedPortal );
  122. m_pExtenderData->bAddedToPVSAlready = true;
  123. }
  124. }*/