BVB Source Codes

CRYENGINE Show AIHideObject.cpp Source code

Return Download CRYENGINE: download AIHideObject.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. /********************************************************************
  4.    -------------------------------------------------------------------------
  5.    File name:   AIHideObject.cpp
  6.    $Id$
  7.    Description:
  8.  
  9.    -------------------------------------------------------------------------
  10.    History:
  11.    - 2:6:2005   16:26 : Created by Kirill Bulatsev
  12.    - 2 Mar 2009                  : Evgeny Adamenkov: Replaced IRenderer with CDebugDrawContext
  13.  
  14.  *********************************************************************/
  15.  
  16. #include "StdAfx.h"
  17. #include "CAISystem.h"
  18. #include "AIHideObject.h"
  19. #include "NavRegion.h"
  20. #include "PipeUser.h"
  21. #include <math.h>
  22. #include "DebugDrawContext.h"
  23. #include "HideSpot.h"
  24.  
  25. static const float LOW_COVER_OFFSET = 0.7f;
  26. static const float HIGH_COVER_OFFSET = 1.7f;
  27. static const int REFINE_SAMPLES = 4;
  28. static const float STEP_SIZE = 0.75f;
  29. static const float SAMPLE_DIST = 0.45f;
  30. static const float SAMPLE_RADIUS = 0.15f;
  31.  
  32. static const float DEFAULT_AGENT_RADIUS = 0.4f;
  33. static const IAISystem::tNavCapMask DEFAULT_AGENT_NAVMASK =
  34.   IAISystem::NAV_TRIANGULAR |
  35.   IAISystem::NAV_WAYPOINT_HUMAN;
  36.  
  37. //
  38. //-------------------------------------------------------------------------------------------------------------
  39. CAIHideObject::CAIHideObject()
  40.         : m_bIsValid(false)
  41.         , m_isUsingCover(false)
  42.         , m_objectPos(ZERO)
  43.         , m_objectDir(ZERO)
  44.         , m_objectRadius(0.0f)
  45.         , m_objectHeight(0.0f)
  46.         , m_objectCollidable(false)
  47.         , m_vLastHidePos(ZERO)
  48.         , m_vLastHideDir(ZERO)
  49.         , m_bIsSmartObject(false)
  50.         , m_useCover(USECOVER_NONE)
  51.         , m_dynCoverEntityId(0)
  52.         , m_dynCoverEntityPos(ZERO)
  53.         , m_dynCoverPosLocal(ZERO)
  54.         , m_hideSpotType(SHideSpotInfo::eHST_INVALID)
  55.         , m_coverPos(ZERO)
  56.         , m_distToCover(0.0f)
  57.         , m_pathOrig(ZERO)
  58.         , m_pathDir(ZERO)
  59.         , m_pathNorm(ZERO)
  60.         , m_pathLimitLeft(0.0f)
  61.         , m_pathLimitRight(0.0f)
  62.         , m_tempCover(0.0f)
  63.         , m_tempDepth(0.0f)
  64.         , m_pathComplete(false)
  65.         , m_highCoverValid(false)
  66.         , m_lowCoverValid(false)
  67.         , m_pathHurryUp(false)
  68.         , m_lowLeftEdgeValid(false)
  69.         , m_lowRightEdgeValid(false)
  70.         , m_highLeftEdgeValid(false)
  71.         , m_highRightEdgeValid(false)
  72.         , m_lowCoverWidth(0.0f)
  73.         , m_highCoverWidth(0.0f)
  74.         , m_lowLeftEdge(0.0f)
  75.         , m_lowRightEdge(0.0f)
  76.         , m_highLeftEdge(0.0f)
  77.         , m_highRightEdge(0.0f)
  78.         , m_pathUpdateIter(0)
  79.         , m_id(0)
  80. {
  81. }
  82.  
  83. //
  84. //-------------------------------------------------------------------------------------------------------------
  85. CAIHideObject::~CAIHideObject()
  86. {
  87.  
  88. }
  89.  
  90. //
  91. //-------------------------------------------------------------------------------------------------------------
  92. void CAIHideObject::Set(const SHideSpot* hs, const Vec3& hidePos, const Vec3& hideDir)
  93. {
  94.         CCCPOINT(AIHideObject_Set);
  95.  
  96.         Vec3 oldObjPos(m_objectPos);
  97.         Vec3 oldObjDir(m_objectDir);
  98.         float oldRadius(m_objectRadius);
  99.  
  100.         m_bIsValid = (hs != NULL);
  101.         m_bIsSmartObject = m_bIsValid ? (hs->info.type == SHideSpotInfo::eHST_SMARTOBJECT) : false;
  102.  
  103.         m_dynCoverEntityId = 0;
  104.         m_dynCoverEntityPos.Set(0, 0, 0);
  105.         m_dynCoverPosLocal.Set(0, 0, 0);
  106.         m_sAnchorName.clear();
  107.  
  108.         if (hs)
  109.         {
  110.                 m_objectPos = hs->info.pos;
  111.                 m_objectDir = hs->info.dir;
  112.                 m_hideSpotType = hs->info.type;
  113.                 m_objectRadius = 0.0f;
  114.                 m_objectHeight = 0.0f;
  115.                 if (m_objectDir.IsZero())
  116.                 {
  117.                         m_objectDir = hideDir;
  118.                         if (m_objectDir.IsZero())
  119.                         {
  120.                                 m_objectDir = m_objectPos - hidePos;               // We believe these are always different
  121.                                 m_objectDir.NormalizeSafe();
  122.                         }
  123.                 }
  124.  
  125.                 if (hs->pObstacle)
  126.                 {
  127.                         // (MATT) The m_ObjectPos line below wasn't used in Crysis gold - should check the impact {2008/08/15}
  128.                         // MTJ accurately reflect position of obstacle itself
  129.                         m_objectPos = hs->pObstacle->vPos;
  130.  
  131.                         m_objectRadius = hs->pObstacle->fApproxRadius;
  132.                         if (m_objectRadius > 0.001f)
  133.                                 m_objectCollidable = hs->pObstacle->IsCollidable() != 0;
  134.                         else
  135.                                 m_objectCollidable = true;
  136.                         m_objectHeight = hs->pObstacle->GetApproxHeight();
  137.                 }
  138.                 if (hs->pAnchorObject)
  139.                 {
  140.                         if ((hs->pAnchorObject->GetType() == AIANCHOR_COMBAT_HIDESPOT) ||
  141.                             (hs->pAnchorObject->GetType() == AIANCHOR_COMBAT_HIDESPOT_SECONDARY))
  142.                         {
  143.                                 m_objectCollidable = true;
  144.                                 m_objectRadius = hs->pAnchorObject->GetRadius();
  145.                         }
  146.                         else
  147.                         {
  148.                                 m_objectCollidable = false;
  149.                                 m_objectRadius = 0.05f; // Omni directional.
  150.                         }
  151.  
  152.                         m_sAnchorName = hs->pAnchorObject->GetName();
  153.                 }
  154.                 if (hs->info.type == SHideSpotInfo::eHST_SMARTOBJECT)
  155.                 {
  156.                         m_HideSmartObject = hs->SOQueryEvent;
  157.                         if (m_HideSmartObject.pRule->pObjectHelper)
  158.                                 m_objectPos = m_HideSmartObject.pObject->GetHelperPos(m_HideSmartObject.pRule->pObjectHelper);
  159.                         else
  160.                                 m_objectPos = m_HideSmartObject.pObject->GetPos();
  161.                         m_objectDir = m_HideSmartObject.pObject->GetOrientation(m_HideSmartObject.pRule->pObjectHelper);
  162.                         m_objectCollidable = true;
  163.                 }
  164.  
  165.                 if (hs->pNavNode && hs->pNavNode->navType == IAISystem::NAV_WAYPOINT_HUMAN)
  166.                 {
  167.                         if (hs->pNavNode->GetWaypointNavData()->type == WNT_HIDESECONDARY)
  168.                         {
  169.                                 m_objectCollidable = false;
  170.                                 m_objectRadius = 0.05f; // Omni directional.
  171.                         }
  172.                         else
  173.                                 m_objectCollidable = true;
  174.                 }
  175.  
  176.                 if (hs->info.type == SHideSpotInfo::eHST_DYNAMIC)
  177.                 {
  178.                         // Get the initial position of the entity which is associated with the dyn hidespot.
  179.                         IEntity* pEnt = gEnv->pEntitySystem->GetEntity(hs->entityId);
  180.                         if (pEnt)
  181.                         {
  182.                                 // Store the original entity position.
  183.                                 m_dynCoverEntityPos = pEnt->GetWorldPos();
  184.                                 // Store the cover position in local entity space.
  185.                                 m_dynCoverPosLocal = pEnt->GetWorldRotation().GetInverted() * (hs->info.pos - pEnt->GetWorldPos());
  186.                                 // Store the entity id.
  187.                                 m_dynCoverEntityId = hs->entityId;
  188.                         }
  189.                         else
  190.                         {
  191.                                 // Could not find entity,
  192.                                 m_dynCoverEntityId = 0;
  193.                                 m_bIsValid = false;
  194.                         }
  195.                 }
  196.                 else
  197.                 {
  198.                         m_dynCoverEntityId = 0;
  199.                 }
  200.         }
  201.  
  202.         if (m_bIsValid)
  203.         {
  204.                 m_vLastHidePos = hidePos;
  205.                 m_vLastHideDir = hideDir;
  206.  
  207.                 // Marcio: Avoid re-sampling if nothing changed!
  208.                 if (!oldObjPos.IsEquivalent(m_objectPos, 0.005f) || !oldObjDir.IsEquivalent(m_objectDir, 0.005f) || (fabs_tpl(oldRadius - m_objectRadius) > 0.005f))
  209.                 {
  210.                         m_useCover = USECOVER_NONE;
  211.                         m_pathUpdateIter = 0;
  212.                         m_pathComplete = false;
  213.                         m_pathHurryUp = false;
  214.                         m_isUsingCover = true;
  215.                         m_id++;
  216.                 }
  217.         }
  218.  
  219.         if (!m_bIsValid && hidePos.GetLength() > 0.001f)
  220.         {
  221.                 CryLog("Trying to set invalid hidespots!");
  222.         }
  223. }
  224.  
  225. //
  226. //-------------------------------------------------------------------------------------------------------------
  227. void CAIHideObject::Update(CPipeUser* pOperand)
  228. {
  229.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  230.  
  231.         if (m_bIsValid && !m_bIsSmartObject)
  232.                 UpdatePathExpand(pOperand);
  233. }
  234.  
  235. bool ProjectedPointOnLine(float& u, const Vec3& lineOrig, const Vec3& lineDir, const Vec3& lineNorm, const Vec3& pt, const Vec3& target)
  236. {
  237.         Plane plane;
  238.         plane.SetPlane(lineNorm, lineOrig);
  239.         Ray r(target, pt - target);
  240.         if (r.direction.IsZero(0.000001f))
  241.                 return false;
  242.         Vec3 intr(pt);
  243.         bool res = Intersect::Ray_Plane(r, plane, intr);
  244.         u = lineDir.Dot(intr - lineOrig);
  245.         return res;
  246. }
  247.  
  248. //
  249. //-------------------------------------------------------------------------------------------------------------
  250. void CAIHideObject::GetCoverPoints(bool useLowCover, float peekOverLeft, float peekOverRight, const Vec3& targetPos, Vec3& hidePos,
  251.                                    Vec3& peekPosLeft, Vec3& peekPosRight, bool& peekLeftClamped, bool& peekRightClamped, bool& coverCompromised) const
  252. {
  253.         // Calculate the extends of the shadow cast by the cover on the walkable line.
  254.         // The returned hide point is in the middle of the umbra, and the peek points are at the extends.
  255.         // The umbra is clipped to the walkable line and the clipping status is returned too.
  256.  
  257.         if (m_pathNorm.Dot(targetPos - m_pathOrig) < 0.0f)
  258.         {
  259.                 hidePos = m_pathOrig;
  260.                 peekPosLeft = m_pathOrig;
  261.                 peekPosRight = m_pathOrig;
  262.                 peekLeftClamped = false;
  263.                 peekRightClamped = false;
  264.                 coverCompromised = true;
  265.  
  266.                 return;
  267.         }
  268.  
  269.         Plane plane;
  270.         plane.SetPlane(m_pathNorm, m_pathOrig);
  271.  
  272.         // Initialize with the center point of the cover.
  273.         float umbraLeft = FLT_MAX, umbraRight = -FLT_MAX;
  274.         if (!m_pathComplete)
  275.         {
  276.                 float u = 0.0f;
  277.                 if (ProjectedPointOnLine(u, m_pathOrig, m_pathDir, m_pathNorm, m_coverPos, targetPos))
  278.                         umbraLeft = umbraRight = u;
  279.         }
  280.  
  281.         bool coverEmpty = false;
  282.  
  283.         // Calculate the umbra (shadow of the cover).
  284.         std::deque<Vec3>::const_iterator begin, end;
  285.  
  286.         if (useLowCover)
  287.         {
  288.                 begin = m_lowCoverPoints.begin();
  289.                 end = m_lowCoverPoints.end();
  290.                 coverEmpty = m_lowCoverPoints.empty();
  291.         }
  292.         else
  293.         {
  294.                 begin = m_highCoverPoints.begin();
  295.                 end = m_highCoverPoints.end();
  296.                 coverEmpty = m_highCoverPoints.empty();
  297.         }
  298.  
  299.         if (!coverEmpty)
  300.         {
  301.                 int validPts = 0;
  302.  
  303.                 for (std::deque<Vec3>::const_iterator it = begin; it != end; ++it)
  304.                 {
  305.                         float u = 0.0f;
  306.                         if (ProjectedPointOnLine(u, m_pathOrig, m_pathDir, m_pathNorm, (*it), targetPos))
  307.                         {
  308.                                 umbraLeft = min(umbraLeft, u);
  309.                                 umbraRight = max(umbraRight, u);
  310.                                 validPts++;
  311.                         }
  312.                 }
  313.  
  314.                 if (!validPts)
  315.                 {
  316.                         hidePos = m_pathOrig;
  317.                         peekPosLeft = m_pathOrig;
  318.                         peekPosRight = m_pathOrig;
  319.                         peekLeftClamped = false;
  320.                         peekRightClamped = false;
  321.                         coverCompromised = true;
  322.  
  323.                         return;
  324.                 }
  325.         }
  326.  
  327.         float mid = (umbraLeft + umbraRight) * 0.5f;
  328.  
  329.         // Allow to reach over the edge or stay almost visible.
  330.         if (umbraLeft - peekOverLeft > mid)
  331.                 umbraLeft = mid;
  332.         else
  333.                 umbraLeft -= peekOverLeft;
  334.  
  335.         if (umbraRight + peekOverRight < mid)
  336.                 umbraRight = mid;
  337.         else
  338.                 umbraRight += peekOverRight;
  339.  
  340.         if (umbraLeft > umbraRight)
  341.                 umbraLeft = umbraRight = (umbraLeft + umbraRight) * 0.5f;
  342.  
  343.         // Clamp the umbra to the walkable line.
  344.         if (umbraLeft < m_pathLimitLeft)
  345.         {
  346.                 umbraLeft = m_pathLimitLeft;
  347.                 peekLeftClamped = true;
  348.         }
  349.         else if (umbraLeft > m_pathLimitRight)
  350.         {
  351.                 umbraLeft = m_pathLimitRight;
  352.                 peekLeftClamped = true;
  353.         }
  354.         else
  355.                 peekLeftClamped = false;
  356.  
  357.         if (umbraRight > m_pathLimitRight)
  358.         {
  359.                 umbraRight = m_pathLimitRight;
  360.                 peekRightClamped = true;
  361.         }
  362.         else if (umbraRight < m_pathLimitLeft)
  363.         {
  364.                 umbraRight = m_pathLimitLeft;
  365.                 peekRightClamped = true;
  366.         }
  367.         else
  368.                 peekRightClamped = false;
  369.  
  370.         hidePos = m_pathOrig + m_pathDir * (umbraLeft + umbraRight) * 0.5f;
  371.         peekPosLeft = m_pathOrig + m_pathDir * umbraLeft;
  372.         peekPosRight = m_pathOrig + m_pathDir * umbraRight;
  373.  
  374.         if (coverEmpty)
  375.                 coverCompromised = m_pathComplete && fabsf((umbraLeft + umbraRight) * 0.5f) > 2.0f;
  376.         else
  377.                 coverCompromised = m_pathComplete && (peekLeftClamped && peekRightClamped) && fabs(umbraRight - umbraLeft) < 0.001f;
  378. }
  379.  
  380. //
  381. //-------------------------------------------------------------------------------------------------------------
  382. void CAIHideObject::GetCoverDistances(bool useLowCover, const Vec3& target, bool& coverCompromised, float& leftEdge, float& rightEdge, float& leftUmbra, float& rightUmbra) const
  383. {
  384.         Vec3 toTarget = (target - m_pathOrig).GetNormalized();
  385.  
  386.         if (m_pathNorm.Dot(toTarget) <= 0.2f) //~80潞
  387.         {
  388.                 leftUmbra = rightUmbra = 0.0f;
  389.                 leftEdge = rightEdge = 0.0f;
  390.                 coverCompromised = true;
  391.  
  392.                 return;
  393.         }
  394.  
  395.         bool coverEmpty = false;
  396.         std::deque<Vec3>::const_iterator begin, end;
  397.  
  398.         leftUmbra = 0.0f;
  399.         rightUmbra = 0.0f;
  400.  
  401.         if (useLowCover)
  402.         {
  403.                 leftEdge = m_lowLeftEdge;
  404.                 rightEdge = m_lowRightEdge;
  405.  
  406.                 begin = m_lowCoverPoints.begin();
  407.                 end = m_lowCoverPoints.end();
  408.                 coverEmpty = m_lowCoverPoints.empty();
  409.         }
  410.         else
  411.         {
  412.                 leftEdge = m_highLeftEdge;
  413.                 rightEdge = m_highRightEdge;
  414.  
  415.                 begin = m_highCoverPoints.begin();
  416.                 end = m_highCoverPoints.end();
  417.                 coverEmpty = m_highCoverPoints.empty();
  418.         }
  419.  
  420.         if (!coverEmpty)
  421.         {
  422.                 bool validFound = false;
  423.  
  424.                 leftUmbra = FLT_MAX;
  425.                 rightUmbra = -FLT_MAX;
  426.  
  427.                 for (std::deque<Vec3>::const_iterator it = begin; it != end; ++it)
  428.                 {
  429.                         float u = 0.0f;
  430.  
  431.                         if (ProjectedPointOnLine(u, m_pathOrig, m_pathDir, m_pathNorm, *it, target))
  432.                         {
  433.                                 leftUmbra = min(leftUmbra, u);
  434.                                 rightUmbra = max(rightUmbra, u);
  435.  
  436.                                 validFound = true;
  437.                         }
  438.                 }
  439.  
  440.                 if (!validFound)
  441.                 {
  442.                         leftUmbra = rightUmbra = 0.0f;
  443.                         leftEdge = rightEdge = 0.0f;
  444.                         coverCompromised = true;
  445.  
  446.                         return;
  447.                 }
  448.         }
  449.  
  450.         const float maxInsideDisplace = 0.75f;
  451.         if ((leftUmbra > maxInsideDisplace) || (rightUmbra < -maxInsideDisplace))
  452.                 coverCompromised = true;
  453.  
  454.         if (leftUmbra < m_pathLimitLeft)
  455.                 leftUmbra = m_pathLimitLeft;
  456.         if (leftUmbra > m_pathLimitRight)
  457.                 leftUmbra = m_pathLimitRight;
  458.  
  459.         if (rightUmbra > m_pathLimitRight)
  460.                 rightUmbra = m_pathLimitRight;
  461.         if (rightUmbra < m_pathLimitLeft)
  462.                 rightUmbra = m_pathLimitLeft;
  463.  
  464.         if (!coverCompromised)
  465.         {
  466.                 if (coverEmpty)
  467.                         coverCompromised = m_pathComplete;
  468.                 else
  469.                         coverCompromised = m_pathComplete && fabsf(rightUmbra - leftUmbra) < 0.5f;
  470.         }
  471. }
  472.  
  473. //
  474. //-------------------------------------------------------------------------------------------------------------
  475. bool CAIHideObject::IsValid() const
  476. {
  477.         if (!m_bIsValid)
  478.                 return false;
  479.  
  480.         if (m_dynCoverEntityId)
  481.         {
  482.                 IEntity* pEnt = gEnv->pEntitySystem->GetEntity(m_dynCoverEntityId);
  483.                 if (!pEnt)
  484.                 {
  485.                         m_bIsValid = false;
  486.  
  487.                         return false;
  488.                 }
  489.                 else
  490.                 {
  491.                         if (Distance::Point_PointSq(pEnt->GetWorldPos(), m_dynCoverEntityPos) > sqr(0.3f))
  492.                         {
  493.                                 m_bIsValid = false;
  494.  
  495.                                 return false;
  496.                         }
  497.  
  498.                         Vec3 curPos = pEnt->GetWorldPos() + pEnt->GetWorldRotation() * m_dynCoverPosLocal;
  499.  
  500.                         if (Distance::Point_PointSq(m_objectPos, curPos) > sqr(0.3f))
  501.                         {
  502.                                 m_bIsValid = false;
  503.  
  504.                                 return false;
  505.                         }
  506.                 }
  507.         }
  508.  
  509.         return m_bIsValid;
  510. }
  511.  
  512. //
  513. //-------------------------------------------------------------------------------------------------------------
  514. bool CAIHideObject::IsCompromised(const CPipeUser* pRequester, const Vec3& target) const
  515. {
  516.         if (!IsValid())
  517.                 return true;
  518.  
  519.         if (pRequester && pRequester->IsInCover() && !IsNearCover(pRequester))
  520.                 return true;
  521.  
  522.         if (!IsCoverPathComplete())
  523.                 return false;
  524.  
  525.         bool lowCompromised = !HasLowCover();
  526.         bool highCompromised = !HasHighCover();
  527.  
  528.         float leftEdge;
  529.         float rightEdge;
  530.         float leftUmbra;
  531.         float rightUmbra;
  532.  
  533.         if (!lowCompromised)
  534.                 GetCoverDistances(true, target, lowCompromised, leftEdge, rightEdge, leftUmbra, rightUmbra);
  535.  
  536.         if (!highCompromised)
  537.                 GetCoverDistances(false, target, highCompromised, leftEdge, rightEdge, leftUmbra, rightUmbra);
  538.  
  539.         return lowCompromised && highCompromised;
  540. }
  541.  
  542. //
  543. //-------------------------------------------------------------------------------------------------------------
  544. bool CAIHideObject::IsNearCover(const CPipeUser* pRequester) const
  545. {
  546.         if (pRequester)
  547.         {
  548.                 float safeRange = 0.25f;
  549.                 if (gAIEnv.configuration.eCompatibilityMode == ECCM_CRYSIS)
  550.                         safeRange = 1.3f;
  551.  
  552.                 float agentRadius = pRequester ? pRequester->GetParameters().m_fPassRadius : DEFAULT_AGENT_RADIUS;
  553.  
  554.                 safeRange += agentRadius;
  555.  
  556.                 float dist = GetDistanceToCoverPath(pRequester->GetPhysicsPos());
  557.                 if (dist > safeRange)
  558.                         return false;
  559.  
  560.                 return true;
  561.         }
  562.  
  563.         return false;
  564. }
  565.  
  566. //
  567. //-------------------------------------------------------------------------------------------------------------
  568. float CAIHideObject::GetCoverWidth(bool useLowCover)
  569. {
  570.         if (!m_pathComplete)
  571.         {
  572.                 // Over estimate a bit.
  573.                 if (useLowCover)
  574.                         return max(0.5f, m_lowCoverWidth);
  575.                 else
  576.                         return max(0.5f, m_highCoverWidth);
  577.         }
  578.         else
  579.         {
  580.                 if (useLowCover)
  581.                         return m_lowCoverWidth;
  582.                 else
  583.                         return m_highCoverWidth;
  584.         }
  585. }
  586.  
  587. //
  588. //-------------------------------------------------------------------------------------------------------------
  589. float CAIHideObject::GetDistanceToCoverPath(const Vec3& pt) const
  590. {
  591.         Lineseg coverPath(m_pathOrig + m_pathDir * m_pathLimitLeft, m_pathOrig + m_pathDir * m_pathLimitRight);
  592.         float t;
  593.         float distToLine = Distance::Point_Lineseg2D(pt, coverPath, t);
  594.         Vec3 ptOnLine(coverPath.GetPoint(t));
  595.         float heightDist = fabsf(ptOnLine.z - pt.z);
  596.         return max(distToLine, heightDist);
  597. }
  598.  
  599. float CAIHideObject::GetMaxCoverPathLen() const
  600. {
  601.         if (gAIEnv.configuration.eCompatibilityMode == ECCM_CRYSIS2)
  602.         {
  603.                 if (m_objectRadius > 0.001f)
  604.                         return m_objectRadius * 2.0f;
  605.         }
  606.  
  607.         return 12.0f;
  608. }
  609.  
  610. Vec3 CAIHideObject::GetPointAlongCoverPath(float distance) const
  611. {
  612.         // TODO: Actually trace along the path points
  613.         return m_pathOrig + m_pathDir * distance;
  614. }
  615.  
  616. void CAIHideObject::GetCoverHeightAlongCoverPath(float distanceAlongPath, const Vec3& target, bool& hasLowCover, bool& hasHighCover) const
  617. {
  618.         /// low cover
  619.         std::deque<Vec3>::const_iterator it = m_lowCoverPoints.begin();
  620.         std::deque<Vec3>::const_iterator itEnd = m_lowCoverPoints.end();
  621.  
  622.         float lowDistanceLeft = -FLT_MAX;
  623.         float lowDistanceRight = FLT_MAX;
  624.  
  625.         for (; it != itEnd; ++it)
  626.         {
  627.                 float u = 0.0f;
  628.                 if (ProjectedPointOnLine(u, m_pathOrig, m_pathDir, m_pathNorm, *it, target))
  629.                 {
  630.                         if (u < distanceAlongPath)
  631.                                 lowDistanceLeft = u;
  632.                         else if (u > distanceAlongPath)
  633.                         {
  634.                                 lowDistanceRight = u;
  635.                                 break;
  636.                         }
  637.                 }
  638.         }
  639.  
  640.         bool lowRightEdge = (it == itEnd);
  641.  
  642.         if ((fabs_tpl(lowDistanceLeft - distanceAlongPath) <= 0.75f) &&
  643.             (lowRightEdge || (fabs_tpl(lowDistanceRight - distanceAlongPath) <= 0.75f)))
  644.                 hasLowCover = true;
  645.  
  646.         // high cover
  647.         it = m_highCoverPoints.begin();
  648.         itEnd = m_highCoverPoints.end();
  649.  
  650.         float highDistanceLeft = -FLT_MAX;
  651.         float highDistanceRight = FLT_MAX;
  652.  
  653.         for (; it != itEnd; ++it)
  654.         {
  655.                 float u = 0.0f;
  656.                 if (ProjectedPointOnLine(u, m_pathOrig, m_pathDir, m_pathNorm, *it, target))
  657.                 {
  658.                         if (u < distanceAlongPath)
  659.                                 highDistanceLeft = u;
  660.                         else if (u > distanceAlongPath)
  661.                         {
  662.                                 highDistanceRight = u;
  663.                                 break;
  664.                         }
  665.                 }
  666.         }
  667.  
  668.         bool highRightEdge = (it == itEnd);
  669.  
  670.         if ((fabs_tpl(highDistanceLeft - distanceAlongPath) < 0.75f) &&
  671.             (lowRightEdge || (fabs_tpl(highDistanceRight - distanceAlongPath) < 0.75f)))
  672.                 hasHighCover = true;
  673. }
  674.  
  675. //
  676. //-------------------------------------------------------------------------------------------------------------
  677. void CAIHideObject::SetupPathExpand(CPipeUser* pOperand)
  678. {
  679.         Vec3 hidePos(GetObjectPos());
  680.         Vec3 hideDir(GetObjectDir());
  681.         float hideRadius(GetObjectRadius());
  682.         float agentRadius = pOperand ? pOperand->GetParameters().m_fPassRadius : DEFAULT_AGENT_RADIUS;
  683.  
  684.         // Move the path origin on ground.
  685.         Vec3 floorPos = GetLastHidePos();
  686.         GetAISystem()->AdjustDirectionalCoverPosition(floorPos, hideDir, agentRadius, 0.7f);
  687.         floorPos.z -= 0.7f;
  688.  
  689.         m_pathOrig = floorPos;
  690.         m_distToCover = AGENT_COVER_CLEARANCE + agentRadius;
  691.  
  692.         m_pathNorm = m_vLastHideDir;
  693.         m_coverPos = hidePos;
  694.  
  695.         m_pathNorm.z = 0;
  696.         m_pathNorm.NormalizeSafe();
  697.         m_pathDir.Set(m_pathNorm.y, -m_pathNorm.x, 0);
  698.  
  699.         Vec3 hitPos;
  700.         float hitDist;
  701.  
  702.         Vec3 lowCoverOrig(m_pathOrig.x, m_pathOrig.y, m_pathOrig.z + LOW_COVER_OFFSET);
  703.         Vec3 highCoverOrig(m_pathOrig.x, m_pathOrig.y, m_pathOrig.z + HIGH_COVER_OFFSET);
  704.  
  705.         m_lowCoverValid = IntersectSweptSphere(&hitPos, hitDist, Lineseg(lowCoverOrig, lowCoverOrig + m_pathNorm * (m_distToCover + 0.5f)), SAMPLE_RADIUS, AICE_ALL);
  706.         m_highCoverValid = IntersectSweptSphere(&hitPos, hitDist, Lineseg(highCoverOrig, highCoverOrig + m_pathNorm * (m_distToCover + 0.5f)), SAMPLE_RADIUS, AICE_ALL);
  707.  
  708.         m_lowLeftEdgeValid = false;
  709.         m_lowRightEdgeValid = false;
  710.         m_highLeftEdgeValid = false;
  711.         m_highRightEdgeValid = false;
  712.  
  713.         m_lowCoverPoints.clear();
  714.         m_highCoverPoints.clear();
  715.  
  716.         m_lowLeftEdge = 0.0;
  717.         m_lowRightEdge = 0.0;
  718.  
  719.         m_highLeftEdge = 0.0;
  720.         m_highRightEdge = 0.0;
  721.  
  722.         m_pathLimitLeft = 0;
  723.         m_pathLimitRight = 0;
  724.  
  725.         m_pathUpdateIter = 0;
  726.         m_pathComplete = false;
  727. }
  728.  
  729. //
  730. //-------------------------------------------------------------------------------------------------------------
  731. bool CAIHideObject::IsSegmentValid(CPipeUser* pOperand, const Vec3& posFrom, const Vec3& posTo)
  732. {
  733.         CAISystem* pAISystem = GetAISystem();
  734.  
  735.         int nBuildingID;
  736.  
  737.         float agentRadius = pOperand ? pOperand->GetParameters().m_fPassRadius : DEFAULT_AGENT_RADIUS;
  738.  
  739.         IAISystem::tNavCapMask navCapMask = pOperand ? pOperand->GetMovementAbility().pathfindingProperties.navCapMask : DEFAULT_AGENT_NAVMASK;
  740.         IAISystem::ENavigationType navType = gAIEnv.pNavigation->CheckNavigationType(posFrom, nBuildingID, navCapMask);
  741.  
  742.         if (navType == IAISystem::NAV_VOLUME || navType == IAISystem::NAV_FLIGHT ||
  743.             navType == IAISystem::NAV_WAYPOINT_3DSURFACE || navType == IAISystem::NAV_TRIANGULAR)
  744.         {
  745.                 CNavRegion* pRegion = gAIEnv.pNavigation->GetNavRegion(navType, gAIEnv.pGraph);
  746.                 if (pRegion)
  747.                 {
  748.                         NavigationBlockers navBlocker;
  749.                         if (pRegion->CheckPassability(posFrom, posTo, agentRadius, navBlocker, navCapMask))
  750.                         {
  751.                                 if (navType == IAISystem::NAV_TRIANGULAR)
  752.                                 {
  753.                                         // Make sure not to enter forbidden area.
  754.                                         if (gAIEnv.pNavigation->IsPointInForbiddenRegion(posTo))
  755.                                                 return false;
  756.                                 }
  757.                                 return true;
  758.                         }
  759.                 }
  760.         }
  761.         else if (navType == IAISystem::NAV_WAYPOINT_HUMAN)
  762.         {
  763.                 const SpecialArea* sa = gAIEnv.pNavigation->GetSpecialArea(nBuildingID);
  764.                 if (sa)
  765.                         return CheckWalkability(posFrom, posTo, agentRadius + 0.1f, sa->GetPolygon(), 0, 0, &sa->GetAABB());
  766.                 else
  767.                 {
  768.                         AIWarning("COPUseCover::IsSegmentValid: Cannot find special area for building ID %d", nBuildingID);
  769.                         return false;
  770.                 }
  771.         }
  772.  
  773.         return false;
  774. }
  775.  
  776. //
  777. //-------------------------------------------------------------------------------------------------------------
  778. void CAIHideObject::SampleCover(CPipeUser* pOperand, float& maxCover, float& maxDepth,
  779.                                 const Vec3& startPos, float maxWidth,
  780.                                 float sampleDist, float sampleRad, float sampleDepth,
  781.                                 std::deque<Vec3>& points, bool pushBack, bool& reachedEdge)
  782. {
  783.         //      const int REFINE_SAMPLES = 4;
  784.  
  785.         Vec3 hitPos;
  786.         Vec3 checkDir = m_pathNorm * sampleDepth;
  787.         maxCover = 0;
  788.         maxDepth = 0;
  789.  
  790.         reachedEdge = false;
  791.  
  792.         // Linear rough samples
  793.  
  794.         int n = 1 + (int)floorf(fabs(maxWidth) / sampleDist);
  795.         float deltaWidth = 1.0f / (float)n * maxWidth;
  796.  
  797.         for (int i = 0; i < n; i++)
  798.         {
  799.                 float w = deltaWidth * (i + 1);
  800.                 Vec3 pos = startPos + m_pathDir * w;
  801.                 float d = 0;
  802.  
  803.                 if (!IntersectSweptSphere(&hitPos, d, Lineseg(pos, pos + checkDir), sampleRad, AICE_ALL))
  804.                 {
  805.                         reachedEdge = true;
  806.                         break;
  807.                 }
  808.                 else
  809.                 {
  810.                         maxCover = w;
  811.                         if (pushBack)
  812.                                 points.push_back(pos + m_pathNorm * d);
  813.                         else
  814.                                 points.push_front(pos + m_pathNorm * d);
  815.                 }
  816.                 maxDepth = max(maxDepth, d);
  817.         }
  818. }
  819.  
  820. //
  821. //-------------------------------------------------------------------------------------------------------------
  822. void CAIHideObject::SampleCoverRefine(CPipeUser* pOperand, float& maxCover, float& maxDepth,
  823.                                       const Vec3& startPos, float maxWidth,
  824.                                       float sampleDist, float sampleRad, float sampleDepth,
  825.                                       std::deque<Vec3>& points, bool pushBack)
  826. {
  827.         Vec3 hitPos;
  828.         int n = 1 + (int)floorf(fabs(maxWidth) / sampleDist);
  829.         float deltaWidth = 1.0f / (float)n * maxWidth;
  830.         Vec3 checkDir = m_pathNorm * sampleDepth;
  831.  
  832.         // Refine few iterations
  833.         float t = 0.0f;
  834.         float dt = 0.5f;
  835.         for (int j = 0; j < REFINE_SAMPLES; j++)
  836.         {
  837.                 Vec3 pos = startPos + m_pathDir * (maxCover + deltaWidth * t);
  838.  
  839.                 float dist = 0;
  840.                 if (!IntersectSweptSphere(&hitPos, dist, Lineseg(pos, pos + checkDir), sampleRad, AICE_ALL))
  841.                         t -= dt;
  842.                 else
  843.                         t += dt;
  844.                 maxDepth = max(maxDepth, dist);
  845.                 dt *= 0.5f;
  846.         }
  847.  
  848.         maxCover += deltaWidth * t;
  849.  
  850.         if (maxDepth < 0.01f)
  851.                 maxDepth = sampleDepth;
  852.  
  853.         if (pushBack)
  854.                 points.push_back(startPos + m_pathDir * maxCover + m_pathNorm * maxDepth);
  855.         else
  856.                 points.push_front(startPos + m_pathDir * maxCover + m_pathNorm * maxDepth);
  857. }
  858.  
  859. //
  860. //-------------------------------------------------------------------------------------------------------------
  861. void CAIHideObject::SampleLine(CPipeUser* pOperand, float& maxMove, float maxWidth, float sampleDist)
  862. {
  863.         // Linear rough samples
  864.         Vec3 lastPos(m_pathOrig);
  865.         int n = 1 + (int)floorf(fabs(maxWidth) / sampleDist);
  866.         float deltaWidth = 1.0f / (float)n * maxWidth;
  867.  
  868.         for (int i = 0; i < n; i++)
  869.         {
  870.                 const float w = deltaWidth * (i + 1);
  871.                 Vec3 pos = m_pathOrig + m_pathDir * w;
  872.                 if (!IsSegmentValid(pOperand, lastPos, pos))
  873.                         break;
  874.                 else
  875.                         maxMove = w;
  876.                 lastPos = pos;
  877.         }
  878. }
  879.  
  880. void CAIHideObject::SampleLineRefine(CPipeUser* pOperand, float& maxMove, float maxWidth, float sampleDist)
  881. {
  882.         // Refine few iterations
  883.         Vec3 lastPos(m_pathOrig + m_pathDir * maxMove);
  884.         int n = 1 + (int)floorf(fabs(maxWidth) / sampleDist);
  885.         float deltaWidth = 1.0f / (float)n * maxWidth;
  886.  
  887.         float t = 0.0f;
  888.         float dt = 0.5f;
  889.         for (int j = 0; j < REFINE_SAMPLES; j++)
  890.         {
  891.                 Vec3 pos = m_pathOrig + m_pathDir * (maxMove + deltaWidth * t);
  892.                 if (!IsSegmentValid(pOperand, lastPos, pos))
  893.                         t -= dt;
  894.                 else
  895.                         t += dt;
  896.                 dt *= 0.5f;
  897.         }
  898.  
  899.         maxMove += deltaWidth * t;
  900. }
  901.  
  902. //
  903. //-------------------------------------------------------------------------------------------------------------
  904. void CAIHideObject::UpdatePathExpand(CPipeUser* pOperand)
  905. {
  906.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  907.  
  908.         if (m_pathUpdateIter == 0)
  909.                 SetupPathExpand(pOperand);
  910.  
  911.         if (m_pathComplete)
  912.                 return;
  913.  
  914.         const float LINE_LEN = GetMaxCoverPathLen();
  915.  
  916.         Vec3 lowCoverOrig(m_pathOrig.x, m_pathOrig.y, m_pathOrig.z + LOW_COVER_OFFSET);
  917.         Vec3 highCoverOrig(m_pathOrig.x, m_pathOrig.y, m_pathOrig.z + HIGH_COVER_OFFSET);
  918.         Vec3 hitPos;
  919.  
  920.         int maxIter = 1;
  921.         int iter = 0;
  922.  
  923.         if (m_pathHurryUp)
  924.                 maxIter = 2;
  925.  
  926.         while (!m_pathComplete && iter < maxIter)
  927.         {
  928.                 switch (m_pathUpdateIter)
  929.                 {
  930.                 case 0:
  931.                         SampleLine(pOperand, m_pathLimitLeft, -LINE_LEN / 2, STEP_SIZE);
  932.                         iter++;
  933.                         break;
  934.                 case 1:
  935.                         SampleLineRefine(pOperand, m_pathLimitLeft, -LINE_LEN / 2, STEP_SIZE);
  936.                         iter++;
  937.                         break;
  938.                 case 2:
  939.                         SampleLine(pOperand, m_pathLimitRight, LINE_LEN / 2, STEP_SIZE);
  940.                         iter++;
  941.                         break;
  942.                 case 3:
  943.                         SampleLineRefine(pOperand, m_pathLimitRight, LINE_LEN / 2, STEP_SIZE);
  944.                         iter++;
  945.                         break;
  946.                 case 4:
  947.                         if (m_lowCoverValid)
  948.                         {
  949.                                 SampleCover(pOperand, m_tempCover, m_tempDepth, lowCoverOrig, m_pathLimitLeft, SAMPLE_DIST, SAMPLE_RADIUS, m_distToCover + 1.0f, m_lowCoverPoints, false, m_lowLeftEdgeValid);
  950.                                 iter++;
  951.                         }
  952.                         break;
  953.                 case 5:
  954.                         if (m_lowCoverValid)
  955.                         {
  956.                                 SampleCoverRefine(pOperand, m_tempCover, m_tempDepth, lowCoverOrig, m_pathLimitLeft, SAMPLE_DIST, SAMPLE_RADIUS, m_distToCover + 1.0f, m_lowCoverPoints, false);
  957.                                 iter++;
  958.                         }
  959.                         break;
  960.                 case 6:
  961.                         if (m_lowCoverValid)
  962.                         {
  963.                                 SampleCover(pOperand, m_tempCover, m_tempDepth, lowCoverOrig, m_pathLimitRight, SAMPLE_DIST, SAMPLE_RADIUS, m_distToCover + 1.0f, m_lowCoverPoints, true, m_lowRightEdgeValid);
  964.                                 iter++;
  965.                         }
  966.                         break;
  967.                 case 7:
  968.                         if (m_lowCoverValid)
  969.                         {
  970.                                 SampleCoverRefine(pOperand, m_tempCover, m_tempDepth, lowCoverOrig, m_pathLimitRight, SAMPLE_DIST, SAMPLE_RADIUS, m_distToCover + 1.0f, m_lowCoverPoints, true);
  971.                                 iter++;
  972.                         }
  973.                         break;
  974.                 case 8:
  975.                         if (m_highCoverValid)
  976.                         {
  977.                                 SampleCover(pOperand, m_tempCover, m_tempDepth, highCoverOrig, m_pathLimitLeft, SAMPLE_DIST, SAMPLE_RADIUS, m_distToCover + 1.0f, m_highCoverPoints, false, m_highLeftEdgeValid);
  978.                                 iter++;
  979.                         }
  980.                         break;
  981.                 case 9:
  982.                         if (m_highCoverValid)
  983.                         {
  984.                                 SampleCoverRefine(pOperand, m_tempCover, m_tempDepth, highCoverOrig, m_pathLimitLeft, SAMPLE_DIST, SAMPLE_RADIUS, m_distToCover + 1.0f, m_highCoverPoints, false);
  985.                                 iter++;
  986.                         }
  987.                         break;
  988.                 case 10:
  989.                         if (m_highCoverValid)
  990.                         {
  991.                                 SampleCover(pOperand, m_tempCover, m_tempDepth, highCoverOrig, m_pathLimitRight, SAMPLE_DIST, SAMPLE_RADIUS, m_distToCover + 1.0f, m_highCoverPoints, true, m_highRightEdgeValid);
  992.                                 iter++;
  993.                         }
  994.                         break;
  995.                 case 11:
  996.                         if (m_highCoverValid)
  997.                         {
  998.                                 SampleCoverRefine(pOperand, m_tempCover, m_tempDepth, highCoverOrig, m_pathLimitRight, SAMPLE_DIST, SAMPLE_RADIUS, m_distToCover + 1.0f, m_highCoverPoints, true);
  999.                                 iter++;
  1000.                         }
  1001.                         break;
  1002.                 default:
  1003.                         m_pathComplete = true;
  1004.                         break;
  1005.                 }
  1006.                 m_pathUpdateIter++;
  1007.         }
  1008.  
  1009.         // Update cover width.
  1010.         m_lowCoverWidth = 0.0f;
  1011.         m_highCoverWidth = 0.0f;
  1012.  
  1013.         float cmin, cmax;
  1014.         std::deque<Vec3>::iterator end;
  1015.  
  1016.         cmin = 0.0f;
  1017.         cmax = 0.0f;
  1018.         end = m_lowCoverPoints.end();
  1019.         for (std::deque<Vec3>::iterator it = m_lowCoverPoints.begin(); it != end; ++it)
  1020.         {
  1021.                 float u = m_pathDir.Dot((*it) - m_pathOrig);
  1022.                 cmin = min(cmin, u);
  1023.                 cmax = max(cmax, u);
  1024.         }
  1025.  
  1026.         m_lowLeftEdge = cmin;
  1027.         m_lowRightEdge = cmax;
  1028.  
  1029.         // Adjust the cover to match the non-collidable cover width if applicable.
  1030.         if (m_pathComplete && !m_objectCollidable && m_objectRadius > 0.1f)
  1031.         {
  1032.                 if (cmin > -m_objectRadius)
  1033.                 {
  1034.                         m_lowCoverPoints.push_front(lowCoverOrig + m_pathNorm * m_distToCover + m_pathDir * -m_objectRadius);
  1035.                         m_lowLeftEdgeValid = true;
  1036.                         cmin = -m_objectRadius;
  1037.                 }
  1038.                 m_lowLeftEdge = min(-m_objectRadius, cmin);
  1039.  
  1040.                 if (cmax < m_objectRadius)
  1041.                 {
  1042.                         m_lowCoverPoints.push_back(lowCoverOrig + m_pathNorm * m_distToCover + m_pathDir * m_objectRadius);
  1043.                         m_lowRightEdgeValid = true;
  1044.                         cmax = m_objectRadius;
  1045.                 }
  1046.                 m_lowRightEdge = max(m_objectRadius, cmax);
  1047.         }
  1048.  
  1049.         m_lowCoverWidth = cmax - cmin;
  1050.  
  1051.         cmin = 0.0f;
  1052.         cmax = 0.0f;
  1053.         end = m_highCoverPoints.end();
  1054.         for (std::deque<Vec3>::iterator it = m_highCoverPoints.begin(); it != end; ++it)
  1055.         {
  1056.                 float u = m_pathDir.Dot((*it) - m_pathOrig);
  1057.                 cmin = min(cmin, u);
  1058.                 cmax = max(cmax, u);
  1059.         }
  1060.  
  1061.         m_highLeftEdge = cmin;
  1062.         m_highRightEdge = cmax;
  1063.  
  1064.         // Adjust the cover to match the non-collidable cover width if applicable.
  1065.         if (m_pathComplete && !m_objectCollidable && m_objectRadius > 0.1f && m_objectHeight > 0.8f)
  1066.         {
  1067.                 CCCPOINT(CAIHideObject_UpdatePathExpand_HighCover);
  1068.                 if (cmin > -m_objectRadius)
  1069.                 {
  1070.                         m_highCoverPoints.push_front(highCoverOrig + m_pathNorm * m_distToCover + m_pathDir * -m_objectRadius);
  1071.                         m_highLeftEdgeValid = true;
  1072.                         cmin = -m_objectRadius;
  1073.                 }
  1074.                 m_highLeftEdge = min(-m_objectRadius, cmin);
  1075.  
  1076.                 if (cmax < m_objectRadius)
  1077.                 {
  1078.                         m_highCoverPoints.push_back(highCoverOrig + m_pathNorm * m_distToCover + m_pathDir * m_objectRadius);
  1079.                         m_highRightEdgeValid = true;
  1080.                         cmax = m_objectRadius;
  1081.                 }
  1082.                 m_highRightEdge = max(m_objectRadius, cmax);
  1083.         }
  1084.  
  1085.         m_highCoverWidth = cmax - cmin;
  1086.  
  1087.         /*      if(m_lowCoverWidth < 0.01f && m_objectRadius > 0.01f)
  1088.             m_lowCoverWidth = m_objectRadius * 2.0f;
  1089.            if(m_highCoverWidth < 0.01f && m_objectRadius > 0.01f)
  1090.             m_highCoverWidth = m_objectRadius * 2.0f;*/
  1091.  
  1092.         /*
  1093.            SampleLine(pOperand, m_pathLimitLeft, -LINE_LEN/2, STEP_SIZE);
  1094.            SampleLineRefine(pOperand, m_pathLimitLeft, -LINE_LEN/2, STEP_SIZE);
  1095.            SampleLine(pOperand, m_pathLimitRight, LINE_LEN/2, STEP_SIZE);
  1096.            SampleLineRefine(pOperand, m_pathLimitRight, LINE_LEN/2, STEP_SIZE);
  1097.  
  1098.            if(m_lowCoverValid)
  1099.            {
  1100.             SampleCover(pOperand, m_tempCover, m_tempDepth, lowCoverOrig, m_pathLimitLeft, SAMPLE_DIST, SAMPLE_RADIUS, m_distToCover + 1.0f, m_lowCoverPoints, false);
  1101.             SampleCoverRefine(pOperand, m_tempCover, m_tempDepth, lowCoverOrig, m_pathLimitLeft, SAMPLE_DIST, SAMPLE_RADIUS, m_distToCover + 1.0f, m_lowCoverPoints, false);
  1102.  
  1103.             SampleCover(pOperand, m_tempCover, m_tempDepth, lowCoverOrig, m_pathLimitRight, SAMPLE_DIST, SAMPLE_RADIUS, m_distToCover + 1.0f, m_lowCoverPoints, true);
  1104.             SampleCoverRefine(pOperand, m_tempCover, m_tempDepth, lowCoverOrig, m_pathLimitRight, SAMPLE_DIST, SAMPLE_RADIUS, m_distToCover + 1.0f, m_lowCoverPoints, true);
  1105.            }
  1106.  
  1107.            if(m_highCoverValid)
  1108.            {
  1109.             SampleCover(pOperand, m_tempCover, m_tempDepth, highCoverOrig, m_pathLimitLeft, SAMPLE_DIST, SAMPLE_RADIUS, m_distToCover + 1.0f, m_highCoverPoints, false);
  1110.             SampleCoverRefine(pOperand, m_tempCover, m_tempDepth, highCoverOrig, m_pathLimitLeft, SAMPLE_DIST, SAMPLE_RADIUS, m_distToCover + 1.0f, m_highCoverPoints, false);
  1111.  
  1112.             SampleCover(pOperand, m_tempCover, m_tempDepth, highCoverOrig, m_pathLimitRight, SAMPLE_DIST, SAMPLE_RADIUS, m_distToCover + 1.0f, m_highCoverPoints, true);
  1113.             SampleCoverRefine(pOperand, m_tempCover, m_tempDepth, highCoverOrig, m_pathLimitRight, SAMPLE_DIST, SAMPLE_RADIUS, m_distToCover + 1.0f, m_highCoverPoints, true);
  1114.            }*/
  1115.  
  1116. }
  1117.  
  1118. //
  1119. //-------------------------------------------------------------------------------------------------------------
  1120. void CAIHideObject::DebugDraw()
  1121. {
  1122.         if (m_bIsSmartObject)
  1123.                 return;
  1124.  
  1125.         ColorB white(255, 255, 255);
  1126.         ColorB red(255, 0, 0);
  1127.         ColorB redTrans(255, 0, 0, 128);
  1128.         ColorB green(0, 192, 0);
  1129.         ColorB greenTrans(0, 192, 0, 128);
  1130.         ColorB blue(0, 0, 255);
  1131.  
  1132.         CDebugDrawContext dc;
  1133.  
  1134.         dc->DrawLine(GetLastHidePos() + Vec3(0, 0, 0.5f), white, GetObjectPos() + Vec3(0, 0, 0.5f), white);
  1135.         dc->DrawLine(GetObjectPos() + Vec3(0, 0, -0.5f), white, GetObjectPos() + Vec3(0, 0, 2.5f), white);
  1136.  
  1137.         if (m_pathUpdateIter == 0)
  1138.                 return;
  1139.  
  1140.         // Draw walkability
  1141.         dc->DrawLine(m_pathOrig + m_pathDir * m_pathLimitLeft, white,
  1142.                      m_pathOrig + m_pathDir * m_pathLimitRight, white);
  1143.  
  1144.         size_t maxPts = max(m_lowCoverPoints.size(), m_highCoverPoints.size());
  1145.         std::vector<Vec3> tris;
  1146.         tris.resize((maxPts + 1) * 12);
  1147.  
  1148.         // Draw low cover
  1149.         if (m_lowCoverPoints.size() > 1)
  1150.         {
  1151.                 std::deque<Vec3>::iterator cur = m_lowCoverPoints.begin(), next = m_lowCoverPoints.begin();
  1152.                 ++next;
  1153.                 size_t i = 0;
  1154.                 while (next != m_lowCoverPoints.end())
  1155.                 {
  1156.                         const Vec3& left = (*cur);
  1157.                         const Vec3& right = (*next);
  1158.                         // Back
  1159.                         tris[i + 0] = left + Vec3(0, 0, -0.5f);
  1160.                         tris[i + 1] = right + Vec3(0, 0, 0.5f);
  1161.                         tris[i + 2] = right + Vec3(0, 0, -0.5f);
  1162.                         tris[i + 3] = left + Vec3(0, 0, -0.5f);
  1163.                         tris[i + 4] = left + Vec3(0, 0, 0.5f);
  1164.                         tris[i + 5] = right + Vec3(0, 0, 0.5f);
  1165.                         i += 6;
  1166.                         // Front
  1167.                         tris[i + 0] = left + Vec3(0, 0, -0.5f);
  1168.                         tris[i + 2] = right + Vec3(0, 0, 0.5f);
  1169.                         tris[i + 1] = right + Vec3(0, 0, -0.5f);
  1170.                         tris[i + 3] = left + Vec3(0, 0, -0.5f);
  1171.                         tris[i + 5] = left + Vec3(0, 0, 0.5f);
  1172.                         tris[i + 4] = right + Vec3(0, 0, 0.5f);
  1173.                         i += 6;
  1174.                         cur = next;
  1175.                         ++next;
  1176.                 }
  1177.                 AIAssert(i > 0);
  1178.                 AIAssert(i <= tris.size());
  1179.                 dc->DrawTriangles(&tris[0], i, greenTrans);
  1180.  
  1181.                 // Draw edge markers
  1182.                 if (m_lowLeftEdgeValid)
  1183.                 {
  1184.                         dc->DrawCone(m_lowCoverPoints.front() + Vec3(0, 0, 0.5f), Vec3(0, 0, -1), 0.07f, 1.2f, green);
  1185.                 }
  1186.  
  1187.                 if (m_lowRightEdgeValid)
  1188.                 {
  1189.                         dc->DrawCone(m_lowCoverPoints.front() + Vec3(0, 0, 0.5f), Vec3(0, 0, -1), 0.07f, 1.2f, green);
  1190.                 }
  1191.         }
  1192.  
  1193.         // Draw high cover
  1194.         if (m_highCoverPoints.size() > 1)
  1195.         {
  1196.                 std::deque<Vec3>::iterator cur = m_highCoverPoints.begin(), next = m_highCoverPoints.begin();
  1197.                 ++next;
  1198.                 size_t i = 0;
  1199.                 while (next != m_highCoverPoints.end())
  1200.                 {
  1201.                         const Vec3& left = (*cur);
  1202.                         const Vec3& right = (*next);
  1203.                         // Back
  1204.                         tris[i + 0] = left + Vec3(0, 0, -0.5f);
  1205.                         tris[i + 1] = right + Vec3(0, 0, 0.25f);
  1206.                         tris[i + 2] = right + Vec3(0, 0, -0.5f);
  1207.                         tris[i + 3] = left + Vec3(0, 0, -0.5f);
  1208.                         tris[i + 4] = left + Vec3(0, 0, 0.25f);
  1209.                         tris[i + 5] = right + Vec3(0, 0, 0.25f);
  1210.                         i += 6;
  1211.                         // Front
  1212.                         tris[i + 0] = left + Vec3(0, 0, -0.5f);
  1213.                         tris[i + 2] = right + Vec3(0, 0, 0.25f);
  1214.                         tris[i + 1] = right + Vec3(0, 0, -0.5f);
  1215.                         tris[i + 3] = left + Vec3(0, 0, -0.5f);
  1216.                         tris[i + 5] = left + Vec3(0, 0, 0.25f);
  1217.                         tris[i + 4] = right + Vec3(0, 0, 0.25f);
  1218.                         i += 6;
  1219.                         cur = next;
  1220.                         ++next;
  1221.                 }
  1222.                 AIAssert(i > 0);
  1223.                 AIAssert(i <= tris.size());
  1224.                 dc->DrawTriangles(&tris[0], i, greenTrans);
  1225.  
  1226.                 // Draw edge markers
  1227.                 if (m_highLeftEdgeValid)
  1228.                 {
  1229.                         dc->DrawCone(m_highCoverPoints.front() + Vec3(0, 0, 0.25f), Vec3(0, 0, -1), 0.07f, 0.75f, green);
  1230.                 }
  1231.  
  1232.                 if (m_highRightEdgeValid)
  1233.                 {
  1234.                         dc->DrawCone(m_highCoverPoints.back() + Vec3(0, 0, 0.25f), Vec3(0, 0, -1), 0.07f, 0.75f, green);
  1235.                 }
  1236.         }
  1237.  
  1238.         if (m_pathComplete && (m_lowCoverPoints.size() < 2) && (m_highCoverPoints.size() < 2))
  1239.         {
  1240.                 dc->DrawCylinder(m_objectPos + Vec3Constants<float>::fVec3_OneZ * HIGH_COVER_OFFSET * 0.25f,
  1241.                                  Vec3Constants<float>::fVec3_OneZ, DEFAULT_AGENT_RADIUS + AGENT_COVER_CLEARANCE, HIGH_COVER_OFFSET, redTrans, true);
  1242.         }
  1243. }
  1244.  
  1245. //
  1246. //----------------------------------------------------------------------------------------------------
  1247. bool CAIHideObject::HasLowCover() const
  1248. {
  1249.         return !m_lowCoverPoints.empty() && m_lowCoverPoints.size() > 1;
  1250. }
  1251.  
  1252. bool CAIHideObject::HasHighCover() const
  1253. {
  1254.         return !m_highCoverPoints.empty() && m_highCoverPoints.size() > 1;
  1255. }
  1256.  
  1257. bool CAIHideObject::IsLeftEdgeValid(bool useLowCover) const
  1258. {
  1259.         return useLowCover ? m_lowLeftEdgeValid : m_highLeftEdgeValid;
  1260. }
  1261.  
  1262. bool CAIHideObject::IsRightEdgeValid(bool useLowCover) const
  1263. {
  1264.         return useLowCover ? m_lowRightEdgeValid : m_highRightEdgeValid;
  1265. }
  1266.  
  1267. const char* CAIHideObject::GetAnchorName() const
  1268. {
  1269.         return m_sAnchorName.c_str();
  1270. }
  1271.  
  1272. //
  1273. //----------------------------------------------------------------------------------------------------
  1274. void CAIHideObject::Serialize(TSerialize ser)
  1275. {
  1276.         ser.BeginGroup("AIHideObject");
  1277.         {
  1278.                 ser.Value("m_bIsValid", m_bIsValid);
  1279.                 if (m_bIsValid)
  1280.                 {
  1281.                         ser.Value("m_isUsingCover", m_isUsingCover);
  1282.                         ser.Value("m_objectPos", m_objectPos);
  1283.                         ser.Value("m_objectDir", m_objectDir);
  1284.                         ser.Value("m_objectRadius", m_objectRadius);
  1285.                         ser.Value("m_objectCollidable", m_objectCollidable);
  1286.                         ser.Value("m_vLastHidePos", m_vLastHidePos);
  1287.                         ser.Value("m_vLastHideDir", m_vLastHideDir);
  1288.                         ser.Value("m_bIsSmartObject", m_bIsSmartObject);
  1289.                         m_HideSmartObject.Serialize(ser);
  1290.                         ser.Value("m_useCover", m_useCover);
  1291.                         ser.Value("m_coverPos", m_coverPos);
  1292.                         ser.Value("m_distToCover", m_distToCover);
  1293.                         ser.Value("m_pathOrig", m_pathOrig);
  1294.                         ser.Value("m_pathDir", m_pathDir);
  1295.                         ser.Value("m_pathNorm", m_pathNorm);
  1296.                         ser.Value("m_pathLimitLeft", m_pathLimitLeft);
  1297.                         ser.Value("m_pathLimitRight", m_pathLimitRight);
  1298.                         ser.Value("m_tempCover", m_tempCover);
  1299.                         ser.Value("m_tempDepth", m_tempDepth);
  1300.                         ser.Value("m_pathComplete", m_pathComplete);
  1301.                         ser.Value("m_highCoverValid", m_highCoverValid);
  1302.                         ser.Value("m_lowCoverValid", m_lowCoverValid);
  1303.                         ser.Value("m_pathHurryUp", m_pathHurryUp);
  1304.                         ser.Value("m_lowLeftEdgeValid", m_lowLeftEdgeValid);
  1305.                         ser.Value("m_lowRightEdgeValid", m_lowRightEdgeValid);
  1306.                         ser.Value("m_highLeftEdgeValid", m_highLeftEdgeValid);
  1307.                         ser.Value("m_highRightEdgeValid", m_highRightEdgeValid);
  1308.                         ser.Value("m_lowCoverPoints", m_lowCoverPoints);
  1309.                         ser.Value("m_highCoverPoints", m_highCoverPoints);
  1310.                         ser.Value("m_lowCoverWidth", m_lowCoverWidth);
  1311.                         ser.Value("m_highCoverWidth", m_highCoverWidth);
  1312.                         ser.Value("m_pathUpdateIter", m_pathUpdateIter);
  1313.                         ser.Value("m_id", m_id);
  1314.                         ser.Value("m_dynCoverEntityId", m_dynCoverEntityId);
  1315.                         ser.Value("m_dynCoverEntityPos", m_dynCoverEntityPos);
  1316.                         ser.Value("m_dynCoverPosLocal", m_dynCoverPosLocal);
  1317.                 }
  1318.                 ser.EndGroup();
  1319.         }
  1320. }
  1321.  
downloadAIHideObject.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