BVB Source Codes

CRYENGINE Show PathMarker.cpp Source code

Return Download CRYENGINE: download PathMarker.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:   PathMarker.cpp
  6.  
  7.    Description: CPathMarker class implementation
  8.  
  9.    (MATT) Used only by CFormation {2009/06/04}
  10.  
  11.    -------------------------------------------------------------------------
  12.    History:
  13.    - 17:11:2004   14:19 : Created by Luciano Morpurgo
  14.  
  15.  *********************************************************************/
  16.  
  17. #include "StdAfx.h"
  18. #include "PathMarker.h"
  19. #include <limits>
  20. #include "DebugDrawContext.h"
  21.  
  22. CPathMarker::CPathMarker(float fMaxDistanceNeeded, float fStep)
  23. {
  24.         if (fStep <= .0f)
  25.                 m_fStep = 0.1f;
  26.         else
  27.                 m_fStep = fStep;
  28.         m_iSize = (int)ceilf(fMaxDistanceNeeded / m_fStep) + 1;
  29.         m_cBuffer.resize(m_iSize);
  30.         m_iCurrentPoint = 0;
  31.         m_fTotalDistanceRun = 0;
  32.         m_iUsed = 0;
  33. }
  34.  
  35. void CPathMarker::Update(const Vec3& vNewPoint, bool b2D)
  36. {
  37.         Vec3 vMovement = (vNewPoint - m_cBuffer[m_iCurrentPoint].vPoint);
  38.         if (b2D)
  39.                 vMovement.z = 0;
  40.  
  41.         float fDistance = vMovement.GetLength();
  42.  
  43.         if (fDistance >= m_fStep)
  44.         {
  45.                 ++m_iCurrentPoint;
  46.                 if (m_iCurrentPoint >= m_iSize)
  47.                         m_iCurrentPoint = 0;
  48.                 m_cBuffer[m_iCurrentPoint].vPoint = vNewPoint;
  49.                 m_cBuffer[m_iCurrentPoint].fDistance = fDistance;
  50.                 m_fTotalDistanceRun += fDistance;
  51.                 if (m_iUsed < m_iSize) m_iUsed++;
  52.         }
  53. }
  54.  
  55. Vec3 CPathMarker::GetPointAtDistance(const Vec3& vTargetPoint, float fDesiredDistance) const
  56. {
  57.         if (!m_iUsed)
  58.                 return vTargetPoint;
  59.  
  60.         float fComputedDistance = Distance::Point_Point(vTargetPoint, m_cBuffer[m_iCurrentPoint].vPoint);
  61.         Vec3 vPoint;
  62.         int iPoint = m_iCurrentPoint;
  63.  
  64.         const Vec3* segStart(&vTargetPoint);
  65.         const Vec3* segEnd(&m_cBuffer[m_iCurrentPoint].vPoint);
  66.         float segLen(fComputedDistance);
  67.  
  68.         for (int i = 0; i < m_iUsed - 1; i++)
  69.         {
  70.                 --iPoint;
  71.                 if (iPoint < 0)
  72.                         iPoint = m_iSize - 1;
  73.  
  74.                 if (fComputedDistance >= fDesiredDistance)
  75.                 {
  76.                         if (segLen > 0)
  77.                         {
  78.                                 float fAlpha;
  79.                                 fAlpha = 1.0f - (fComputedDistance - fDesiredDistance) / segLen;
  80.                                 if (fAlpha < 0) fAlpha = 0.0f;
  81.                                 if (fAlpha > 1) fAlpha = 1.0f;
  82.                                 return *segStart + fAlpha * (*segEnd - *segStart);
  83.                         }
  84.                 }
  85.  
  86.                 segStart = segEnd;
  87.                 segEnd = &m_cBuffer[iPoint].vPoint;
  88.                 segLen = m_cBuffer[iPoint].fDistance;
  89.  
  90.                 fComputedDistance += segLen;
  91.         }
  92.  
  93.         return *segEnd;
  94. }
  95.  
  96. Vec3 CPathMarker::GetPointAtDistanceFromNewestPoint(float fDesiredDistanceFromNewestPoint) const
  97. {
  98.         if (!m_iUsed)
  99.                 return Vec3(0, 0, 0);
  100.  
  101.         if (m_iUsed < 2 || fDesiredDistanceFromNewestPoint <= 0.0f)
  102.                 return m_cBuffer[m_iCurrentPoint].vPoint;
  103.  
  104.         const pathStep_t* segStart = NULL;
  105.         const pathStep_t* segEnd = NULL;
  106.  
  107.         for (int i = 0; i < m_iUsed - 1; i++)
  108.         {
  109.                 int indexSegEnd = m_iCurrentPoint - i;
  110.                 int indexSegStart = m_iCurrentPoint - i - 1;
  111.  
  112.                 if (indexSegStart < 0)
  113.                         indexSegStart += m_iUsed;
  114.                 if (indexSegEnd < 0)
  115.                         indexSegEnd += m_iUsed;
  116.  
  117.                 segEnd = &m_cBuffer[indexSegEnd];
  118.                 segStart = &m_cBuffer[indexSegStart];
  119.  
  120.                 const float segLen = segEnd->fDistance;
  121.  
  122.                 if (fDesiredDistanceFromNewestPoint > segLen)
  123.                 {
  124.                         fDesiredDistanceFromNewestPoint -= segLen;
  125.                 }
  126.                 else
  127.                 {
  128.                         Vec3 dir = segStart->vPoint - segEnd->vPoint;
  129.                         dir.NormalizeSafe();
  130.                         return segEnd->vPoint + dir * fDesiredDistanceFromNewestPoint;
  131.                 }
  132.         }
  133.  
  134.         return segEnd->vPoint;
  135. }
  136.  
  137. //
  138. //----------------------------------------------------------------------------------------------------------------
  139. Vec3 CPathMarker::GetDirectionAtDistance(const Vec3& vTargetPoint, float fDesiredDistance) const
  140. {
  141.         if (!m_iUsed)
  142.                 return Vec3(0, 0, 0);
  143.  
  144.         float fComputedDistance = Distance::Point_Point(vTargetPoint, m_cBuffer[m_iCurrentPoint].vPoint);
  145.         Vec3 vDir(0, 0, 0);
  146.         int iPoint = m_iCurrentPoint;
  147.  
  148.         const Vec3* segStart(&vTargetPoint);
  149.         const Vec3* segEnd(&m_cBuffer[m_iCurrentPoint].vPoint);
  150.         float segLen(fComputedDistance);
  151.  
  152.         for (int i = 0; i < m_iUsed; i++)
  153.         {
  154.                 if (--iPoint < 0) iPoint = m_iSize - 1;
  155.  
  156.                 if (fComputedDistance >= fDesiredDistance)
  157.                         break;
  158.  
  159.                 segStart = segEnd;
  160.                 segEnd = &m_cBuffer[iPoint].vPoint;
  161.                 segLen = m_cBuffer[iPoint].fDistance;
  162.  
  163.                 fComputedDistance += segLen;
  164.         }
  165.  
  166.         if (segLen > 0)
  167.         {
  168.                 vDir = *segStart - *segEnd;
  169.                 vDir.NormalizeSafe();
  170.         }
  171.  
  172.         return vDir;
  173.  
  174. }
  175.  
  176. //
  177. //----------------------------------------------------------------------------------------------------------------
  178. Vec3 CPathMarker::GetDirectionAtDistanceFromNewestPoint(float fDistanceFromNewestPoint) const
  179. {
  180.         if (!m_iUsed)
  181.                 return Vec3(0, 0, 0);
  182.  
  183.         const pathStep_t* segEnd = NULL;
  184.         const pathStep_t* segStart = NULL;
  185.  
  186.         for (int i = 0; i < m_iUsed; i++)
  187.         {
  188.                 int indexSegEnd = m_iCurrentPoint - i;
  189.                 int indexSegStart = m_iCurrentPoint - 1 - i;
  190.  
  191.                 if (indexSegStart < 0)
  192.                         indexSegStart += m_iUsed;
  193.                 if (indexSegEnd < 0)
  194.                         indexSegEnd += m_iUsed;
  195.  
  196.                 segEnd = &m_cBuffer[indexSegEnd];
  197.                 segStart = &m_cBuffer[indexSegStart];
  198.  
  199.                 if ((fDistanceFromNewestPoint -= segStart->fDistance) <= 0.0f)
  200.                         break;
  201.         }
  202.  
  203.         Vec3 vDir = segEnd->vPoint - segStart->vPoint;
  204.         vDir.NormalizeSafe();
  205.  
  206.         return vDir;
  207. }
  208.  
  209. //
  210. //----------------------------------------------------------------------------------------------------------------
  211. Vec3 CPathMarker::GetMoveDirectionAtDistance(Vec3& vTargetPoint, float fDesiredDistance, const Vec3& vUserPos,
  212.                                              float falloff, float* alignmentWithPath,
  213.                                              CSteeringDebugInfo* debugInfo)
  214. {
  215.         int iPoint = m_iCurrentPoint;
  216.         float closestDist = std::numeric_limits<float>::max();
  217.         int closestIndex = iPoint; // default to last point
  218.         int closestPtsBack = 0;
  219.         int ptsBack = 0;
  220.         for (int i = 0; i < m_iUsed; i++)
  221.         {
  222.                 // guarantee first point won't be chosen so we can use closestIndex and
  223.                 // closestIndex + 1
  224.                 if (i != 0)
  225.                 {
  226.                         Vec3 delta = m_cBuffer[iPoint].vPoint - vUserPos;
  227.                         float dist = delta.GetLength();
  228.                         if (dist < closestDist)
  229.                         {
  230.                                 closestDist = dist;
  231.                                 closestIndex = iPoint;
  232.                                 closestPtsBack = ptsBack;
  233.                         }
  234.                 }
  235.                 if (--iPoint < 0) iPoint = m_iSize - 1;
  236.                 ++ptsBack;
  237.         }
  238.  
  239.         // The direction is based on this segment, but as if this segment is moved ahead.
  240.         // Without a lookahead then we don't anticipte corners. If we just use a segment
  241.         // from in front then its direction on a corner will counteract any advantage.
  242.         // This way if the path ahead turns to the right and we're already on the right
  243.         // of the path, parallel to the path where we are, then we won't turn.
  244.         int nextIndex = (closestIndex + 1) % m_iSize;
  245.         // Get the orientation of the closest line segment
  246.         Vec3 segDir = m_cBuffer[nextIndex].vPoint - m_cBuffer[closestIndex].vPoint;
  247.         segDir.z = 0.0f;
  248.         segDir.NormalizeSafe();
  249.         Vec3 segRightDir(segDir.y, -segDir.x, 0.0f);
  250.  
  251.         // path can be wonky at the start - if so then use a fallback
  252.         if ((segDir | (vTargetPoint - vUserPos)) < 0.0f)
  253.         {
  254.                 segDir = vTargetPoint - vUserPos;
  255.                 segDir.z = 0.0f;
  256.                 segDir.NormalizeSafe();
  257.                 if (alignmentWithPath)
  258.                         *alignmentWithPath = 0.0f;
  259.         }
  260.  
  261.         // now lookahead
  262.         float lookahead = falloff;
  263.         iPoint = closestIndex;
  264.         for (int i = 0; i < closestPtsBack; ++i)
  265.         {
  266.                 iPoint = (iPoint + 1) % m_iSize;
  267.                 lookahead -= m_cBuffer[iPoint].fDistance;
  268.                 if (lookahead <= 0.0f)
  269.                         break;
  270.         }
  271.  
  272.         // Work out how far to one side (the right) we are
  273.         Vec3 delta = vUserPos - m_cBuffer[iPoint].vPoint;
  274.         delta.z = 0.0f;
  275.         Vec3 sideVec = delta - (delta | segDir) * segDir;
  276.         float sideDist = sideVec | segRightDir;
  277.  
  278.         // Now blend in a steering based on this distance and the falloff
  279.         float steerFactor = -sideDist / falloff;
  280.         if (steerFactor > 1.0f)
  281.                 steerFactor = 1.0f;
  282.         else if (steerFactor < -1.0f)
  283.                 steerFactor = -1.0f;
  284.  
  285.         Vec3 userDir = segDir + steerFactor * segRightDir;
  286.         userDir.NormalizeSafe();
  287.  
  288.         if (alignmentWithPath)
  289.                 *alignmentWithPath = userDir | segDir;
  290.  
  291.         if (debugInfo)
  292.         {
  293.                 debugInfo->segStart = m_cBuffer[iPoint].vPoint;
  294.                 debugInfo->segEnd = debugInfo->segStart + segDir;
  295.  
  296.                 debugInfo->pts.resize(0);
  297.                 iPoint = m_iCurrentPoint;
  298.                 for (int i = 0; i < m_iUsed; i++)
  299.                 {
  300.                         debugInfo->pts.push_back(m_cBuffer[iPoint].vPoint);
  301.                         if (--iPoint < 0)
  302.                                 iPoint = m_iSize - 1;
  303.                 }
  304.         }
  305.  
  306.         return userDir;
  307. }
  308.  
  309. //
  310. //----------------------------------------------------------------------------------------------------------------
  311. float CPathMarker::GetDistanceToPoint(Vec3& vTargetPoint, Vec3& vMyPoint)
  312. {
  313.         float fComputedDistance = (vTargetPoint - m_cBuffer[m_iCurrentPoint].vPoint).GetLength();
  314.         //the closest navpoint to the given MyPoint is chosen to compute the distance along the path
  315.         //TO DO: that's not always exact, in some cases it could be the wrong point
  316.         float fMinDistance2 = 100000000.0f;
  317.         int iClosestPoint = m_iCurrentPoint;
  318.         for (int i = 0; i < m_iUsed; i++)
  319.         {
  320.                 float fCurrentDistance = (vMyPoint - m_cBuffer[i].vPoint).len2();
  321.                 if (fCurrentDistance <= fMinDistance2)
  322.                 {
  323.                         fMinDistance2 = fCurrentDistance;
  324.                         iClosestPoint = i;
  325.                 }
  326.         }
  327.  
  328.         int iPoint = m_iCurrentPoint;
  329.         while (iPoint != iClosestPoint)
  330.         {
  331.                 fComputedDistance += m_cBuffer[iPoint].fDistance;
  332.                 if (--iPoint < 0) iPoint = m_iSize - 1;
  333.         }
  334.         //final adjustment to distance : instead of adding the fDistance of iClosestPoint,
  335.         // we add the distance from the previous point (iClosestPoint+1) to vMyPoint
  336.         iPoint = (iClosestPoint + 1) % m_iSize;
  337.         fComputedDistance += (vMyPoint - m_cBuffer[iPoint].vPoint).GetLength();
  338.         return fComputedDistance;
  339. }
  340.  
  341. //
  342. //----------------------------------------------------------------------------------------------------------------
  343. void CPathMarker::Init(const Vec3& vEndPoint, const Vec3& vInitPoint)
  344. {
  345.         m_cBuffer[0].vPoint = vEndPoint;
  346.         m_cBuffer[0].fDistance = 0;
  347.         m_cBuffer[0].bPassed = false;
  348.         m_iCurrentPoint = 0;
  349.         m_fTotalDistanceRun = 0;
  350.         m_iUsed = 1;
  351. }
  352. //
  353. //----------------------------------------------------------------------------------------------------------------
  354. void CPathMarker::Serialize(TSerialize ser)
  355. {
  356.         ser.BeginGroup("AIPathMarker");
  357.         {
  358.                 ser.Value("m_fStep", m_fStep);
  359.                 ser.Value("m_iCurrentPoint", m_iCurrentPoint);
  360.                 ser.Value("m_iSize", m_iSize);
  361.                 ser.Value("m_iUsed", m_iUsed);
  362.                 ser.Value("m_fTotalDistanceRun", m_fTotalDistanceRun);
  363.                 ser.BeginGroup("AIPathMarkerPoints");
  364.                 {
  365.                         if (ser.IsReading())
  366.                         {
  367.                                 m_cBuffer.clear();
  368.                                 m_cBuffer.resize(m_iSize);
  369.                         }
  370.                         for (int i = 0; i < m_iUsed; i++)
  371.                         {
  372.                                 ser.BeginGroup("point");
  373.                                 pathStep_t& point = m_cBuffer[i];
  374.                                 ser.Value("pos", point.vPoint);
  375.                                 ser.Value("dist", point.fDistance);
  376.                                 ser.Value("passed", point.bPassed);
  377.                                 ser.EndGroup();
  378.                         }
  379.                         ser.EndGroup();
  380.                 }
  381.                 ser.EndGroup();
  382.         }
  383. }
  384.  
  385. void CPathMarker::DebugDraw()
  386. {
  387.         if (m_iUsed < 2)
  388.                 return;
  389.  
  390.         int prev = m_iCurrentPoint;
  391.         int cur = m_iCurrentPoint - 1;
  392.         if (cur < 0) cur = m_iSize - 1;
  393.  
  394.         CDebugDrawContext dc;
  395.  
  396.         for (int i = 0; i < m_iUsed - 1; ++i)
  397.         {
  398.                 dc->DrawLine(m_cBuffer[prev].vPoint, ColorB(255, 255, 255, 128),
  399.                              m_cBuffer[cur].vPoint, ColorB(255, 255, 255, 128), 3.0f);
  400.                 prev = cur;
  401.                 --cur;
  402.                 if (cur < 0) cur = m_iSize - 1;
  403.         }
  404. }
  405.  
downloadPathMarker.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