BVB Source Codes

CRYENGINE Show DynamicCoverManager.cpp Source code

Return Download CRYENGINE: download DynamicCoverManager.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. #include "StdAfx.h"
  4. #include "DynamicCoverManager.h"
  5. #include "CoverSystem.h"
  6.  
  7. const bool DynamicCoverDeferred = false;
  8.  
  9. void DynamicCoverManager::OnEntityEvent(IEntity* entity, SEntityEvent& event)
  10. {
  11.         assert(m_entityCover.find(entity->GetId()) != m_entityCover.end());
  12.         assert((event.event == ENTITY_EVENT_XFORM) || (event.event == ENTITY_EVENT_DONE));
  13.  
  14.         EntityId entityID = entity->GetId();
  15.  
  16.         if (event.event == ENTITY_EVENT_XFORM)
  17.                 MoveEvent(entityID, entity->GetWorldTM());
  18.         else
  19.                 RemoveEntity(entityID);
  20. }
  21.  
  22. DynamicCoverManager::DynamicCoverManager()
  23.         : m_segmentsGrid(20.0f, 20.0f, 20.0f, segment_position(m_segments))
  24. {
  25. }
  26.  
  27. void DynamicCoverManager::AddValidationSegment(const ValidationSegment& segment)
  28. {
  29.         size_t index;
  30.  
  31.         if (m_freeSegments.empty())
  32.         {
  33.                 index = m_segments.size();
  34.                 m_segments.push_back(segment);
  35.         }
  36.         else
  37.         {
  38.                 index = m_freeSegments.back();
  39.                 m_freeSegments.pop_back();
  40.  
  41.                 ValidationSegment& slot = m_segments[index];
  42.                 slot = segment;
  43.         }
  44.         assert(m_segmentsGrid.find(segment.center, index) == m_segmentsGrid.end());
  45.         m_segmentsGrid.insert(segment.center, index);
  46.         assert(m_segments.capacity() < (512 << 10));
  47. }
  48.  
  49. void DynamicCoverManager::RemoveSurfaceValidationSegments(const CoverSurfaceID& surfaceID)
  50. {
  51.         Segments::iterator it = m_segments.begin();
  52.         Segments::iterator end = m_segments.end();
  53.  
  54.         size_t pushbackCount = 0;
  55.  
  56.         for (; it != end; ++it)
  57.         {
  58.                 ValidationSegment& segment = *it;
  59.  
  60.                 if (segment.surfaceID == surfaceID)
  61.                 {
  62.                         segment.surfaceID = CoverSurfaceID(0);
  63.  
  64.                         size_t index = (size_t)std::distance(m_segments.begin(), it);
  65.                         m_freeSegments.push_back(static_cast<uint16>(index));
  66.  
  67.                         SegmentsGrid::iterator gridIt = m_segmentsGrid.find(segment.center, index);
  68.                         assert(gridIt != m_segmentsGrid.end());
  69.                         if (gridIt != m_segmentsGrid.end())
  70.                                 m_segmentsGrid.erase(gridIt);
  71.                         ++pushbackCount;
  72.                 }
  73.         }
  74.  
  75.         ValidationQueue::iterator qit = m_validationQueue.begin();
  76.         ValidationQueue::iterator qend = m_validationQueue.end();
  77.  
  78.         if (pushbackCount > 0)
  79.         {
  80.                 for (; qit != qend; )
  81.                 {
  82.                         QueuedValidation& queued = *qit;
  83.  
  84.                         if (std::find(m_freeSegments.end() - pushbackCount, m_freeSegments.end(), queued.validationSegmentIdx) != m_freeSegments.end())
  85.                         {
  86.                                 std::swap(queued, m_validationQueue.back());
  87.                                 m_validationQueue.pop_back();
  88.                                 qend = m_validationQueue.end();
  89.                         }
  90.                         else
  91.                                 ++qit;
  92.                 }
  93.         }
  94. }
  95.  
  96. void DynamicCoverManager::AddEntity(EntityId entityID)
  97. {
  98.         gEnv->pEntitySystem->AddEntityEventListener(entityID, ENTITY_EVENT_XFORM, this);
  99.         gEnv->pEntitySystem->AddEntityEventListener(entityID, ENTITY_EVENT_DONE, this);
  100.  
  101.         m_entityCover.insert(EntityCover::value_type(entityID, EntityCoverState(gEnv->pTimer->GetFrameStartTime())));
  102. }
  103.  
  104. void DynamicCoverManager::RemoveEntity(EntityId entityID)
  105. {
  106.         EntityCover::iterator it = m_entityCover.find(entityID);
  107.  
  108.         if (it != m_entityCover.end())
  109.         {
  110.                 EntityCoverState& state = it->second;
  111.  
  112.                 RemoveEntity(it->first, state);
  113.  
  114.                 m_entityCover.erase(it);
  115.         }
  116. }
  117.  
  118. void DynamicCoverManager::RemoveEntity(EntityId entityID, EntityCoverState& state)
  119. {
  120.         gEnv->pEntitySystem->RemoveEntityEventListener(entityID, ENTITY_EVENT_XFORM, this);
  121.         gEnv->pEntitySystem->RemoveEntityEventListener(entityID, ENTITY_EVENT_DONE, this);
  122.  
  123.         m_entityCoverSampler.Cancel(entityID);
  124.  
  125.         RemoveEntityCoverSurfaces(state);
  126. }
  127.  
  128. void DynamicCoverManager::Reset()
  129. {
  130.         m_validationQueue.clear();
  131. }
  132.  
  133. void DynamicCoverManager::Clear()
  134. {
  135.         ClearValidationSegments();
  136.  
  137.         EntityCover::iterator it = m_entityCover.begin();
  138.         EntityCover::iterator end = m_entityCover.end();
  139.  
  140.         for (; it != end; ++it)
  141.         {
  142.                 EntityCoverState& state = it->second;
  143.  
  144.                 RemoveEntity(it->first, state);
  145.         }
  146.  
  147.         m_entityCoverSampler.Clear();
  148.         m_entityCover.clear();
  149. }
  150.  
  151. void DynamicCoverManager::ClearValidationSegments()
  152. {
  153.         m_segments.clear();
  154.         m_segmentsGrid.clear();
  155.         m_freeSegments.clear();
  156.         m_validationQueue.clear();
  157. }
  158.  
  159. void DynamicCoverManager::Update(float updateTime)
  160. {
  161.         PREFAST_SUPPRESS_WARNING(6239);
  162.         if (!DynamicCoverDeferred && !m_validationQueue.empty())
  163.                 ValidateOne();
  164.  
  165.         EntityCover::iterator it = m_entityCover.begin();
  166.         EntityCover::iterator end = m_entityCover.end();
  167.  
  168.         CTimeValue now = gEnv->pTimer->GetFrameStartTime();
  169.  
  170.         for (; it != end; ++it)
  171.         {
  172.                 EntityCoverState& state = it->second;
  173.  
  174.                 if (state.state == EntityCoverState::Moving)
  175.                 {
  176.                         if ((now - state.lastMovement).GetMilliSecondsAsInt64() >= 150)
  177.                         {
  178.                                 state.state = EntityCoverState::Sampling;
  179.  
  180.                                 m_entityCoverSampler.Queue(it->first, functor(*this, &DynamicCoverManager::EntityCoverSampled));
  181.                         }
  182.                 }
  183.         }
  184.  
  185.         m_entityCoverSampler.Update();
  186. }
  187.  
  188. void DynamicCoverManager::EntityCoverSampled(EntityId entityID, EntityCoverSampler::ESide side,
  189.                                              const ICoverSystem::SurfaceInfo& surfaceInfo)
  190. {
  191.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  192.  
  193.         EntityCover::iterator it = m_entityCover.find(entityID);
  194.         assert(it != m_entityCover.end());
  195.  
  196.         if (it != m_entityCover.end())
  197.         {
  198.                 EntityCoverState& state = it->second;
  199.  
  200.                 if (side == EntityCoverSampler::LastSide)
  201.                         state.state = EntityCoverState::Sampled;
  202.  
  203.                 if (surfaceInfo.sampleCount > 0)
  204.                 {
  205.                         if (state.surfaceID[side])
  206.                                 gAIEnv.pCoverSystem->UpdateSurface(state.surfaceID[side], surfaceInfo);
  207.                         else
  208.                                 state.surfaceID[side] = gAIEnv.pCoverSystem->AddSurface(surfaceInfo);
  209.                 }
  210.                 else if (state.surfaceID[side])
  211.                 {
  212.                         gAIEnv.pCoverSystem->RemoveSurface(state.surfaceID[side]);
  213.                         state.surfaceID[side] = CoverSurfaceID(0);
  214.                 }
  215.         }
  216. }
  217.  
  218. void DynamicCoverManager::RemoveEntityCoverSurfaces(EntityCoverState& state)
  219. {
  220.         for (size_t i = 0; i < 4; ++i)
  221.         {
  222.                 if (state.surfaceID[i])
  223.                 {
  224.                         gAIEnv.pCoverSystem->RemoveSurface(state.surfaceID[i]);
  225.                         state.surfaceID[i] = CoverSurfaceID(0);
  226.                 }
  227.         }
  228. }
  229.  
  230. void DynamicCoverManager::BreakEvent(const Vec3& position, float radius)
  231. {
  232.         m_dirtyBuf.clear();
  233.  
  234.         if (size_t count = m_segmentsGrid.query_sphere(position, radius, m_dirtyBuf))
  235.         {
  236.                 for (size_t i = 0; i < count; ++i)
  237.                         QueueValidation(m_dirtyBuf[i]);
  238.         }
  239. }
  240.  
  241. void DynamicCoverManager::MoveEvent(EntityId entityID, const Matrix34& worldTM)
  242. {
  243.         EntityCover::iterator it = m_entityCover.find(entityID);
  244.  
  245.         if (it != m_entityCover.end())
  246.         {
  247.                 EntityCoverState& state = it->second;
  248.  
  249.                 if (!state.lastWorldTM.GetTranslation().IsEquivalent(worldTM.GetTranslation(), 0.075f) || !Matrix33::IsEquivalent(Matrix33(state.lastWorldTM), Matrix33(worldTM), 0.0125f))
  250.                 {
  251.                         m_entityCoverSampler.Cancel(entityID);
  252.  
  253.                         state.state = EntityCoverState::Moving;
  254.                         state.lastMovement = gEnv->pTimer->GetFrameStartTime();
  255.                         state.lastWorldTM = worldTM;
  256.  
  257.                         RemoveEntityCoverSurfaces(state);
  258.                 }
  259.         }
  260. }
  261.  
  262. void DynamicCoverManager::QueueValidation(int index)
  263. {
  264.         ValidationSegment& validationSegment = m_segments[index];
  265.  
  266.         if ((validationSegment.flags & ValidationSegment::Disabled) || (validationSegment.flags & ValidationSegment::Validating))
  267.                 return;
  268.  
  269.         validationSegment.flags |= ValidationSegment::Validating;
  270.  
  271.         m_validationQueue.push_back(QueuedValidation(index));
  272.  
  273.         if (DynamicCoverDeferred)
  274.         {
  275.                 if (m_validationQueue.size() == 1)
  276.                         ValidateOne();
  277.         }
  278. }
  279.  
  280. void DynamicCoverManager::ValidateOne()
  281. {
  282.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  283.  
  284.         QueuedValidation& queuedValidation = m_validationQueue.front();
  285.         assert(queuedValidation.waitingCount == 0);
  286.  
  287.         ValidationSegment& validationSegment = m_segments[queuedValidation.validationSegmentIdx];
  288.  
  289.         const float ValidationGrounOffset = 0.35f;
  290.         const float ValidationVerticalSpacing = 0.075f;
  291.         const float ValidationTraceLength = 0.5f;
  292.  
  293.         const float radius = min(0.15f, validationSegment.length * 0.25f);
  294.         Vec3 dir = -validationSegment.normal * ValidationTraceLength;
  295.  
  296.         primitives::sphere sphere;
  297.         sphere.center = validationSegment.center + validationSegment.normal * (radius + 0.025f);
  298.         sphere.r = radius;
  299.  
  300.         float centerZ = validationSegment.center.z + ValidationGrounOffset + radius;
  301.         float maxZ = validationSegment.center.z + validationSegment.height;
  302.  
  303.         if (DynamicCoverDeferred)
  304.         {
  305.                 while (centerZ < maxZ)
  306.                 {
  307.                         sphere.center.z = centerZ;
  308.  
  309.                         ++queuedValidation.waitingCount;
  310.                         ++queuedValidation.negativeCount;
  311.  
  312.                         gAIEnv.pIntersectionTester->Queue(IntersectionTestRequest::HighestPriority,
  313.                                                           IntersectionTestRequest(sphere.type, sphere, dir, ent_static | ent_terrain),
  314.                                                           functor(*this, &DynamicCoverManager::IntersectionTestComplete));
  315.  
  316.                         //GetAISystem()->AddDebugLine(sphere.center, sphere.center + dir, 255, 255, 128, 5.0f);
  317.  
  318.                         centerZ += radius + ValidationVerticalSpacing;
  319.                 }
  320.         }
  321.         else
  322.         {
  323.                 validationSegment.flags &= ~ValidationSegment::Validating;
  324.  
  325.                 sphere.center.z = centerZ;
  326.                 Vec3 end = sphere.center + dir;
  327.  
  328.                 Vec3 boxMin(min(sphere.center.x, end.x), min(sphere.center.y, end.y), min(sphere.center.z, end.z));
  329.                 boxMin -= Vec3(radius, radius, radius);
  330.  
  331.                 Vec3 boxMax(max(sphere.center.x, end.x), max(sphere.center.y, end.y), boxMin.z + validationSegment.height);
  332.                 boxMax += Vec3(radius, radius, radius);
  333.  
  334.                 uint32 collisionEntities = CoverCollisionEntities;
  335.                 if (collisionEntities & ent_static)
  336.                         collisionEntities |= ent_rigid | ent_sleeping_rigid; // support 0-mass rigid entities too
  337.  
  338.                 IPhysicalEntity** entityList = 0;
  339.                 size_t entityCount = (size_t)GetPhysicalEntitiesInBox(boxMin, boxMax, entityList, collisionEntities);
  340.  
  341.                 if (entityCount)
  342.                 {
  343.                         if (CoverCollisionEntities & ent_static)
  344.                         {
  345.                                 for (size_t i = 0; i < entityCount; ++i)
  346.                                 {
  347.                                         IPhysicalEntity* entity = entityList[i];
  348.  
  349.                                         if (entity->GetType() == PE_RIGID)
  350.                                         {
  351.                                                 pe_status_dynamics status;
  352.  
  353.                                                 if (entity->GetStatus(&status))
  354.                                                 {
  355.                                                         if ((status.mass > 0.00001f) && (status.mass < 99999.9999f)) // 99 tons won't move
  356.                                                         {
  357.                                                                 entityList[i] = entityList[--entityCount];
  358.                                                                 --i;
  359.                                                         }
  360.                                                 }
  361.                                         }
  362.                                 }
  363.                         }
  364.  
  365.                         if (entityCount)
  366.                         {
  367.                                 while (centerZ < maxZ)
  368.                                 {
  369.                                         sphere.center.z = centerZ;
  370.  
  371.                                         float closest = FLT_MAX;
  372.                                         IPhysicalEntity* closestEntity = 0;
  373.  
  374.                                         ray_hit hit;
  375.                                         for (size_t i = 0; i < entityCount; ++i)
  376.                                         {
  377.                                                 if (gEnv->pPhysicalWorld->CollideEntityWithPrimitive(entityList[i], primitives::sphere::type, &sphere, dir, &hit))
  378.                                                 {
  379.                                                         if (hit.dist < closest)
  380.                                                         {
  381.                                                                 closest = hit.dist + radius;
  382.                                                                 closestEntity = entityList[i];
  383.                                                         }
  384.                                                 }
  385.                                         }
  386.  
  387.                                         if (!closestEntity)
  388.                                         {
  389.                                                 validationSegment.flags |= ValidationSegment::Disabled;
  390.  
  391.                                                 CoverSurface& surface = gAIEnv.pCoverSystem->GetCoverSurface(validationSegment.surfaceID);
  392.  
  393.                                                 if (surface.IsValid())
  394.                                                 {
  395.                                                         CoverSurface::Segment& segment = surface.GetSegment(validationSegment.segmentIdx);
  396.  
  397.                                                         segment.flags |= CoverSurface::Segment::Disabled;
  398.                                                 }
  399.                                                 break;
  400.                                         }
  401.  
  402.                                         centerZ += radius + ValidationVerticalSpacing;
  403.                                 }
  404.                         }
  405.                 }
  406.  
  407.                 m_validationQueue.pop_front();
  408.         }
  409. }
  410.  
  411. void DynamicCoverManager::IntersectionTestComplete(const QueuedIntersectionID& intID, const IntersectionTestResult& result)
  412. {
  413.         if (!m_validationQueue.empty())
  414.         {
  415.                 QueuedValidation& queuedValidation = m_validationQueue.front();
  416.                 assert(queuedValidation.waitingCount > 0);
  417.  
  418.                 --queuedValidation.waitingCount;
  419.                 queuedValidation.negativeCount -= result ? 1 : 0;
  420.  
  421.                 if (!queuedValidation.waitingCount)
  422.                 {
  423.                         ValidationSegment& validationSegment = m_segments[queuedValidation.validationSegmentIdx];
  424.                         validationSegment.flags &= ~ValidationSegment::Validating;
  425.  
  426.                         if (queuedValidation.negativeCount)
  427.                         {
  428.                                 validationSegment.flags |= ValidationSegment::Disabled;
  429.  
  430.                                 CoverSurface& surface = gAIEnv.pCoverSystem->GetCoverSurface(validationSegment.surfaceID);
  431.  
  432.                                 if (surface.IsValid())
  433.                                 {
  434.                                         CoverSurface::Segment& segment = surface.GetSegment(validationSegment.segmentIdx);
  435.  
  436.                                         segment.flags |= CoverSurface::Segment::Disabled;
  437.                                 }
  438.                         }
  439.  
  440.                         m_validationQueue.pop_front();
  441.  
  442.                         if (DynamicCoverDeferred)
  443.                         {
  444.                                 if (!m_validationQueue.empty())
  445.                                         ValidateOne();
  446.                         }
  447.                 }
  448.         }
  449. }
  450.  
downloadDynamicCoverManager.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top