BVB Source Codes

CRYENGINE Show Navigation.cpp Source code

Return Download CRYENGINE: download Navigation.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. /********************************************************************
  4.    CryGame Source File.
  5.    -------------------------------------------------------------------------
  6.    File name:   Navigation.cpp
  7.    Version:     v1.00
  8.    Description:
  9.  
  10.    -------------------------------------------------------------------------
  11.    History:
  12.    - ?
  13.    - 4 May 2009  : Evgeny Adamenkov: Replaced IRenderer with CDebugDrawContext
  14.  
  15.  *********************************************************************/
  16.  
  17. #include "StdAfx.h"
  18.  
  19. #include "Navigation.h"
  20. #include "PolygonSetOps/Polygon2d.h"
  21. #include "FlightNavRegion2.h"
  22. #include "Free2DNavRegion.h"
  23.  
  24. #include "Navigation/CustomNavRegion.h"
  25. #include "DebugDrawContext.h"
  26. #include "Graph.h"
  27. #include "CalculationStopper.h"
  28. #include <CrySystem/File/CryBufferedFileReader.h>
  29.  
  30. static const int maxForbiddenNameLen = 1024;
  31.  
  32. // flag used for debugging/profiling the improvement obtained from using a
  33. // QuadTree for the forbidden shapes. Currently it's actually faster not
  34. // using quadtree - need to experiment more
  35. // kirill - enabling quadtree - is faster on low-spec
  36. bool useForbiddenQuadTree = true;//false;
  37.  
  38. CNavigation::CNavigation(ISystem* pSystem) :
  39.         m_nNumBuildings(0),
  40.         m_pTriangulator(0),
  41.         m_dynamicLinkUpdateTimeBump(1.0f),
  42.         m_dynamicLinkUpdateTimeBumpDuration(0),
  43.         m_dynamicLinkUpdateTimeBumpElapsed(0)
  44. {
  45.         CGraph* pGraph = gAIEnv.pGraph;
  46. }
  47.  
  48. CNavigation::~CNavigation()
  49. {
  50. }
  51.  
  52. bool CNavigation::Init()
  53. {
  54.         m_nNumBuildings = 0;
  55.         return true;
  56. }
  57.  
  58. void CNavigation::ShutDown()
  59. {
  60.         FlushAllAreas();
  61.  
  62.         if (m_pTriangulator)
  63.         {
  64.                 delete m_pTriangulator;
  65.                 m_pTriangulator = 0;
  66.         }
  67. }
  68.  
  69. //====================================================================
  70. // OnMissionLoaded
  71. //====================================================================
  72. void CNavigation::OnMissionLoaded()
  73. {
  74. }
  75.  
  76. // // loads the triangulation for this level and mission
  77. //
  78. //-----------------------------------------------------------------------------------------------------------
  79. void CNavigation::LoadNavigationData(const char* szLevel, const char* szMission)
  80. {
  81.         LOADING_TIME_PROFILE_SECTION(GetISystem());
  82.  
  83.         m_nNumBuildings = 0;
  84.  
  85.         CTimeValue startTime = gEnv->pTimer->GetAsyncCurTime();
  86.  
  87.         CAISystem* pAISystem = GetAISystem();
  88.         CGraph* pGraph = gAIEnv.pGraph;
  89.  
  90.         pGraph->Clear(IAISystem::NAV_TRIANGULAR | IAISystem::NAV_WAYPOINT_HUMAN | IAISystem::NAV_WAYPOINT_3DSURFACE);
  91.  
  92.         pGraph->CheckForEmpty(IAISystem::NAV_TRIANGULAR | IAISystem::NAV_WAYPOINT_HUMAN | IAISystem::NAV_WAYPOINT_3DSURFACE | IAISystem::NAV_VOLUME | IAISystem::NAV_FLIGHT | IAISystem::NAV_ROAD | IAISystem::NAV_FREE_2D);
  93.  
  94.         char fileNameAreas[1024];
  95.  
  96.         cry_sprintf(fileNameAreas, "%s/areas%s.bai", szLevel, szMission);
  97.  
  98. #if defined(SEG_WORLD)
  99.         pAISystem->ReadAreasFromFile(fileNameAreas, Vec3(0));
  100. #else
  101.         pAISystem->ReadAreasFromFile(fileNameAreas);
  102. #endif
  103.  
  104.         CTimeValue endTime = gEnv->pTimer->GetAsyncCurTime();
  105.         AILogLoading("Navigation Data Loaded in %5.2f sec", (endTime - startTime).GetSeconds());
  106. }
  107.  
  108. static const size_t DynamicLinkConnectionBumpDelayFrames = 10;
  109.  
  110. float CNavigation::GetDynamicLinkConnectionTimeModifier() const
  111. {
  112.         if ((m_dynamicLinkUpdateTimeBumpElapsed >= DynamicLinkConnectionBumpDelayFrames) &&
  113.             (m_dynamicLinkUpdateTimeBumpElapsed < m_dynamicLinkUpdateTimeBumpDuration + DynamicLinkConnectionBumpDelayFrames))
  114.                 return m_dynamicLinkUpdateTimeBump;
  115.  
  116.         return 1.0f;
  117. }
  118.  
  119. void CNavigation::BumpDynamicLinkConnectionUpdateTime(float modifier, size_t durationFrames)
  120. {
  121.         m_dynamicLinkUpdateTimeBump = modifier;
  122.         m_dynamicLinkUpdateTimeBumpDuration = durationFrames;
  123.         m_dynamicLinkUpdateTimeBumpElapsed = 0;
  124. }
  125.  
  126. void CNavigation::Serialize(TSerialize ser)
  127. {
  128. }
  129.  
  130. void CNavigation::Update(CTimeValue frameStartTime, float frameDeltaTime)
  131. {
  132.         if (m_dynamicLinkUpdateTimeBumpElapsed <= m_dynamicLinkUpdateTimeBumpDuration + DynamicLinkConnectionBumpDelayFrames)
  133.                 ++m_dynamicLinkUpdateTimeBumpElapsed;
  134.  
  135.         UpdateNavRegions();
  136.  
  137.         // Update path devalues.
  138.         for (ShapeMap::iterator it = m_mapDesignerPaths.begin(); it != m_mapDesignerPaths.end(); ++it)
  139.                 it->second.devalueTime = max(0.0f, it->second.devalueTime - frameDeltaTime);
  140. }
  141.  
  142. //
  143. //-----------------------------------------------------------------------------------------------------------
  144. void CNavigation::UpdateNavRegions()
  145. {
  146.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  147.  
  148.         //return;
  149.         CAISystem* pAISystem = GetAISystem();
  150. }
  151.  
  152. //
  153. //-----------------------------------------------------------------------------------------------------------
  154. void CNavigation::FlushSystemNavigation(bool bDeleteAll)
  155. {
  156.         FlushSpecialAreas();
  157.         if (gAIEnv.pGraph)
  158.         {
  159.                 if (bDeleteAll)
  160.                 {
  161.                         // Just reconstruct if unloading the level
  162.                         stl::reconstruct(*gAIEnv.pGraph);
  163.                 }
  164.                 else
  165.                 {
  166.                         gAIEnv.pGraph->Clear(IAISystem::NAVMASK_ALL);
  167.                         gAIEnv.pGraph->ResetIDs();
  168.                 }
  169.         }
  170. }
  171.  
  172. void CNavigation::Reset(IAISystem::EResetReason reason)
  173. {
  174.         if (reason == IAISystem::RESET_ENTER_GAME)
  175.                 m_validationErrorMarkers.clear();
  176.  
  177.         // enable all nav modifiers
  178.         {
  179.                 SpecialAreas::iterator it = m_specialAreas.begin();
  180.                 SpecialAreas::iterator end = m_specialAreas.end();
  181.  
  182.                 for (; it != end; ++it)
  183.                 {
  184.                         SpecialArea& specialArea = *it;
  185.                         specialArea.bAltered = false;
  186.                 }
  187.         }
  188.  
  189.         // Reset path devalue stuff.
  190.         for (ShapeMap::iterator it = m_mapDesignerPaths.begin(); it != m_mapDesignerPaths.end(); ++it)
  191.                 it->second.devalueTime = 0;
  192. }
  193.  
  194. // copies a designer path into provided list if a path of such name is found
  195. //
  196. //-----------------------------------------------------------------------------------------------------------
  197. bool CNavigation::GetDesignerPath(const char* szName, SShape& path) const
  198. {
  199.         ShapeMap::const_iterator di = m_mapDesignerPaths.find(szName);
  200.         if (di != m_mapDesignerPaths.end())
  201.         {
  202.                 path = di->second;
  203.                 return true;
  204.         }
  205.  
  206.         return false;
  207. }
  208.  
  209. //====================================================================
  210. // ReadArea
  211. //====================================================================
  212. void ReadArea(CCryBufferedFileReader& file, int version, string& name, SpecialArea& sa)
  213. {
  214.         unsigned nameLen;
  215.         file.ReadType(&nameLen);
  216.         char tmpName[1024];
  217.         file.ReadType(&tmpName[0], nameLen);
  218.         tmpName[nameLen] = '\0';
  219.         name = tmpName;
  220.  
  221.         int64 type = 0;
  222.         file.ReadType(&type);
  223.         sa.type = (SpecialArea::EType) type;
  224.  
  225.         int64 waypointConnections = 0;
  226.         file.ReadType(&waypointConnections);
  227.         sa.waypointConnections = (EWaypointConnections) waypointConnections;
  228.  
  229.         char altered = 0;
  230.         file.ReadType(&altered);
  231.         sa.bAltered = altered != 0;
  232.         file.ReadType(&sa.fHeight);
  233.         if (version <= 16)
  234.         {
  235.                 float junk;
  236.                 file.ReadType(&junk);
  237.         }
  238.         file.ReadType(&sa.fNodeAutoConnectDistance);
  239.         file.ReadType(&sa.fMaxZ);
  240.         file.ReadType(&sa.fMinZ);
  241.  
  242.         int nBuildingID;
  243.         file.ReadType(&nBuildingID);
  244.         sa.nBuildingID = (int16)nBuildingID;
  245.  
  246.         if (version >= 18)
  247.         {
  248.                 unsigned char lightLevel = 0;
  249.                 file.ReadType(&lightLevel);
  250.                 sa.lightLevel = (EAILightLevel)lightLevel;
  251.         }
  252.  
  253.         if (version >= 23)
  254.         {
  255.                 char critterOnly = 0;
  256.                 file.ReadType(&critterOnly);
  257.                 sa.bCritterOnly = critterOnly != 0;
  258.         }
  259.  
  260.         // now the area itself
  261.         ListPositions pts;
  262.         unsigned ptsSize;
  263.         file.ReadType(&ptsSize);
  264.  
  265.         for (unsigned iPt = 0; iPt < ptsSize; ++iPt)
  266.         {
  267.                 Vec3 pt;
  268.                 file.ReadType(&pt);
  269.                 pts.push_back(pt);
  270.         }
  271.         sa.SetPolygon(pts);
  272. }
  273.  
  274. //====================================================================
  275. // ReadPolygonArea
  276. //====================================================================
  277. #if defined(SEG_WORLD)
  278. bool ReadPolygonArea(CCryBufferedFileReader& file, int version, string& name, ListPositions& pts, const Vec3& vSegmentOffset)
  279. #else
  280. bool ReadPolygonArea(CCryBufferedFileReader& file, int version, string& name, ListPositions& pts)
  281. #endif
  282. {
  283.         unsigned nameLen = maxForbiddenNameLen;
  284.         file.ReadType(&nameLen);
  285.         if (nameLen >= maxForbiddenNameLen)
  286.         {
  287.                 AIWarning("Excessive forbidden area name length - AI loading failed");
  288.                 return false;
  289.         }
  290.         char tmpName[maxForbiddenNameLen];
  291.         file.ReadRaw(&tmpName[0], nameLen);
  292.         tmpName[nameLen] = '\0';
  293.         name = tmpName;
  294.  
  295.         unsigned ptsSize;
  296.         file.ReadType(&ptsSize);
  297.  
  298.         for (unsigned iPt = 0; iPt < ptsSize; ++iPt)
  299.         {
  300.                 Vec3 pt;
  301.                 file.ReadType(&pt);
  302. #if defined(SEG_WORLD)
  303.                 pt += vSegmentOffset;
  304. #endif
  305.                 pts.push_back(pt);
  306.         }
  307.         return true;
  308. }
  309.  
  310. //====================================================================
  311. // ReadForbiddenArea
  312. //====================================================================
  313. bool ReadForbiddenArea(CCryBufferedFileReader& file, int version, CAIShape* shape)
  314. {
  315.         MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Navigation, 0, "Forbidden areas");
  316.  
  317.         unsigned nameLen = maxForbiddenNameLen;
  318.         file.ReadType(&nameLen);
  319.         if (nameLen >= maxForbiddenNameLen)
  320.         {
  321.                 AIWarning("Excessive forbidden area name length - AI loading failed");
  322.                 return false;
  323.         }
  324.         char tmpName[maxForbiddenNameLen];
  325.         file.ReadRaw(&tmpName[0], nameLen);
  326.         tmpName[nameLen] = '\0';
  327.         shape->SetName(tmpName);
  328.  
  329.         unsigned ptsSize;
  330.         file.ReadType(&ptsSize);
  331.  
  332.         ShapePointContainer& pts = shape->GetPoints();
  333.         pts.resize(ptsSize);
  334.  
  335.         for (unsigned i = 0; i < ptsSize; ++i)
  336.                 file.ReadType(&pts[i]);
  337.  
  338.         // Call build AABB since the point container was filled directly.
  339.         shape->BuildAABB();
  340.  
  341.         return true;
  342. }
  343.  
  344. //====================================================================
  345. // ReadExtraLinkCostArea
  346. //====================================================================
  347. void ReadExtraLinkCostArea(CCryBufferedFileReader& file, int version, string& name, SExtraLinkCostShape& shape)
  348. {
  349.         unsigned nameLen;
  350.         file.ReadType(&nameLen);
  351.         char tmpName[1024];
  352.         file.ReadRaw(&tmpName[0], nameLen);
  353.         tmpName[nameLen] = '\0';
  354.         name = tmpName;
  355.  
  356.         file.ReadType(&shape.origCostFactor);
  357.         shape.costFactor = shape.origCostFactor;
  358.         file.ReadType(&shape.aabb.min);
  359.         file.ReadType(&shape.aabb.max);
  360.  
  361.         unsigned ptsSize;
  362.         file.ReadType(&ptsSize);
  363.  
  364.         for (unsigned iPt = 0; iPt < ptsSize; ++iPt)
  365.         {
  366.                 Vec3 pt;
  367.                 file.ReadType(&pt);
  368.                 shape.shape.push_back(pt);
  369.         }
  370. }
  371.  
  372. //====================================================================
  373. // ReadAreasFromFile_Old
  374. //====================================================================
  375. void CNavigation::ReadAreasFromFile_Old(CCryBufferedFileReader& file, int fileVersion)
  376. {
  377.         FlushAllAreas();
  378.  
  379.         unsigned numAreas;
  380.  
  381.         // Read forbidden areas
  382.         {
  383.                 file.ReadType(&numAreas);
  384.                 // vague sanity check
  385.                 AIAssert(numAreas < 1000000);
  386.                 for (unsigned iArea = 0; iArea < numAreas; ++iArea)
  387.                 {
  388.                         CAIShape* pShape = new CAIShape;
  389.                         if (!ReadForbiddenArea(file, fileVersion, pShape))
  390.                                 return;
  391.                 }
  392.         }
  393.  
  394.         // Read navigation modifiers (special areas)
  395.         {
  396.                 file.ReadType(&numAreas);
  397.                 // vague sanity check
  398.                 AIAssert(numAreas < 1000000);
  399.                 m_specialAreas.clear();
  400.                 m_specialAreas.resize(numAreas);
  401.  
  402.                 string name;
  403.                 for (unsigned iArea = 0; iArea < numAreas; ++iArea)
  404.                 {
  405.                         SpecialArea sa;
  406.                         ReadArea(file, fileVersion, name, sa);
  407.                 }
  408.         }
  409.  
  410.         // Read designer forbidden areas
  411.         {
  412.                 file.ReadType(&numAreas);
  413.                 // vague sanity check
  414.                 AIAssert(numAreas < 1000000);
  415.                 for (unsigned iArea = 0; iArea < numAreas; ++iArea)
  416.                 {
  417.                         CAIShape* pShape = new CAIShape;
  418.                         ReadForbiddenArea(file, fileVersion, pShape);
  419.                 }
  420.         }
  421.  
  422.         // Read forbidden boundaries
  423.         {
  424.                 file.ReadType(&numAreas);
  425.                 // vague sanity check
  426.                 AIAssert(numAreas < 1000000);
  427.                 for (unsigned iArea = 0; iArea < numAreas; ++iArea)
  428.                 {
  429.                         CAIShape* pShape = new CAIShape;
  430.                         ReadForbiddenArea(file, fileVersion, pShape);
  431.                 }
  432.         }
  433.  
  434.         // Read extra link costs
  435.         {
  436.                 file.ReadType(&numAreas);
  437.                 // vague sanity check
  438.                 AIAssert(numAreas < 1000000);
  439.                 for (unsigned iArea = 0; iArea < numAreas; ++iArea)
  440.                 {
  441.                         SExtraLinkCostShape shape(ListPositions(), 0.0f);
  442.                         string name;
  443.                         ReadExtraLinkCostArea(file, fileVersion, name, shape);
  444.                 }
  445.         }
  446.  
  447.         // Read designer paths
  448.         {
  449.                 file.ReadType(&numAreas);
  450.                 // vague sanity check
  451.                 AIAssert(numAreas < 1000000);
  452.                 for (unsigned iArea = 0; iArea < numAreas; ++iArea)
  453.                 {
  454.                         ListPositions lp;
  455.                         string name;
  456. #if defined(SEG_WORLD)
  457.                         ReadPolygonArea(file, fileVersion, name, lp, Vec3(0));
  458. #else
  459.                         ReadPolygonArea(file, fileVersion, name, lp);
  460. #endif
  461.  
  462.                         int navType(0), type(0);
  463.                         bool closed(false);
  464.                         file.ReadType(&navType);
  465.                         file.ReadType(&type);
  466.  
  467.                         if (fileVersion >= 22)
  468.                         {
  469.                                 file.ReadType(&closed);
  470.                         }
  471.  
  472.                         if (m_mapDesignerPaths.find(name) != m_mapDesignerPaths.end())
  473.                                 AIError("CNavigation::ReadAreasFromFile_Old: Designer path '%s' already exists, please rename the path and reexport.", name.c_str());
  474.                         else
  475.                                 m_mapDesignerPaths.insert(ShapeMap::iterator::value_type(name, SShape(lp, false, (IAISystem::ENavigationType)navType, type, closed)));
  476.                 }
  477.         }
  478. }
  479.  
  480. //
  481. // Reads (designer paths) areas from file. clears the existing areas
  482. // SEG_WORLD: adds offset to the areas read, and doesn't clear existing areas.
  483. #if defined(SEG_WORLD)
  484. void CNavigation::ReadAreasFromFile(CCryBufferedFileReader& file, int fileVersion, const Vec3& vSegmentOffset)
  485. #else
  486. void CNavigation::ReadAreasFromFile(CCryBufferedFileReader& file, int fileVersion)
  487. #endif
  488. {
  489. #if defined(SEG_WORLD)
  490.         // don't flush all areas here if we're in segmented world
  491.         if (!gEnv->p3DEngine->GetSegmentsManager()) //@TODO: make seg-world manager available from gEnv.
  492.                 FlushAllAreas();
  493. #else
  494.         FlushAllAreas();
  495. #endif
  496.  
  497.         unsigned numAreas;
  498.  
  499.         // Read designer paths
  500.         {
  501.                 file.ReadType(&numAreas);
  502.                 // vague sanity check
  503.                 AIAssert(numAreas < 1000000);
  504.                 for (unsigned iArea = 0; iArea < numAreas; ++iArea)
  505.                 {
  506.                         ListPositions lp;
  507.                         string name;
  508. #if defined(SEG_WORLD)
  509.                         ReadPolygonArea(file, fileVersion, name, lp, vSegmentOffset);
  510. #else
  511.                         ReadPolygonArea(file, fileVersion, name, lp);
  512. #endif
  513.  
  514.                         int navType(0), type(0);
  515.                         bool closed(false);
  516.                         file.ReadType(&navType);
  517.                         file.ReadType(&type);
  518.  
  519.                         if (fileVersion >= 22)
  520.                         {
  521.                                 file.ReadType(&closed);
  522.                         }
  523.  
  524.                         if (m_mapDesignerPaths.find(name) != m_mapDesignerPaths.end())
  525.                         {
  526.                                 AIError("CNavigation::ReadAreasFromFile: Designer path '%s' already exists, please rename the path and reexport.", name.c_str());
  527.                                 //@TODO do something about AI Paths in multiple area.bai files when in Segmented World
  528.                         }
  529.                         else
  530.                                 m_mapDesignerPaths.insert(ShapeMap::iterator::value_type(name, SShape(lp, false, (IAISystem::ENavigationType)navType, type, closed)));
  531.                 }
  532.         }
  533. }
  534.  
  535. // Offsets all areas when segmented world shifts
  536. void CNavigation::OffsetAllAreas(const Vec3& additionalOffset)
  537. {
  538.         for (ShapeMap::iterator it = m_mapDesignerPaths.begin(); it != m_mapDesignerPaths.end(); ++it)
  539.                 it->second.OffsetShape(additionalOffset);
  540. }
  541.  
  542. //===================================================================
  543. // GetSpecialAreaNearestPos
  544. //===================================================================
  545. const SpecialArea* CNavigation::GetSpecialAreaNearestPos(const Vec3& pos, SpecialArea::EType areaType)
  546. {
  547.         if (const SpecialArea* specialArea = GetSpecialArea(pos, areaType))
  548.                 return specialArea;
  549.  
  550.         float bestSq = std::numeric_limits<float>::max();
  551.         const SpecialArea* result = 0;
  552.  
  553.         SpecialAreas::const_iterator it = m_specialAreas.begin();
  554.         SpecialAreas::const_iterator end = m_specialAreas.end();
  555.  
  556.         for (; it != end; ++it)
  557.         {
  558.                 const SpecialArea& specialArea = *it;
  559.                 if (specialArea.type == areaType)
  560.                 {
  561.                         if (specialArea.fHeight > 0.00001f && (pos.z < specialArea.fMinZ || pos.z > specialArea.fMaxZ))
  562.                                 continue;
  563.  
  564.                         Vec3 polyPt;
  565.                         float distSq = Distance::Point_Polygon2DSq(pos, specialArea.GetPolygon(), polyPt);
  566.                         if (distSq < bestSq)
  567.                         {
  568.                                 bestSq = distSq;
  569.                                 result = &specialArea;
  570.                         }
  571.                 }
  572.         }
  573.  
  574.         return result;
  575. }
  576.  
  577. //====================================================================
  578. // GetPath
  579. //====================================================================
  580. uint32 CNavigation::GetPath(const char* szPathName, Vec3* points, uint32 maxpoints) const
  581. {
  582.         ListPositions junk1;
  583.         AABB junk2;
  584.         junk2.Reset();
  585.         SShape pathShape(junk1, junk2);
  586.         uint32 count = 0;
  587.  
  588.         if (GetDesignerPath(szPathName, pathShape))
  589.         {
  590.                 for (std::vector<Vec3>::iterator it = pathShape.shape.begin(), e = pathShape.shape.end(); it != e && count < maxpoints; ++it)
  591.                 {
  592.                         points[count] = *it;
  593.                         ++count;
  594.                 }
  595.         }
  596.  
  597.         return count;
  598. }
  599.  
  600. //====================================================================
  601. // GetNearestPointOnPath
  602. //====================================================================
  603. float CNavigation::GetNearestPointOnPath(const char* szPathName, const Vec3& vPos, Vec3& vResult, bool& bLoopPath, float& totalLength) const
  604. {
  605.         // calculate a point on a path which has the nearest distance from the given point.
  606.         // Also returns segno it means ( 0.0 start point 100.0 end point always)
  607.         // strict even if t == 0 or t == 1.0
  608.  
  609.         // return values
  610.         // return value : segno;
  611.         // vResult : the point on path
  612.         // bLoopPath : true if the path is looped
  613.  
  614.         vResult = ZERO;
  615.         bLoopPath = false;
  616.  
  617.         float result = -1.0;
  618.  
  619.         SShape pathShape;
  620.         if (!GetDesignerPath(szPathName, pathShape) || pathShape.shape.empty())
  621.                 return result;
  622.  
  623.         float dist = FLT_MAX;
  624.         bool bFound = false;
  625.         float segNo = 0.0f;
  626.         float howmanypath = 0.0f;
  627.  
  628.         Vec3 vPointOnLine;
  629.  
  630.         ListPositions::const_iterator cur = pathShape.shape.begin();
  631.         ListPositions::const_reverse_iterator last = pathShape.shape.rbegin();
  632.         ListPositions::const_iterator next(cur);
  633.         ++next;
  634.  
  635.         float lengthTmp = 0.0f;
  636.         while (next != pathShape.shape.end())
  637.         {
  638.                 Lineseg seg(*cur, *next);
  639.  
  640.                 lengthTmp += (*cur - *next).GetLength();
  641.  
  642.                 float t;
  643.                 float d = Distance::Point_Lineseg(vPos, seg, t);
  644.                 if (d < dist)
  645.                 {
  646.                         Vec3 vSeg = seg.GetPoint(1.0f) - seg.GetPoint(0.0f);
  647.                         Vec3 vTmp = vPos - seg.GetPoint(t);
  648.  
  649.                         vSeg.NormalizeSafe();
  650.                         vTmp.NormalizeSafe();
  651.  
  652.                         dist = d;
  653.                         bFound = true;
  654.                         result = segNo + t;
  655.                         vPointOnLine = seg.GetPoint(t);
  656.                 }
  657.                 cur = next;
  658.                 ++next;
  659.                 segNo += 1.0f;
  660.                 howmanypath += 1.0f;
  661.         }
  662.         if (howmanypath == 0.0f)
  663.                 return result;
  664.  
  665.         if (bFound == false)
  666.         {
  667.                 segNo = 0.0f;
  668.                 cur = pathShape.shape.begin();
  669.                 while (cur != pathShape.shape.end())
  670.                 {
  671.                         Vec3 vTmp = vPos - *cur;
  672.                         float d = vTmp.GetLength();
  673.                         if (d < dist)
  674.                         {
  675.                                 dist = d;
  676.                                 bFound = true;
  677.                                 result = segNo;
  678.                                 vPointOnLine = *cur;
  679.                         }
  680.                         ++cur;
  681.                         segNo += 1.0f;
  682.                 }
  683.         }
  684.  
  685.         vResult = vPointOnLine;
  686.  
  687.         cur = pathShape.shape.begin();
  688.  
  689.         Vec3 vTmp = *cur - *last;
  690.         if (vTmp.GetLength() < 0.0001f)
  691.                 bLoopPath = true;
  692.  
  693.         totalLength = lengthTmp;
  694.  
  695.         return result * 100.0f / howmanypath;
  696. }
  697.  
  698. //====================================================================
  699. // GetPointOnPathBySegNo
  700. //====================================================================
  701. void CNavigation::GetPointOnPathBySegNo(const char* szPathName, Vec3& vResult, float segNo) const
  702. {
  703.         vResult = ZERO;
  704.  
  705.         SShape pathShape;
  706.         if ((segNo < 0.f) || (segNo > 100.f) || !GetDesignerPath(szPathName, pathShape))
  707.                 return;
  708.  
  709.         ListPositions& shape = pathShape.shape;
  710.         size_t size = shape.size();
  711.         if (size == 0)
  712.                 return;
  713.  
  714.         if (size == 1)
  715.         {
  716.                 vResult = *(shape.begin());
  717.                 return;
  718.         }
  719.  
  720.         float totalLength = 0.0f;
  721.         for (ListPositions::const_iterator cur = shape.begin(), next = cur; ++next != shape.end(); cur = next)
  722.         {
  723.                 totalLength += (*next - *cur).GetLength();
  724.         }
  725.  
  726.         float segLength = totalLength * segNo / 100.0f;
  727.         float currentLength = 0.0f;
  728.         float currentSegLength = 0.0f;
  729.  
  730.         ListPositions::const_iterator cur, next;
  731.         for (cur = shape.begin(), next = cur; ++next != shape.end(); cur = next)
  732.         {
  733.                 const Vec3& curPoint = *cur;
  734.                 Vec3 currentSeg = *next - curPoint;
  735.                 currentSegLength = currentSeg.GetLength();
  736.  
  737.                 if (currentLength + currentSegLength > segLength)
  738.                 {
  739.                         vResult = curPoint;
  740.                         if (currentSegLength > 0.0003f)
  741.                         {
  742.                                 vResult += ((segLength - currentLength) / currentSegLength) * currentSeg;
  743.                         }
  744.                         return;
  745.                 }
  746.  
  747.                 currentLength += currentSegLength;
  748.         }
  749.  
  750.         vResult = *cur;
  751. }
  752.  
  753. //====================================================================
  754. // IsSegmentValid
  755. //====================================================================
  756. bool CNavigation::IsSegmentValid(IAISystem::tNavCapMask navCap, float rad, const Vec3& posFrom, Vec3& posTo, IAISystem::ENavigationType& navTypeFrom) const
  757. {
  758.         int nBuildingID = -1;
  759.  
  760.         navTypeFrom = CheckNavigationType(posFrom, nBuildingID, navCap);
  761.  
  762.         if (navTypeFrom == IAISystem::NAV_TRIANGULAR)
  763.         {
  764.                 // Make sure not to enter forbidden area.
  765.                 if (IsPathForbidden(posFrom, posTo))
  766.                         return false;
  767.  
  768.                 if (IsPointForbidden(posTo, rad))
  769.                         return false;
  770.         }
  771.  
  772.         const SpecialArea* pSpecialArea = (nBuildingID != -1 ? GetSpecialArea(nBuildingID) : 0);
  773.         if (pSpecialArea)
  774.         {
  775.                 const ListPositions& polygon = pSpecialArea->GetPolygon();
  776.  
  777.                 if (Overlap::Lineseg_Polygon2D(Lineseg(posFrom, posTo), polygon, &pSpecialArea->GetAABB()))
  778.                         return false;
  779.         }
  780.  
  781.         return CheckWalkability(posFrom, posTo, rad + 0.15f, &posTo);
  782. }
  783.  
  784. //====================================================================
  785. // GetSpecialArea
  786. //====================================================================
  787. const SpecialArea* CNavigation::GetSpecialArea(const Vec3& pos, SpecialArea::EType areaType)
  788. {
  789.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  790.  
  791.         SpecialAreas::iterator it = m_specialAreas.begin();
  792.         SpecialAreas::iterator end = m_specialAreas.end();
  793.  
  794.         for (; it != end; ++it)
  795.         {
  796.                 const SpecialArea& specialArea = *it;
  797.                 if ((specialArea.type == areaType) && IsPointInSpecialArea(pos, specialArea))
  798.                         return &specialArea;
  799.         }
  800.  
  801.         return 0;
  802. }
  803.  
  804. //====================================================================
  805. // GetSpecialArea
  806. //====================================================================
  807. const SpecialArea* CNavigation::GetSpecialArea(int buildingID) const
  808. {
  809.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  810.  
  811.         assert(buildingID < 0 || buildingID < (int)m_specialAreas.size());
  812.         if (buildingID >= 0 && buildingID < (int)m_specialAreas.size())
  813.                 return &m_specialAreas[buildingID];
  814.  
  815.         return 0;
  816. }
  817.  
  818. const SpecialArea* CNavigation::GetSpecialArea(const char* name) const
  819. {
  820.         SpecialAreaNames::const_iterator it = m_specialAreaNames.find(CONST_TEMP_STRING(name));
  821.         if (it != m_specialAreaNames.end())
  822.                 return GetSpecialArea(it->second);
  823.  
  824.         return 0;
  825. }
  826.  
  827. const char* CNavigation::GetSpecialAreaName(int buildingID) const
  828. {
  829.         SpecialAreaNames::const_iterator it = m_specialAreaNames.begin();
  830.         SpecialAreaNames::const_iterator end = m_specialAreaNames.end();
  831.  
  832.         for (; it != end; ++it)
  833.         {
  834.                 if (it->second == buildingID)
  835.                         return it->first.c_str();
  836.         }
  837.  
  838.         return "<Unknown>";
  839. }
  840.  
  841. void CNavigation::InsertSpecialArea(const char* name, const SpecialArea& sa)
  842. {
  843.         assert(sa.nBuildingID >= 0);
  844.         std::pair<SpecialAreaNames::iterator, bool> result = m_specialAreaNames.insert(
  845.           SpecialAreaNames::iterator::value_type(name, sa.nBuildingID));
  846.  
  847.         if ((size_t)sa.nBuildingID >= m_specialAreas.size())
  848.                 m_specialAreas.resize(sa.nBuildingID + 1);
  849.         m_specialAreas[sa.nBuildingID] = sa;
  850. }
  851.  
  852. void CNavigation::EraseSpecialArea(const char* name)
  853. {
  854.         SpecialAreaNames::iterator it = m_specialAreaNames.find(CONST_TEMP_STRING(name));
  855.         if (it == m_specialAreaNames.end())
  856.                 return;
  857.  
  858.         SpecialArea& specialArea = m_specialAreas[it->second];
  859.         assert(specialArea.nBuildingID >= 0);
  860.  
  861.         m_freeSpecialAreaIDs.push_back(specialArea.nBuildingID);
  862.         m_specialAreaNames.erase(it);
  863.         specialArea.nBuildingID = -1;
  864. }
  865.  
  866. void CNavigation::FlushSpecialAreas()
  867. {
  868.         m_specialAreaNames.clear();
  869.         m_specialAreas.clear();
  870.         m_freeSpecialAreaIDs.clear();
  871. }
  872.  
  873. //====================================================================
  874. // GetVolumeRegions
  875. //====================================================================
  876. void CNavigation::GetVolumeRegions(VolumeRegions& volumeRegions) const
  877. {
  878.         volumeRegions.resize(0);
  879.  
  880.         SpecialAreas::const_iterator it = m_specialAreas.begin();
  881.         SpecialAreas::const_iterator end = m_specialAreas.end();
  882.  
  883.         for (; it != end; ++it)
  884.         {
  885.                 const SpecialArea& specialArea = *it;
  886.  
  887.                 if (specialArea.type == SpecialArea::TYPE_VOLUME)
  888.                         volumeRegions.push_back(std::make_pair(GetSpecialAreaName(specialArea.nBuildingID), &specialArea));
  889.         }
  890. }
  891.  
  892. //====================================================================
  893. // GetBuildingInfo
  894. //====================================================================
  895. bool CNavigation::GetBuildingInfo(int nBuildingID, IAISystem::SBuildingInfo& info) const
  896. {
  897.         if (const SpecialArea* specialArea = GetSpecialArea(nBuildingID))
  898.         {
  899.                 info.fNodeAutoConnectDistance = specialArea->fNodeAutoConnectDistance;
  900.                 info.waypointConnections = specialArea->waypointConnections;
  901.  
  902.                 return true;
  903.         }
  904.  
  905.         return false;
  906. }
  907.  
  908. bool CNavigation::IsPointInBuilding(const Vec3& pos, int nBuildingID) const
  909. {
  910.         if (const SpecialArea* specialArea = GetSpecialArea(nBuildingID))
  911.                 return IsPointInSpecialArea(pos, *specialArea);
  912.  
  913.         return false;
  914. }
  915.  
  916. void CNavigation::FlushAllAreas()
  917. {
  918.         FlushSpecialAreas();
  919.         m_mapDesignerPaths.clear();
  920. }
  921.  
  922. //
  923. //-----------------------------------------------------------------------------------------------------------
  924. bool CNavigation::DoesNavigationShapeExists(const char* szName, EnumAreaType areaType, bool road)
  925. {
  926.         if (areaType == AREATYPE_PATH && !road)
  927.         {
  928.                 return m_mapDesignerPaths.find(szName) != m_mapDesignerPaths.end();
  929.         }
  930.         return false;
  931. }
  932.  
  933. //
  934. //-----------------------------------------------------------------------------------------------------------
  935. bool CNavigation::CreateNavigationShape(const SNavigationShapeParams& params)
  936. {
  937.         std::vector<Vec3> vecPts(params.points, params.points + params.nPoints);
  938.  
  939.         if (params.areaType == AREATYPE_PATH && params.pathIsRoad == false)
  940.         {
  941.                 //designer path need to preserve directions
  942.         }
  943.         else
  944.         {
  945.                 if (params.closed)
  946.                         EnsureShapeIsWoundAnticlockwise<std::vector<Vec3>, float>(vecPts);
  947.         }
  948.  
  949.         ListPositions listPts(vecPts.begin(), vecPts.end());
  950.  
  951.         if (params.areaType == AREATYPE_PATH)
  952.         {
  953.                 if (listPts.size() < 2)
  954.                         return true; // Do not report too few points as errors.
  955.  
  956.                 if (m_mapDesignerPaths.find(params.szPathName) != m_mapDesignerPaths.end())
  957.                 {
  958.                         AIError("CAISystem::CreateNavigationShape: Designer path '%s' already exists, please rename the path.", params.szPathName);
  959.                         return false;
  960.                 }
  961.  
  962.                 if (params.closed)
  963.                 {
  964.                         if (Distance::Point_Point(listPts.front(), listPts.back()) > 0.1f)
  965.                                 listPts.push_back(listPts.front());
  966.                 }
  967.                 m_mapDesignerPaths.insert(ShapeMap::iterator::value_type(params.szPathName, SShape(listPts, false, (IAISystem::ENavigationType)params.nNavType, params.nAuxType, params.closed)));
  968.         }
  969.         return true;
  970. }
  971.  
  972. // deletes designer created path
  973. //
  974. //-----------------------------------------------------------------------------------------------------------
  975. void CNavigation::DeleteNavigationShape(const char* szName)
  976. {
  977.         ShapeMap::iterator di;
  978.         di = m_mapDesignerPaths.find(szName);
  979.         if (di != m_mapDesignerPaths.end())
  980.                 m_mapDesignerPaths.erase(di);
  981. }
  982.  
  983. void CNavigation::DisableModifier(const char* name)
  984. {
  985.         SpecialAreaNames::iterator it = m_specialAreaNames.find(name);
  986.  
  987.         if (it != m_specialAreaNames.end())
  988.         {
  989.                 SpecialArea& specialArea = m_specialAreas[it->second];
  990.                 if (specialArea.bAltered)  // already disabled
  991.                         return;
  992.  
  993.                 GetAISystem()->InvalidatePathsThroughArea(specialArea.GetPolygon());
  994.                 specialArea.bAltered = true;
  995.         }
  996. }
  997.  
  998. //====================================================================
  999. // IsPointInWaterAreas
  1000. //====================================================================
  1001. inline bool IsPointInWaterAreas(const Vec3& pt, const std::vector<ListPositions>& areas)
  1002. {
  1003.         unsigned nAreas = areas.size();
  1004.         for (unsigned i = 0; i < nAreas; ++i)
  1005.         {
  1006.                 const ListPositions& area = areas[i];
  1007.                 if (Overlap::Point_Polygon2D(pt, area))
  1008.                         return true;
  1009.         }
  1010.         return false;
  1011. }
  1012.  
  1013. //===================================================================
  1014. // IsPointInWaterAreas
  1015. //===================================================================
  1016. bool CNavigation::IsPointInWaterAreas(const Vec3& pt) const
  1017. {
  1018.         SpecialAreas::const_iterator it = m_specialAreas.begin();
  1019.         SpecialAreas::const_iterator end = m_specialAreas.end();
  1020.  
  1021.         for (; it != end; ++it)
  1022.         {
  1023.                 const SpecialArea& specialArea = *it;
  1024.  
  1025.                 if (specialArea.type == SpecialArea::TYPE_WATER)
  1026.                 {
  1027.                         if (Overlap::Point_AABB2D(pt, specialArea.GetAABB()))
  1028.                                 if (Overlap::Point_Polygon2D(pt, specialArea.GetPolygon()))
  1029.                                         return true;
  1030.                 }
  1031.         }
  1032.  
  1033.         return false;
  1034. }
  1035.  
  1036. //====================================================================
  1037. // IsPointInSpecialArea
  1038. //====================================================================
  1039. bool CNavigation::IsPointInSpecialArea(const Vec3& pos, const SpecialArea& sa)
  1040. {
  1041.         if (sa.fHeight > 0.00001f && (pos.z < sa.fMinZ || pos.z > sa.fMaxZ))
  1042.                 return false;
  1043.  
  1044.         return Overlap::Point_Polygon2D(pos, sa.GetPolygon(), &sa.GetAABB());
  1045. }
  1046.  
  1047. //===================================================================
  1048. // IsPointInTriangulationAreas
  1049. //===================================================================
  1050. bool CNavigation::IsPointInTriangulationAreas(const Vec3& pos) const
  1051. {
  1052.         AIAssert(gEnv->IsEditor());
  1053.  
  1054.         bool foundOne = false;
  1055.         SpecialAreas::const_iterator it = m_specialAreas.begin();
  1056.         SpecialAreas::const_iterator end = m_specialAreas.end();
  1057.  
  1058.         for (; it != end; ++it)
  1059.         {
  1060.                 const SpecialArea& specialArea = *it;
  1061.  
  1062.                 if (specialArea.type == SpecialArea::TYPE_TRIANGULATION)
  1063.                 {
  1064.                         if (Overlap::Point_Polygon2D(pos, specialArea.GetPolygon(), &specialArea.GetAABB()))
  1065.                                 return true;
  1066.  
  1067.                         foundOne = true;
  1068.                 }
  1069.         }
  1070.  
  1071.         return !foundOne;
  1072. }
  1073.  
  1074. //====================================================================
  1075. // GetPointOutsideForbidden
  1076. //====================================================================
  1077. Vec3 CNavigation::GetPointOutsideForbidden(Vec3& pos, float distance, const Vec3* startPos) const
  1078. {
  1079.         return pos;
  1080. }
  1081.  
  1082. const char* CNavigation::GetNearestPathOfTypeInRange(IAIObject* requester, const Vec3& reqPos, float range, int type, float devalue, bool useStartNode)
  1083. {
  1084.         AIAssert(requester);
  1085.         float rangeSq(sqr(range));
  1086.  
  1087.         ShapeMap::iterator closestShapeIt(m_mapDesignerPaths.end());
  1088.         float closestShapeDist(rangeSq);
  1089.         CAIActor* pReqActor = requester->CastToCAIActor();
  1090.  
  1091.         for (ShapeMap::iterator it = m_mapDesignerPaths.begin(); it != m_mapDesignerPaths.end(); ++it)
  1092.         {
  1093.                 const SShape& path = it->second;
  1094.  
  1095.                 // Skip paths which we cannot travel
  1096.                 if ((path.navType & pReqActor->GetMovementAbility().pathfindingProperties.navCapMask) == 0)
  1097.                         continue;
  1098.                 // Skip wrong type
  1099.                 if (path.type != type)
  1100.                         continue;
  1101.                 // Skip locked paths
  1102.                 if (path.devalueTime > 0.01f)
  1103.                         continue;
  1104.  
  1105.                 // Skip paths too far away
  1106.                 Vec3 tmp;
  1107.                 if (Distance::Point_AABBSq(reqPos, path.aabb, tmp) > rangeSq)
  1108.                         continue;
  1109.  
  1110.                 float d;
  1111.                 if (useStartNode)
  1112.                 {
  1113.                         // Disntance to start node.
  1114.                         d = Distance::Point_PointSq(reqPos, path.shape.front());
  1115.                 }
  1116.                 else
  1117.                 {
  1118.                         // Distance to nearest point on path.
  1119.                         ListPositions::const_iterator nearest = path.NearestPointOnPath(reqPos, false, d, tmp);
  1120.                 }
  1121.  
  1122.                 if (d < closestShapeDist)
  1123.                 {
  1124.                         closestShapeIt = it;
  1125.                         closestShapeDist = d;
  1126.                 }
  1127.         }
  1128.  
  1129.         if (closestShapeIt != m_mapDesignerPaths.end())
  1130.         {
  1131.                 closestShapeIt->second.devalueTime = devalue;
  1132.                 return closestShapeIt->first.c_str();
  1133.         }
  1134.  
  1135.         return 0;
  1136. }
  1137.  
  1138. //====================================================================
  1139. // DisableNavigationInBrokenRegion
  1140. //====================================================================
  1141. void CNavigation::DisableNavigationInBrokenRegion(std::vector<Vec3>& outline)
  1142. {
  1143.         if (!gAIEnv.pGraph)
  1144.         {
  1145.                 AIWarning("Being asked to disable navigation in broken region, yet no graph");
  1146.                 return;
  1147.         }
  1148.         AABB outlineAABB(AABB::RESET);
  1149.         for (std::vector<Vec3>::const_iterator it = outline.begin(); it != outline.end(); ++it)
  1150.                 outlineAABB.Add(*it);
  1151.         outlineAABB.min.z = -std::numeric_limits<float>::max();
  1152.         outlineAABB.max.z = std::numeric_limits<float>::max();
  1153.  
  1154.         AILogEvent("Disabling navigation in broken region (%5.2f, %5.2f, %5.2f) to (%5.2f, %5.2f, %5.2f)",
  1155.                    outlineAABB.min.x, outlineAABB.min.y, outlineAABB.min.z,
  1156.                    outlineAABB.max.x, outlineAABB.max.y, outlineAABB.max.z);
  1157. }
  1158.  
  1159. //====================================================================
  1160. // GetVolumeRegionFiles
  1161. //====================================================================
  1162. void CNavigation::GetVolumeRegionFiles(const char* szLevel, const char* szMission, DynArray<CryStringT<char>>& filenames) const
  1163. {
  1164.         filenames.clear();
  1165.  
  1166.         VolumeRegions volumeRegions;
  1167.         GetVolumeRegions(volumeRegions);
  1168.  
  1169.         string name;
  1170.         unsigned nRegions = volumeRegions.size();
  1171.         for (unsigned i = 0; i < nRegions; ++i)
  1172.         {
  1173.                 const string& regionName = volumeRegions[i].first;
  1174.                 /// match what's done in CVolumeNavRegion
  1175.                 if (regionName.length() > 17)
  1176.                 {
  1177.                         name = string(regionName.c_str() + 17);
  1178.                 }
  1179.                 else
  1180.                 {
  1181.                         AIWarning("CAISystem::GetVolumeRegionFiles region name is too short %s", regionName.c_str());
  1182.                         continue;
  1183.                 }
  1184.  
  1185.                 CryStringT<char> fileName;
  1186.                 fileName.Format("%s/v3d%s-region-%s.bai", szLevel, szMission, name.c_str());
  1187.  
  1188.                 filenames.push_back(fileName);
  1189.         }
  1190. }
  1191.  
  1192. //====================================================================
  1193. // GetNavRegion
  1194. //====================================================================
  1195. CNavRegion* CNavigation::GetNavRegion(IAISystem::ENavigationType type, const class CGraph* pGraph) const
  1196. {
  1197.         switch (type)
  1198.         {
  1199.         case IAISystem::NAV_UNSET:
  1200.                 return 0;
  1201.         }
  1202.         return 0;
  1203. }
  1204.  
  1205. //====================================================================
  1206. // CheckNavigationType
  1207. // When areas are nested there is an ordering - make this explicit by
  1208. // ordering the search over the navigation types
  1209. //====================================================================
  1210. IAISystem::ENavigationType CNavigation::CheckNavigationType(const Vec3& pos, int& nBuildingID, IAISystem::tNavCapMask navCapMask) const
  1211. {
  1212.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  1213.  
  1214.         if (navCapMask & IAISystem::NAV_WAYPOINT_HUMAN)
  1215.         {
  1216.                 SpecialAreas::const_iterator it = m_specialAreas.begin();
  1217.                 SpecialAreas::const_iterator end = m_specialAreas.end();
  1218.  
  1219.                 for (; it != end; ++it)
  1220.                 {
  1221.                         const SpecialArea& specialArea = *it;
  1222.  
  1223.                         if (specialArea.type == SpecialArea::TYPE_WAYPOINT_HUMAN)
  1224.                         {
  1225.                                 if (IsPointInSpecialArea(pos, specialArea))
  1226.                                 {
  1227.                                         nBuildingID = specialArea.nBuildingID;
  1228.  
  1229.                                         return IAISystem::NAV_WAYPOINT_HUMAN;
  1230.                                 }
  1231.                         }
  1232.                 }
  1233.         }
  1234.  
  1235.         if (navCapMask & IAISystem::NAV_VOLUME)
  1236.         {
  1237.                 SpecialAreas::const_iterator it = m_specialAreas.begin();
  1238.                 SpecialAreas::const_iterator end = m_specialAreas.end();
  1239.  
  1240.                 for (; it != end; ++it)
  1241.                 {
  1242.                         const SpecialArea& specialArea = *it;
  1243.  
  1244.                         if (specialArea.type == SpecialArea::TYPE_VOLUME)
  1245.                         {
  1246.                                 if (IsPointInSpecialArea(pos, specialArea))
  1247.                                 {
  1248.                                         nBuildingID = specialArea.nBuildingID;
  1249.  
  1250.                                         return IAISystem::NAV_VOLUME;
  1251.                                 }
  1252.                         }
  1253.                 }
  1254.         }
  1255.  
  1256.         if (navCapMask & IAISystem::NAV_FLIGHT)
  1257.         {
  1258.                 SpecialAreas::const_iterator it = m_specialAreas.begin();
  1259.                 SpecialAreas::const_iterator end = m_specialAreas.end();
  1260.  
  1261.                 for (; it != end; ++it)
  1262.                 {
  1263.                         const SpecialArea& specialArea = *it;
  1264.  
  1265.                         if (specialArea.type == SpecialArea::TYPE_FLIGHT)
  1266.                         {
  1267.                                 if (IsPointInSpecialArea(pos, specialArea))
  1268.                                 {
  1269.                                         nBuildingID = specialArea.nBuildingID;
  1270.  
  1271.                                         return IAISystem::NAV_FLIGHT;
  1272.                                 }
  1273.                         }
  1274.                 }
  1275.         }
  1276.  
  1277.         if (navCapMask & IAISystem::NAV_FREE_2D)
  1278.         {
  1279.                 SpecialAreas::const_iterator it = m_specialAreas.begin();
  1280.                 SpecialAreas::const_iterator end = m_specialAreas.end();
  1281.  
  1282.                 for (; it != end; ++it)
  1283.                 {
  1284.                         const SpecialArea& specialArea = *it;
  1285.  
  1286.                         if (specialArea.type == SpecialArea::TYPE_FREE_2D)
  1287.                         {
  1288.                                 if (IsPointInSpecialArea(pos, specialArea))
  1289.                                 {
  1290.                                         nBuildingID = specialArea.nBuildingID;
  1291.  
  1292.                                         return IAISystem::NAV_FREE_2D;
  1293.                                 }
  1294.                         }
  1295.                 }
  1296.         }
  1297.  
  1298.         if (navCapMask & IAISystem::NAV_TRIANGULAR)
  1299.                 return IAISystem::NAV_TRIANGULAR;
  1300.  
  1301.         if (navCapMask & IAISystem::NAV_FREE_2D)
  1302.                 return IAISystem::NAV_FREE_2D;
  1303.  
  1304.         return IAISystem::NAV_UNSET;
  1305. }
  1306.  
  1307. void CNavigation::GetMemoryStatistics(ICrySizer* pSizer)
  1308. {
  1309.         {
  1310.                 SIZER_SUBCOMPONENT_NAME(pSizer, "NavRegions");
  1311.         }
  1312.  
  1313.         size_t size = 0;
  1314.         for (ShapeMap::iterator itr = m_mapDesignerPaths.begin(); itr != m_mapDesignerPaths.end(); ++itr)
  1315.         {
  1316.                 size += (itr->first).capacity();
  1317.                 size += itr->second.MemStats();
  1318.         }
  1319.         pSizer->AddObject(&m_mapDesignerPaths, size);
  1320. }
  1321.  
  1322. size_t CNavigation::GetMemoryUsage() const
  1323. {
  1324.         size_t mem = 0;
  1325.         return mem;
  1326. }
  1327.  
  1328. #ifdef CRYAISYSTEM_DEBUG
  1329. //-----------------------------------------------------------------------------------------------------------
  1330. void CNavigation::DebugDraw() const
  1331. {
  1332.         CDebugDrawContext dc;
  1333.  
  1334.         if (!m_validationErrorMarkers.empty())
  1335.         {
  1336.                 for (unsigned i = 0; i < m_validationErrorMarkers.size(); ++i)
  1337.                 {
  1338.                         const SValidationErrorMarker& marker = m_validationErrorMarkers[i];
  1339.                         dc->DrawOBB(marker.obb, marker.pos, false, marker.col, eBBD_Faceted);
  1340.  
  1341.                         const float s = 0.01f;
  1342.                         dc->DrawLine(marker.pos + Vec3(-s, 0, 0), marker.col, marker.pos + Vec3(s, 0, 0), marker.col);
  1343.                         dc->DrawLine(marker.pos + Vec3(0, -s, 0), marker.col, marker.pos + Vec3(0, s, 0), marker.col);
  1344.                         dc->DrawLine(marker.pos + Vec3(0, 0, -s), marker.col, marker.pos + Vec3(0, 0, s), marker.col);
  1345.  
  1346.                         dc->Draw3dLabelEx(marker.pos, 1.1f, marker.col, true, true, false, false, "%s", marker.msg.c_str());
  1347.                 }
  1348.         }
  1349.  
  1350.         CAISystem* pAISystem = GetAISystem();
  1351.         int debugDrawVal = gAIEnv.CVars.DebugDraw;
  1352.  
  1353.         // Draw occupied designer paths
  1354.         for (ShapeMap::const_iterator it = m_mapDesignerPaths.begin(); it != m_mapDesignerPaths.end(); ++it)
  1355.         {
  1356.                 const SShape& path = it->second;
  1357.                 if (path.devalueTime < 0.01f)
  1358.                         continue;
  1359.                 dc->Draw3dLabel(path.shape.front(), 1, "%.1f", path.devalueTime);
  1360.         }
  1361. }
  1362.  
  1363. #endif //CRYAISYSTEM_DEBUG
  1364.  
downloadNavigation.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