BVB Source Codes

CRYENGINE Show FlyHelpers_PathFollower.cpp Source code

Return Download CRYENGINE: download FlyHelpers_PathFollower.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. #include "StdAfx.h"
  4. #include "FlyHelpers_PathFollower.h"
  5.  
  6. #include "FlyHelpers_PathFollowerHelpers.h"
  7. #include "FlyHelpers_Debug.h"
  8.  
  9. namespace FlyHelpers
  10. {
  11.  
  12. PathFollower::PathFollower()
  13.         : m_targetPosition(0, 0, 0)
  14.         , m_lookAtPosition(0, 0, 0)
  15.         , m_finalPosition(0, 0, 0)
  16.         , m_stopAtFinalLocation(false)
  17.         , m_pCurrentPath(NULL)
  18. {
  19. }
  20.  
  21. PathFollower::~PathFollower()
  22. {
  23. }
  24.  
  25. void PathFollower::SetPath(const SShape& path, const bool loopAlongPath)
  26. {
  27.         m_pCurrentPath = &m_path;
  28.  
  29.         m_path.Clear();
  30.         for (size_t i = 0; i < path.shape.size(); ++i)
  31.         {
  32.                 const Vec3& point = path.shape[i];
  33.                 m_path.AddPoint(point);
  34.         }
  35.  
  36.         if (loopAlongPath)
  37.         {
  38.                 m_path.MakeLooping();
  39.         }
  40.  
  41.         m_reversePath.Clear();
  42.         const size_t pathPointCount = m_path.GetPointCount();
  43.         for (size_t i = 1; i <= pathPointCount; ++i)
  44.         {
  45.                 const size_t reverseIndex = pathPointCount - i;
  46.                 const Vec3& reversePoint = m_path.GetPoint(reverseIndex);
  47.                 m_reversePath.AddPoint(reversePoint);
  48.         }
  49.  
  50.         ResetFinalPathLocation();
  51. }
  52.  
  53. void PathFollower::SetUseReversePath(const bool useReversePath)
  54. {
  55.         CRY_ASSERT(m_pCurrentPath);
  56.  
  57.         const bool usingReversePath = (m_pCurrentPath == &m_reversePath);
  58.         const bool shouldSwitchPaths = (usingReversePath != useReversePath);
  59.         if (!shouldSwitchPaths)
  60.         {
  61.                 return;
  62.         }
  63.  
  64.         m_targetLocation = GetReversePathLocation(*m_pCurrentPath, m_targetLocation);
  65.         m_lookAtLocation = GetReversePathLocation(*m_pCurrentPath, m_lookAtLocation);
  66.         m_finalLocation = GetReversePathLocation(*m_pCurrentPath, m_finalLocation);
  67.  
  68.         m_pCurrentPath = useReversePath ? &m_reversePath : &m_path;
  69.  
  70.         m_targetPosition = CalculatePathPosition(m_targetLocation);
  71.         m_lookAtPosition = CalculatePathPosition(m_lookAtLocation);
  72.         m_finalPosition = CalculatePathPosition(m_finalLocation);
  73. }
  74.  
  75. PathLocation PathFollower::GetNonReversedTargetLocation() const
  76. {
  77.         CRY_ASSERT(m_pCurrentPath);
  78.  
  79.         const bool usingReversePath = (m_pCurrentPath == &m_reversePath);
  80.         if (usingReversePath)
  81.         {
  82.                 return GetReversePathLocation(m_reversePath, m_targetLocation);
  83.         }
  84.         else
  85.         {
  86.                 return m_targetLocation;
  87.         }
  88. }
  89.  
  90. void PathFollower::SetFinalPathLocation(const Vec3& position)
  91. {
  92.         m_stopAtFinalLocation = true;
  93.  
  94.         const PathLocation closestPathLocation = FindClosestPathLocation(*m_pCurrentPath, position);
  95.         m_finalLocation = closestPathLocation;
  96.         m_finalPosition = CalculatePathPosition(m_finalLocation);
  97.  
  98.         const float distanceToNewFinalPositionSquared = Distance::Point_PointSq(m_finalPosition, m_targetPosition);
  99.         const float pathRadiusSquared = m_params.pathRadius * m_params.pathRadius;
  100.         const bool keepCurrentPathDirection = (distanceToNewFinalPositionSquared <= pathRadiusSquared);
  101.         if (keepCurrentPathDirection)
  102.         {
  103.                 if (m_finalLocation < m_targetLocation)
  104.                 {
  105.                         m_targetLocation = m_finalLocation;
  106.                         m_targetPosition = m_finalPosition;
  107.                 }
  108.                 return;
  109.         }
  110.  
  111.         bool switchPathDirection = false;
  112.         if (m_params.loopAlongPath)
  113.         {
  114.                 const float totalPathDistance = m_pCurrentPath->GetTotalPathDistance();
  115.  
  116.                 const float distanceAlongCurrentPath = m_targetLocation.CalculateDistanceAlongPathInTheCurrentDirectionTo(*m_pCurrentPath, closestPathLocation);
  117.  
  118.                 // TODO: Replace radius with distance from entity to target? Should use projected entity location in path instead?
  119.                 const float paddedDistanceAlongCurrentPath = max(0.0f, distanceAlongCurrentPath - m_params.pathRadius);
  120.  
  121.                 const float distanceAlongReversedCurrentPath = totalPathDistance - paddedDistanceAlongCurrentPath;
  122.  
  123.                 switchPathDirection = (distanceAlongReversedCurrentPath < paddedDistanceAlongCurrentPath);
  124.         }
  125.         else
  126.         {
  127.                 // TODO: target location might not be the best here, we should use projected entity position instead likely.
  128.                 switchPathDirection = (m_finalLocation < m_targetLocation);
  129.         }
  130.  
  131.         if (switchPathDirection)
  132.         {
  133.                 const bool usingReversePath = (m_pCurrentPath == &m_reversePath);
  134.                 SetUseReversePath(!usingReversePath);
  135.         }
  136.  
  137.         m_finalPosition = CalculatePathPosition(m_finalLocation);
  138. }
  139.  
  140. void PathFollower::ResetFinalPathLocation()
  141. {
  142.         m_stopAtFinalLocation = (!m_params.loopAlongPath);
  143.  
  144.         SetUseReversePath(false);
  145.  
  146.         const size_t segmentCount = m_path.GetSegmentCount();
  147.         m_finalLocation.segmentIndex = (segmentCount == 0) ? 0 : segmentCount - 1;
  148.         m_finalLocation.normalizedSegmentPosition = 1.0f;
  149.         m_finalPosition = CalculatePathPosition(m_finalLocation);
  150. }
  151.  
  152. void PathFollower::SetDesiredSpeed(const float desiredSpeed)
  153. {
  154.         m_params.desiredSpeed = desiredSpeed;
  155. }
  156.  
  157. void PathFollower::Init(const SShape& path, const PathFollowerParams& params, const PathEntityIn& pathEntity)
  158. {
  159.         m_params = params;
  160.         m_params.lookAheadDistance = max(0.1f, m_params.lookAheadDistance);
  161.  
  162.         SetPath(path, m_params.loopAlongPath);
  163.  
  164.         CRY_ASSERT(m_pCurrentPath);
  165.  
  166.         if (m_params.startPathFromClosestLocation)
  167.         {
  168.                 const PathLocation closestPathLocation = FindClosestPathLocation(*m_pCurrentPath, pathEntity.position);
  169.                 m_targetLocation = closestPathLocation;
  170.         }
  171.         else
  172.         {
  173.                 const PathLocation startPathLocation;
  174.                 const PathLocation nearStartPathLocation = TracePathForward(*m_pCurrentPath, startPathLocation, m_params.maxStartDistanceAlongNonLoopingPath);
  175.  
  176.                 // TODO: Don't create a new path copy, have FindClosestPathLocation take ranges?
  177.                 const Path startPathSection = CreatePathSubset(*m_pCurrentPath, startPathLocation, nearStartPathLocation);
  178.                 if (startPathSection.GetSegmentCount() > 0)
  179.                 {
  180.                         const PathLocation closestPathLocation = FindClosestPathLocation(startPathSection, pathEntity.position);
  181.                         m_targetLocation = closestPathLocation;
  182.                 }
  183.                 else
  184.                 {
  185.                         m_targetLocation = PathLocation();
  186.                 }
  187.         }
  188.  
  189.         m_targetPosition = CalculatePathPosition(m_targetLocation);
  190. }
  191.  
  192. PathEntityOut PathFollower::Update(const PathEntityIn& pathEntity, const float elapsedSeconds)
  193. {
  194.         CRY_ASSERT(m_pCurrentPath);
  195.  
  196.         const PathLocation targetLocationOld = m_targetLocation;
  197.         const PathLocation lookAtLocationOld = m_lookAtLocation;
  198.  
  199.         // TODO: Arrived at path end?
  200.  
  201.         const float distanceToPathSquared = Distance::Point_PointSq(m_targetPosition, pathEntity.position);
  202.         const bool closeToTargetPosition = (distanceToPathSquared < (m_params.pathRadius * m_params.pathRadius));
  203.  
  204.         if (closeToTargetPosition)
  205.         {
  206.                 const float plannedAdvance = m_params.desiredSpeed * elapsedSeconds;
  207.                 m_targetLocation = CalculateNextPathLocation(m_targetLocation, plannedAdvance);
  208.                 if (m_stopAtFinalLocation)
  209.                 {
  210.                         const bool passedFinalLocation = (targetLocationOld <= m_finalLocation && m_finalLocation <= m_targetLocation);
  211.                         const bool loopedPastFinalLocation = (m_targetLocation <= targetLocationOld && (targetLocationOld <= m_finalLocation || m_finalLocation <= m_targetLocation));
  212.                         const bool shouldClampTargetLocation = (passedFinalLocation || loopedPastFinalLocation);
  213.                         if (shouldClampTargetLocation)
  214.                         {
  215.                                 m_targetLocation = m_finalLocation;
  216.                         }
  217.                 }
  218.                 m_targetPosition = CalculatePathPosition(m_targetLocation);
  219.         }
  220.  
  221.         m_lookAtLocation = CalculateNextPathLocation(m_targetLocation, m_params.lookAheadDistance);
  222.         m_lookAtPosition = CalculatePathPosition(m_lookAtLocation);
  223.  
  224.         PathEntityOut result;
  225.         result.speed = m_params.desiredSpeed;
  226.         result.moveDirection = m_targetPosition - pathEntity.position;
  227.  
  228.         result.moveDirection.NormalizeSafe(pathEntity.forward);
  229.         result.lookPosition = m_lookAtPosition;
  230.         result.lookDirection = m_lookAtPosition - pathEntity.position;
  231.         result.lookDirection.NormalizeSafe(pathEntity.forward);
  232.  
  233.         const float distanceToTargetPosition = (m_targetPosition - pathEntity.position).GetLength();
  234.         const float remainingDistanceAlongPathFromTarget = m_targetLocation.CalculateDistanceAlongPathTo(*m_pCurrentPath, m_finalLocation);
  235.         const float remainingDistanceApproximation = distanceToTargetPosition + remainingDistanceAlongPathFromTarget;
  236.         result.distanceToPathEnd = remainingDistanceApproximation;
  237.  
  238.         if (m_stopAtFinalLocation)
  239.         {
  240.                 if (0.0f < m_params.decelerateDistance)
  241.                 {
  242.                         if (remainingDistanceApproximation < m_params.decelerateDistance)
  243.                         {
  244.                                 result.speed *= remainingDistanceApproximation / m_params.decelerateDistance;
  245.                         }
  246.                 }
  247.         }
  248.  
  249.         return result;
  250. }
  251.  
  252. Vec3 PathFollower::CalculatePathPosition(const PathLocation& pathLocation) const
  253. {
  254.         CRY_ASSERT(m_pCurrentPath);
  255.  
  256.         if (m_params.loopAlongPath)
  257.         {
  258.                 return pathLocation.CalculatePathPositionCatmullRomLooping(*m_pCurrentPath);
  259.         }
  260.         else
  261.         {
  262.                 return pathLocation.CalculatePathPositionCatmullRom(*m_pCurrentPath);
  263.         }
  264. }
  265.  
  266. PathLocation PathFollower::CalculateNextPathLocation(const PathLocation& pathLocation, const float advance) const
  267. {
  268.         CRY_ASSERT(m_pCurrentPath);
  269.  
  270.         if (m_params.loopAlongPath)
  271.         {
  272.                 return TracePathForwardLooping(*m_pCurrentPath, pathLocation, advance);
  273.         }
  274.         else
  275.         {
  276.                 return TracePathForward(*m_pCurrentPath, pathLocation, advance);
  277.         }
  278. }
  279.  
  280. void PathFollower::Draw()
  281. {
  282.         CRY_ASSERT(m_pCurrentPath);
  283.  
  284.         const bool usingReversedPath = (m_pCurrentPath == &m_reversePath);
  285.         const ColorB pathColor = (usingReversedPath) ? Col_Yellow : Col_White;
  286.         DrawDebugPath(*m_pCurrentPath, pathColor);
  287.  
  288.         DrawDebugLocation(m_targetPosition, Col_Green);
  289.         DrawDebugLocation(m_lookAtPosition, Col_Red);
  290.         DrawDebugLocation(m_finalPosition, Col_Yellow);
  291. }
  292.  
  293. }
  294.  
downloadFlyHelpers_PathFollower.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