BVB Source Codes

CRYENGINE Show CoverSurface.cpp Source code

Return Download CRYENGINE: download CoverSurface.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 "CoverSurface.h"
  5.  
  6. #include "DebugDrawContext.h"
  7.  
  8. CoverSurface::CoverSurface()
  9.         : m_flags(0)
  10.         , m_aabb(AABB::RESET)
  11. {
  12. }
  13.  
  14. CoverSurface::CoverSurface(const ICoverSystem::SurfaceInfo& surfaceInfo)
  15. {
  16.         m_flags = surfaceInfo.flags;
  17.         m_samples.assign(surfaceInfo.samples, surfaceInfo.samples + surfaceInfo.sampleCount);
  18.  
  19.         Generate();
  20. }
  21.  
  22. void CoverSurface::Swap(CoverSurface& other)
  23. {
  24.         m_samples.swap(other.m_samples);
  25.         m_segments.swap(other.m_segments);
  26.         m_locations.swap(other.m_locations);
  27.  
  28.         std::swap(m_aabb, other.m_aabb);
  29.         std::swap(m_flags, other.m_flags);
  30. }
  31.  
  32. bool CoverSurface::IsValid() const
  33. {
  34.         return m_samples.size() > 1;
  35. }
  36.  
  37. void CoverSurface::Clear()
  38. {
  39.         m_samples.clear();
  40.         m_segments.clear();
  41.         m_aabb.Reset();
  42. }
  43.  
  44. uint32 CoverSurface::GetSampleCount() const
  45. {
  46.         return m_samples.size();
  47. }
  48.  
  49. bool CoverSurface::GetSurfaceInfo(ICoverSystem::SurfaceInfo* surfaceInfo) const
  50. {
  51.         if (m_samples.empty())
  52.                 return false;
  53.  
  54.         if (surfaceInfo)
  55.         {
  56.                 surfaceInfo->sampleCount = m_samples.size();
  57.                 if (surfaceInfo->sampleCount)
  58.                         surfaceInfo->samples = &m_samples.front();
  59.                 surfaceInfo->flags = m_flags;
  60.         }
  61.  
  62.         return true;
  63. }
  64.  
  65. uint32 CoverSurface::GetSegmentCount() const
  66. {
  67.         return m_segments.size();
  68. }
  69.  
  70. CoverSurface::Segment& CoverSurface::GetSegment(uint16 segmentIdx)
  71. {
  72.         return m_segments[segmentIdx];
  73. }
  74.  
  75. const CoverSurface::Segment& CoverSurface::GetSegment(uint16 segmentIdx) const
  76. {
  77.         return m_segments[segmentIdx];
  78. }
  79.  
  80. const AABB& CoverSurface::GetAABB() const
  81. {
  82.         return m_aabb;
  83. }
  84.  
  85. const uint32 CoverSurface::GetFlags() const
  86. {
  87.         return m_flags;
  88. }
  89.  
  90. void CoverSurface::ReserveSamples(uint32 sampleCount)
  91. {
  92.         m_samples.reserve(sampleCount);
  93. }
  94.  
  95. void CoverSurface::AddSample(const Sample& sample)
  96. {
  97.         m_samples.push_back(sample);
  98. }
  99.  
  100. void CoverSurface::Generate()
  101. {
  102.         uint32 sampleCount = m_samples.size();
  103.  
  104.         if (sampleCount < 2)
  105.                 return;
  106.  
  107.         m_segments.clear();
  108.         m_segments.reserve(sampleCount - 1);
  109.  
  110.         m_aabb = AABB(AABB::RESET);
  111.  
  112.         for (uint32 i = 0; i < sampleCount - 1; ++i)
  113.         {
  114.                 const Sample& left = m_samples[i];
  115.                 const Sample& right = m_samples[i + 1];
  116.  
  117.                 Vec3 rightToLeft = left.position - right.position;
  118.  
  119.                 Segment segment(CoverUp.Cross(rightToLeft).normalized(), rightToLeft.GetLength(), i, i + 1, 0);
  120.  
  121.                 m_aabb.Add(left.position);
  122.                 m_aabb.Add(left.position + Vec3(0.0f, 0.0f, left.GetHeight()));
  123.  
  124.                 m_aabb.Add(right.position);
  125.                 m_aabb.Add(right.position + Vec3(0.0f, 0.0f, right.GetHeight()));
  126.  
  127.                 if ((left.flags & ICoverSampler::Sample::Dynamic) && (right.flags & ICoverSampler::Sample::Dynamic))
  128.                 {
  129.                         m_flags |= ICoverSystem::SurfaceInfo::Dynamic;
  130.  
  131.                         segment.flags |= Segment::Dynamic;
  132.                 }
  133.  
  134.                 m_segments.push_back(segment);
  135.         }
  136.  
  137.         if (m_flags & ICoverSystem::SurfaceInfo::Looped)
  138.         {
  139.                 const Sample& left = m_samples.back();
  140.                 const Sample& right = m_samples.front();
  141.  
  142.                 Vec3 rightToLeft = left.position - right.position;
  143.  
  144.                 Segment segment(CoverUp.Cross(rightToLeft).normalized(), rightToLeft.GetLength(), static_cast<uint16>(m_samples.size() - 1), 0, 0);
  145.  
  146.                 if ((left.flags & ICoverSampler::Sample::Dynamic) && (right.flags & ICoverSampler::Sample::Dynamic))
  147.                 {
  148.                         m_flags |= ICoverSystem::SurfaceInfo::Dynamic;
  149.  
  150.                         segment.flags |= Segment::Dynamic;
  151.                 }
  152.  
  153.                 m_segments.push_back(segment);
  154.         }
  155.  
  156.         GenerateLocations();
  157. }
  158.  
  159. // this can later move into the file
  160. // once all the calculation are more stable
  161. void CoverSurface::GenerateLocations()
  162. {
  163.         const float MinLocationSeparation = 0.5f;
  164.         const float IntermediateLocationSeparation = 1.5f;
  165.         const float RightSnapThreshold = 0.125f;
  166.  
  167.         bool looped = (m_flags& ICoverSystem::SurfaceInfo::Looped) != 0;
  168.  
  169.         uint32 segmentCount = m_segments.size();
  170.         float spanRight = 0.0f;
  171.         float spanLeft = 0.0f;
  172.         float lastLocation = 0.0f;
  173.  
  174.         for (uint32 i = 0; i < segmentCount; ++i)
  175.         {
  176.                 uint32 segmentIdx = i;
  177.                 Segment& segment = m_segments[segmentIdx];
  178.                 Sample& left = m_samples[segment.leftIdx];
  179.                 Sample& right = m_samples[segment.rightIdx];
  180.  
  181.                 float segmentStart = spanRight;
  182.                 spanRight += segment.length;
  183.  
  184.                 uint32 segmentLocationCount = 0;
  185.  
  186.                 if (m_locations.empty())
  187.                 {
  188.                         m_locations.push_back(Location(segmentIdx, 0.0f, left.GetHeight()));
  189.                         m_locations.back().flags |= Location::LeftEdge;
  190.  
  191.                         if (spanRight < MinLocationSeparation)
  192.                                 continue;
  193.  
  194.                         ++segmentLocationCount;
  195.                 }
  196.  
  197.                 float invSegLength = 1.0f / segment.length;
  198.  
  199.                 while ((spanRight - spanLeft) >= MinLocationSeparation)
  200.                 {
  201.                         if ((segmentLocationCount < 3) ||
  202.                             ((spanLeft - lastLocation) >= IntermediateLocationSeparation) ||
  203.                             ((spanRight - spanLeft) < ((3.0f * MinLocationSeparation) + 0.015f)))
  204.                         {
  205.                                 float offset = ((spanLeft + MinLocationSeparation) - segmentStart) * invSegLength;
  206.  
  207.                                 assert((offset >= 0.0f) && (offset <= 1.0f));
  208.  
  209.                                 float leftHeight = left.GetHeight();
  210.                                 float rightHeight = right.GetHeight();
  211.  
  212.                                 float height = leftHeight + offset * (rightHeight - leftHeight);
  213.  
  214.                                 m_locations.push_back(Location(segmentIdx, offset, height));
  215.                                 lastLocation = spanLeft + MinLocationSeparation;
  216.                         }
  217.  
  218.                         spanLeft += MinLocationSeparation;
  219.  
  220.                         ++segmentLocationCount;
  221.                 }
  222.  
  223.                 bool isLast = (i == (segmentCount - 1)) && !looped;
  224.                 if (isLast)
  225.                 {
  226.                         Location& back = m_locations.back();
  227.  
  228.                         Location* last = 0;
  229.  
  230.                         float distanceSq = (GetLocation(static_cast<uint16>(m_locations.size() - 1)) - right.position).len2();
  231.                         if (distanceSq < sqr(RightSnapThreshold))
  232.                                 last = &back;
  233.                         else
  234.                         {
  235.                                 m_locations.push_back(Location());
  236.                                 last = &m_locations.back();
  237.                         }
  238.  
  239.                         last->segmentIdx = segmentIdx;
  240.                         last->SetOffset(1.0f);
  241.                         last->SetHeight(right.GetHeight());
  242.  
  243.                         if (isLast)
  244.                                 last->flags |= Location::RightEdge;
  245.                 }
  246.         }
  247. }
  248.  
  249. uint32 CoverSurface::GetLocationCount() const
  250. {
  251.         return m_locations.size();
  252. }
  253.  
  254. Vec3 CoverSurface::GetLocation(uint16 location, float offset, float* height, Vec3* normal) const
  255. {
  256.         assert(location < m_locations.size());
  257.  
  258.         if (location < m_locations.size())
  259.         {
  260.                 const Location& loc = m_locations[location];
  261.                 const Segment& segment = m_segments[loc.segmentIdx];
  262.                 const Vec3& left = m_samples[segment.leftIdx].position;
  263.                 const Vec3& right = m_samples[segment.rightIdx].position;
  264.  
  265.                 if (height)
  266.                         *height = loc.GetHeight();
  267.  
  268.                 if (normal)
  269.                         *normal = segment.normal;
  270.  
  271.                 const float tmpOffset = static_cast<float>(__fsel(offset - 0.001f, offset, 0.0f));
  272.                 return (left + loc.GetOffset() * (right - left)) + segment.normal * tmpOffset;
  273.         }
  274.  
  275.         return Vec3Constants<float>::fVec3_Zero;
  276. }
  277.  
  278. bool CoverSurface::IsPointInCover(const Vec3& eye, const Vec3& point) const
  279. {
  280.         uint32 segmentCount = m_segments.size();
  281.  
  282.         if (segmentCount < 1)
  283.                 return false;
  284.  
  285.         Vec3 observer(eye);
  286.  
  287.         for (uint32 i = 0; i < segmentCount; ++i)
  288.         {
  289.                 const Segment& segment = m_segments[i];
  290.  
  291.                 if (((segment.flags & Segment::Disabled) == 0) && IsPointBehindSegment(observer, point, segment))
  292.                         return true;
  293.         }
  294.  
  295.         return false;
  296. }
  297.  
  298. bool CoverSurface::IsCircleInCover(const Vec3& eye, const Vec3& center, float radius) const
  299. {
  300.         uint32 segmentCount = m_segments.size();
  301.  
  302.         if (segmentCount < 1)
  303.                 return false;
  304.  
  305.         Vec3 observer(eye);
  306.  
  307.         enum
  308.         {
  309.                 Left = 0,
  310.                 Center,
  311.                 Right,
  312.         };
  313.  
  314.         uint8 result = 0;
  315.  
  316.         // loop center only first for early out
  317.         for (uint32 i = 0; i < segmentCount; ++i)
  318.         {
  319.                 const Segment& segment = m_segments[i];
  320.  
  321.                 if (((segment.flags & Segment::Disabled) != 0) || !IsPointBehindSegment(observer, center, segment))
  322.                         continue;
  323.  
  324.                 result |= 1 << Center;
  325.                 break;
  326.         }
  327.  
  328.         if ((result & (1 << Center)) == 0)
  329.                 return false;
  330.  
  331.         Vec3 dirRight = (observer - center).Cross(CoverUp).normalized();
  332.         Vec3 left = center - (dirRight * radius);
  333.  
  334.         for (uint32 i = 0; i < segmentCount; ++i)
  335.         {
  336.                 const Segment& segment = m_segments[i];
  337.  
  338.                 if (((segment.flags & Segment::Disabled) != 0) || !IsPointBehindSegment(observer, left, segment))
  339.                         continue;
  340.  
  341.                 result |= 1 << Left;
  342.                 break;
  343.         }
  344.  
  345.         if ((result & (1 << Left)) == 0)
  346.                 return false;
  347.  
  348.         Vec3 right = center + (dirRight * radius);
  349.  
  350.         for (uint32 i = 0; i < segmentCount; ++i)
  351.         {
  352.                 const Segment& segment = m_segments[i];
  353.  
  354.                 if (((segment.flags & Segment::Disabled) != 0) || !IsPointBehindSegment(observer, right, segment))
  355.                         continue;
  356.  
  357.                 result |= 1 << Right;
  358.                 break;
  359.         }
  360.  
  361.         return ((result & (1 << Right)) != 0);
  362. }
  363.  
  364. bool CoverSurface::GetCoverOcclusionAt(const Vec3& eye, const Vec3& point, float* heightSq) const
  365. {
  366.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  367.  
  368.         uint32 segmentCount = m_segments.size();
  369.  
  370.         if (segmentCount < 1)
  371.                 return false;
  372.  
  373.         Vec3 observer(eye);
  374.  
  375.         for (uint32 i = 0; i < segmentCount; ++i)
  376.         {
  377.                 const Segment& segment = m_segments[i];
  378.  
  379.                 if (((segment.flags & Segment::Disabled) == 0) && GetOcclusionBehindSegment(observer, point, segment, heightSq))
  380.                         return true;
  381.         }
  382.  
  383.         return false;
  384. }
  385.  
  386. bool CoverSurface::GetCoverOcclusionAt(const Vec3& eye, const Vec3& center, float radius, float* heightSq) const
  387. {
  388.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  389.  
  390.         uint32 segmentCount = m_segments.size();
  391.  
  392.         if (segmentCount < 1)
  393.                 return false;
  394.  
  395.         Vec3 observer(eye);
  396.  
  397.         enum
  398.         {
  399.                 Left = 0,
  400.                 Center,
  401.                 Right,
  402.         };
  403.  
  404.         float heightSqArr[3];
  405.         uint8 result = 0;
  406.  
  407.         // If we store the index we continue to the last one
  408.         // evaluated instead of re-iterating through segments
  409.         // that were previously excluded
  410.         uint32 segmentIndex = 0;
  411.  
  412.         Vec3 dirRight = (observer - center).Cross(CoverUp).normalized();
  413.         Vec3 left = center - (dirRight * radius);
  414.  
  415.         for (; segmentIndex < segmentCount; ++segmentIndex)
  416.         {
  417.                 const Segment& segment = m_segments[segmentIndex];
  418.  
  419.                 if (((segment.flags & Segment::Disabled) != 0) || !GetOcclusionBehindSegment(observer, left, segment, &heightSqArr[Left]))
  420.                         continue;
  421.  
  422.                 result |= 1 << Left;
  423.                 break;
  424.         }
  425.  
  426.         if ((result & (1 << Left)) == 0)
  427.                 return false;
  428.  
  429.         for (; segmentIndex < segmentCount; ++segmentIndex)
  430.         {
  431.                 const Segment& segment = m_segments[segmentIndex];
  432.  
  433.                 if (((segment.flags & Segment::Disabled) != 0) || !GetOcclusionBehindSegment(observer, center, segment, &heightSqArr[Center]))
  434.                         continue;
  435.  
  436.                 result |= 1 << Center;
  437.                 break;
  438.         }
  439.  
  440.         if ((result & (1 << Center)) == 0)
  441.                 return false;
  442.  
  443.         Vec3 right = center + (dirRight * radius);
  444.  
  445.         for (; segmentIndex < segmentCount; ++segmentIndex)
  446.         {
  447.                 const Segment& segment = m_segments[segmentIndex];
  448.  
  449.                 if (((segment.flags & Segment::Disabled) != 0) || !GetOcclusionBehindSegment(observer, right, segment, &heightSqArr[Right]))
  450.                         continue;
  451.  
  452.                 result |= 1 << Right;
  453.                 break;
  454.         }
  455.  
  456.         if ((result & (1 << Right)) != 0)
  457.         {
  458.                 uint32 lowest = (heightSqArr[Left] < heightSqArr[Right]) ?
  459.                                 ((heightSqArr[Left] < heightSqArr[Center]) ? Left : Center) :
  460.                                 ((heightSqArr[Right] < heightSqArr[Center]) ? Right : Center);
  461.  
  462.                 *heightSq = heightSqArr[lowest];
  463.  
  464.                 return true;
  465.         }
  466.  
  467.         return false;
  468. }
  469.  
  470. bool CoverSurface::GenerateCoverPath(float distanceToCover, CoverPath* path, bool skipSimplify) const
  471. {
  472.         uint32 segmentCount = m_segments.size();
  473.  
  474.         if (segmentCount < 1)
  475.                 return false;
  476.  
  477.         if (segmentCount == 1)
  478.         {
  479.                 const Segment& segment = m_segments[0];
  480.  
  481.                 Vec3 extrusion = segment.normal * distanceToCover;
  482.  
  483.                 Vec3 left = m_samples[segment.leftIdx].position + extrusion;
  484.                 Vec3 right = m_samples[segment.rightIdx].position + extrusion;
  485.  
  486.                 path->AddPoint(left);
  487.                 path->AddPoint(right);
  488.  
  489.                 return true;
  490.         }
  491.  
  492.         Points points;
  493.  
  494.         const float ExtraPointMinAngleCos = cos_tpl(DEG2RAD(20.0f));
  495.  
  496.         const Segment& firstSegment = m_segments[0];
  497.         Vec3 extrusionLeft = firstSegment.normal * distanceToCover;
  498.         points.push_back(m_samples[firstSegment.leftIdx].position + extrusionLeft);
  499.  
  500.         for (uint32 i = 1; i < segmentCount; ++i)
  501.         {
  502.                 const Segment& prevSegment = m_segments[i - 1];
  503.                 const Segment& segment = m_segments[i];
  504.  
  505.                 const float crossProduct = prevSegment.normal.Cross(segment.normal).z;
  506.                 if (fabsf(crossProduct) > FLT_EPSILON)
  507.                 {
  508.                         Vec3 prevExtrusion = prevSegment.normal * distanceToCover;
  509.                         points.push_back(m_samples[prevSegment.rightIdx].position + prevExtrusion);
  510.  
  511.                         Vec3 currentExtrusion = segment.normal * distanceToCover;
  512.  
  513.                         float angleCos = prevSegment.normal.Dot(segment.normal);
  514.                         if ((angleCos <= ExtraPointMinAngleCos) && ((prevExtrusion - currentExtrusion).len2() > sqr(0.35f)))
  515.                         {
  516.                                 Vec3 normalAvg = ((prevSegment.normal + segment.normal) * 0.5f).normalized();
  517.  
  518.                                 float thetaCos = prevSegment.normal.Dot(normalAvg);
  519.                                 if (thetaCos < 0.01f)
  520.                                         thetaCos = 0.5f;
  521.  
  522.                                 float extrusionOffset = distanceToCover / thetaCos;
  523.  
  524.                                 points.push_back(m_samples[segment.leftIdx].position + (normalAvg * extrusionOffset));
  525.                         }
  526.  
  527.                         if (crossProduct > 0.0f)
  528.                         {
  529.                                 points.push_back(m_samples[segment.leftIdx].position + currentExtrusion);
  530.                         }
  531.                 }
  532.         }
  533.  
  534.         const Segment& lastSegment = m_segments[segmentCount - 1];
  535.         Vec3 extrusionRight = lastSegment.normal * distanceToCover;
  536.         points.push_back(m_samples[lastSegment.rightIdx].position + extrusionRight);
  537.  
  538.         if (!skipSimplify)
  539.                 SimplifyCoverPath(points);
  540.  
  541.         Points::const_iterator it = points.begin();
  542.         Points::const_iterator itEnd = points.end();
  543.  
  544.         bool looped = m_flags & ICoverSystem::SurfaceInfo::Looped;
  545.         path->Reserve(looped ? (points.size() + 1) : points.size());
  546.  
  547.         for (; it != itEnd; ++it)
  548.                 path->AddPoint(*it);
  549.  
  550.         if (looped)
  551.         {
  552.                 path->AddPoint(points.front());
  553.                 path->SetFlags(path->GetFlags() | CoverPath::Looped);
  554.         }
  555.  
  556.         return true;
  557. }
  558.  
  559. CoverSurface::Points CoverSurface::s_simplifiedPoints;
  560.  
  561. void CoverSurface::SimplifyCoverPath(Points& points) const
  562. {
  563.         uint32 pointCount = points.size();
  564.         if (pointCount < 3)
  565.                 return;
  566.  
  567.         s_simplifiedPoints.reserve(pointCount);
  568.         s_simplifiedPoints.clear();
  569.  
  570.         Points::iterator rightIt = points.begin();
  571.         Points::iterator leftIt = rightIt++;
  572.         Points::iterator midIt = rightIt++;
  573.  
  574.         s_simplifiedPoints.push_back(*leftIt);
  575.  
  576.         for (; rightIt != points.end(); )
  577.         {
  578.                 const Vec3& left = *leftIt;
  579.                 const Vec3& mid = *midIt;
  580.                 const Vec3& right = *rightIt;
  581.  
  582.                 float t;
  583.                 Lineseg line(left, right);
  584.  
  585.                 if (Distance::Point_LinesegSq(mid, line, t) < sqr(0.015f))
  586.                 {
  587.                         midIt = rightIt++;
  588.                         continue;
  589.                 }
  590.  
  591.                 s_simplifiedPoints.push_back(*midIt);
  592.  
  593.                 leftIt = midIt;
  594.                 midIt = rightIt++;
  595.         }
  596.  
  597.         s_simplifiedPoints.push_back(*midIt);
  598.  
  599.         s_simplifiedPoints.swap(points);
  600. }
  601.  
  602. bool CoverSurface::CalculatePathCoverage(const Vec3& eye, const CoverPath& coverPath,
  603.                                          CoverInterval* interval) const
  604. {
  605.         const CoverPath::Points& pathPoints = coverPath.GetPoints();
  606.  
  607.         const uint32 pathPointCount = pathPoints.size();
  608.  
  609.         if (pathPointCount < 2)
  610.                 return false;
  611.  
  612.         Plane leftPlane;
  613.         Plane rightPlane;
  614.  
  615.         Vec3 eyeLoc = eye;
  616.         eyeLoc.z = 0.0f;
  617.  
  618.         FindCoverPlanes(eyeLoc, leftPlane, rightPlane);
  619.  
  620.         if (gAIEnv.CVars.DebugDrawCoverPlanes != 0)
  621.         {
  622.                 CDebugDrawContext dc;
  623.  
  624.                 Vec3 leftFwd = leftPlane.n.Cross(Vec3Constants<float>::fVec3_OneZ).normalized();
  625.                 Vec3 rightFwd = rightPlane.n.Cross(Vec3Constants<float>::fVec3_OneZ).normalized();
  626.  
  627.                 dc->DrawLine(eye - leftFwd * 50.0f, Col_MediumSeaGreen, eye + leftFwd * 50.0f, Col_MediumSeaGreen, 10.0f);
  628.                 dc->DrawLine(eye - leftFwd * 2.0f, Col_MediumSeaGreen, eye - leftFwd * 2.0f + leftPlane.n * 0.5f, Col_MediumSeaGreen, 5.0f);
  629.                 dc->DrawLine(eye + leftFwd * 2.0f, Col_MediumSeaGreen, eye + leftFwd * 2.0f + leftPlane.n * 0.5f, Col_MediumSeaGreen, 5.0f);
  630.                 dc->DrawLine(eye - rightFwd * 50.0f, Col_Orange, eye + rightFwd * 50.0f, Col_Orange, 10.0f);
  631.                 dc->DrawLine(eye - rightFwd * 2.0f, Col_Orange, eye - rightFwd * 2.0f + rightPlane.n * 0.5f, Col_Orange, 5.0f);
  632.                 dc->DrawLine(eye + rightFwd * 2.0f, Col_Orange, eye + rightFwd * 2.0f + rightPlane.n * 0.5f, Col_Orange, 5.0f);
  633.         }
  634.  
  635.         float leftCoverage = -1.0f;
  636.         float leftClosestSq = FLT_MAX;
  637.  
  638.         float rightCoverage = -1.0f;
  639.         float rightClosestSq = FLT_MAX;
  640.  
  641.         for (uint32 i = 0; i < (pathPointCount - 1); ++i)
  642.         {
  643.                 const CoverPath::Point& leftPoint = pathPoints[i];
  644.                 const CoverPath::Point& rightPoint = pathPoints[i + 1];
  645.  
  646.                 float t;
  647.                 Vec3 point;
  648.  
  649.                 Vec3 dir = leftPoint.position - rightPoint.position;
  650.                 dir.z = 0.0f;
  651.  
  652.                 Vec3 left = leftPoint.position;
  653.                 Vec3 right = rightPoint.position;
  654.  
  655.                 if (IntersectCoverPlane(right, dir, leftPlane, &point, &t))
  656.                 {
  657.                         float distSq = (eyeLoc - point).len2();
  658.                         if (distSq < leftClosestSq)
  659.                         {
  660.                                 leftClosestSq = distSq;
  661.                                 leftCoverage = rightPoint.distance - (dir.len() * t);
  662.                         }
  663.                 }
  664.  
  665.                 if (IntersectCoverPlane(left, -dir, rightPlane, &point, &t))
  666.                 {
  667.                         float distSq = (eyeLoc - point).len2();
  668.                         if (distSq < rightClosestSq)
  669.                         {
  670.                                 rightClosestSq = distSq;
  671.                                 rightCoverage = leftPoint.distance + (dir.len() * t);
  672.                         }
  673.                 }
  674.         }
  675.  
  676.         if (m_flags & ICoverSystem::SurfaceInfo::Looped)
  677.         {
  678.                 if ((leftCoverage < 0.0f) || (rightCoverage < 0.0f))
  679.                         return false;
  680.  
  681.                 if (leftCoverage > rightCoverage)
  682.                         rightCoverage += coverPath.GetLength();
  683.         }
  684.         else
  685.         {
  686.                 if ((leftCoverage < 0.0f) && (rightCoverage > 0.0f))
  687.                         leftCoverage = 0.0f;
  688.                 else if ((rightCoverage < 0.0f) && (leftCoverage > 0.0f))
  689.                         rightCoverage = coverPath.GetLength();
  690.         }
  691.  
  692.         *interval = CoverInterval(leftCoverage, rightCoverage);
  693.  
  694.         return true;
  695. }
  696.  
  697. bool CoverSurface::IntersectCoverPlane(const Vec3& origin, const Vec3& length, const Plane& plane, Vec3* point, float* t) const
  698. {
  699.         float planeNormalDotSegment = plane.n | length;
  700.  
  701.         if ((planeNormalDotSegment == 0.0f) || (planeNormalDotSegment > 0.0f))
  702.                 return false;
  703.  
  704.         float distanceToStart = plane.DistFromPlane(origin);
  705.         float scale = -distanceToStart / planeNormalDotSegment;
  706.  
  707.         if ((scale < 0.0f) || (scale > 1.0f))
  708.                 return false;
  709.  
  710.         *point = origin + length * scale;
  711.         *t = scale;
  712.  
  713.         return true;
  714. }
  715.  
  716. void CoverSurface::FindCoverPlanes(const Vec3& eye, Plane& left, Plane& right) const
  717. {
  718.         const uint32 coverSampleCount = m_samples.size();
  719.  
  720.         if (coverSampleCount < 2)
  721.                 return;
  722.  
  723.         Vec3 leftToEye = eye - m_samples[m_segments.front().leftIdx].position;
  724.         leftToEye.z = 0.0f;
  725.         Vec3 leftNormal = leftToEye.Cross(CoverUp).normalized();
  726.         left.SetPlane(leftNormal, eye);
  727.  
  728.         Vec3 rightToEye = eye - m_samples[m_segments.back().rightIdx].position;
  729.         rightToEye.z = 0.0f;
  730.         Vec3 rightNormal = CoverUp.Cross(rightToEye).normalized();
  731.         right.SetPlane(rightNormal, eye);
  732.  
  733.         for (uint32 i = 1; i < coverSampleCount - 1; ++i)
  734.         {
  735.                 const Sample& sample = m_samples[i];
  736.  
  737.                 if (left.DistFromPlane(sample.position) < 0.0f)
  738.                 {
  739.                         leftToEye = eye - sample.position;
  740.                         leftToEye.z = 0.0f;
  741.                         leftNormal = leftToEye.Cross(CoverUp).normalized();
  742.                         left.SetPlane(leftNormal, eye);
  743.                 }
  744.                 else if (right.DistFromPlane(sample.position) < 0.0f)
  745.                 {
  746.                         rightToEye = eye - sample.position;
  747.                         rightToEye.z = 0.0f;
  748.                         rightNormal = CoverUp.Cross(rightToEye).normalized();
  749.                         right.SetPlane(rightNormal, eye);
  750.                 }
  751.         }
  752. }
  753.  
  754. void CoverSurface::DebugDraw() const
  755. {
  756.         uint32 coverSampleCount = m_samples.size();
  757.         uint32 segmentCount = m_segments.size();
  758.  
  759.         if (coverSampleCount < 2)
  760.                 return;
  761.  
  762.         static std::vector<Vec3> coverSurface;
  763.         coverSurface.resize(2 * coverSampleCount * 6);
  764.  
  765.         const float offset = -0.05f;
  766.         const float floorOffset = 0.005f;
  767.  
  768.         bool looped = (m_flags& ICoverSystem::SurfaceInfo::Looped) != 0;
  769.  
  770.         CDebugDrawContext dc;
  771.         dc->SetBackFaceCulling(false);
  772.         dc->SetDepthWrite(false);
  773.  
  774.         // Low Cover
  775.         uint32 k = 0;
  776.         bool wasDynamic = false;
  777.         for (uint32 i = 0; i < segmentCount; ++i)
  778.         {
  779.                 const Segment& segment = m_segments[i];
  780.  
  781.                 if (segment.flags & Segment::Disabled)
  782.                         continue;
  783.  
  784.                 const Sample& left = m_samples[segment.leftIdx];
  785.                 const Sample& right = m_samples[segment.rightIdx];
  786.  
  787.                 bool isDynamic = (left.flags & ICoverSampler::Sample::Dynamic) && (right.flags & ICoverSampler::Sample::Dynamic);
  788.  
  789.                 if (isDynamic != wasDynamic)
  790.                 {
  791.                         if (k > 0)
  792.                         {
  793.                                 ColorB color(wasDynamic ? Col_Yellow : Col_DarkGreen);
  794.                                 color.a = 128;
  795.  
  796.                                 dc->DrawTriangles(&coverSurface[0], k * 6, color);
  797.                                 k = 0;
  798.                         }
  799.  
  800.                         wasDynamic = isDynamic;
  801.                 }
  802.  
  803.                 Vec3 leftNormal = (i > 0) ?
  804.                                   (segment.normal + m_segments[i - 1].normal).normalized() : segment.normal;
  805.                 Vec3 rightNormal = (i < segmentCount - 1) ?
  806.                                    (segment.normal + m_segments[i + 1].normal).normalized() : segment.normal;
  807.  
  808.                 Vec3 bottomLeft(left.position - (leftNormal * offset));
  809.                 Vec3 bottomRight(right.position - (rightNormal * offset));
  810.  
  811.                 coverSurface[k * 6 + 0] = bottomLeft;
  812.                 coverSurface[k * 6 + 1] = bottomRight + Vec3(0.0f, 0.0f, min(right.GetHeight(), LowCoverMaxHeight));
  813.                 coverSurface[k * 6 + 2] = bottomRight;
  814.                 coverSurface[k * 6 + 3] = bottomLeft;
  815.                 coverSurface[k * 6 + 4] = bottomLeft + Vec3(0.0f, 0.0f, min(left.GetHeight(), LowCoverMaxHeight));
  816.                 coverSurface[k * 6 + 5] = bottomRight + Vec3(0.0f, 0.0f, min(right.GetHeight(), LowCoverMaxHeight));
  817.  
  818.                 ++k;
  819.         }
  820.  
  821.         if (k > 0)
  822.         {
  823.                 ColorB color(wasDynamic ? Col_Yellow : Col_DarkGreen);
  824.                 color.a = 128;
  825.  
  826.                 dc->DrawTriangles(&coverSurface[0], k * 6, color);
  827.         }
  828.  
  829.         if (looped)
  830.         {
  831.                 ColorB color(Col_SlateBlue);
  832.                 color.a = 128;
  833.  
  834.                 dc->DrawTriangles(&coverSurface[(segmentCount - 1) * 6], 6, color);
  835.         }
  836.  
  837.         // High Cover
  838.         k = 0;
  839.         wasDynamic = false;
  840.         for (uint32 i = 0; i < segmentCount; ++i)
  841.         {
  842.                 const Segment& segment = m_segments[i];
  843.  
  844.                 if (segment.flags & Segment::Disabled)
  845.                         continue;
  846.  
  847.                 const Sample& left = m_samples[segment.leftIdx];
  848.                 const Sample& right = m_samples[segment.rightIdx];
  849.  
  850.                 bool isDynamic = (left.flags & ICoverSampler::Sample::Dynamic) && (right.flags & ICoverSampler::Sample::Dynamic);
  851.  
  852.                 if (isDynamic != wasDynamic)
  853.                 {
  854.                         if (k > 0)
  855.                         {
  856.                                 ColorB color(wasDynamic ? Col_YellowGreen : Col_MediumSeaGreen);
  857.                                 color.a = 128;
  858.  
  859.                                 dc->DrawTriangles(&coverSurface[0], k * 6, color);
  860.                                 k = 0;
  861.                         }
  862.  
  863.                         wasDynamic = isDynamic;
  864.                 }
  865.  
  866.                 if ((left.GetHeight() <= LowCoverMaxHeight) && (right.GetHeight() <= LowCoverMaxHeight))
  867.                         continue;
  868.  
  869.                 Vec3 leftNormal = (i > 0) ?
  870.                                   (segment.normal + m_segments[i - 1].normal).normalized() : segment.normal;
  871.                 Vec3 rightNormal = (i < segmentCount - 1) ?
  872.                                    (segment.normal + m_segments[i + 1].normal).normalized() : segment.normal;
  873.  
  874.                 Vec3 bottomLeft(left.position - (leftNormal * offset));
  875.                 bottomLeft += Vec3(0.0f, 0.0f, min(left.GetHeight(), LowCoverMaxHeight));
  876.                 Vec3 bottomRight(right.position - (rightNormal * offset));
  877.                 bottomRight += Vec3(0.0f, 0.0f, min(right.GetHeight(), LowCoverMaxHeight));
  878.  
  879.                 coverSurface[k * 6 + 0] = bottomLeft;
  880.                 coverSurface[k * 6 + 1] = bottomRight + Vec3(0.0f, 0.0f, max(right.GetHeight() - LowCoverMaxHeight, 0.0f));
  881.                 coverSurface[k * 6 + 2] = bottomRight;
  882.                 coverSurface[k * 6 + 3] = bottomLeft;
  883.                 coverSurface[k * 6 + 4] = bottomLeft + Vec3(0.0f, 0.0f, max(left.GetHeight() - LowCoverMaxHeight, 0.0f));
  884.                 coverSurface[k * 6 + 5] = bottomRight + Vec3(0.0f, 0.0f, max(right.GetHeight() - LowCoverMaxHeight, 0.0f));
  885.  
  886.                 ++k;
  887.         }
  888.  
  889.         if (k > 0)
  890.         {
  891.                 {
  892.                         ColorB color(wasDynamic ? Col_YellowGreen : Col_MediumSeaGreen);
  893.                         color.a = 128;
  894.  
  895.                         uint32 drawCount = looped ? k - 1 : k;
  896.                         dc->DrawTriangles(&coverSurface[0], drawCount * 6, color);
  897.                 }
  898.  
  899.                 if (looped)
  900.                 {
  901.                         ColorB color(Col_SteelBlue);
  902.                         color.a = 128;
  903.  
  904.                         dc->DrawTriangles(&coverSurface[(k - 1) * 6], 6, color);
  905.                 }
  906.         }
  907.  
  908.         // Segments
  909.         for (uint32 i = 0; i < segmentCount; ++i)
  910.         {
  911.                 const Segment& segment = m_segments[i];
  912.  
  913.                 Vec3 leftNormal = (i > 0) ?
  914.                                   (0.5f * (segment.normal + m_segments[i - 1].normal)) : segment.normal;
  915.                 Vec3 rightNormal = (i < segmentCount - 1) ?
  916.                                    (0.5f * (segment.normal + m_segments[i + 1].normal)) : segment.normal;
  917.  
  918.                 const Vec3& left = m_samples[segment.leftIdx].position - (leftNormal * offset) + (CoverUp * floorOffset);
  919.                 const Vec3& right = m_samples[segment.rightIdx].position - (rightNormal * offset) + (CoverUp * floorOffset);
  920.  
  921.                 Vec3 segmentCenter = (left + right) * 0.5f;
  922.  
  923.                 bool loopSegment = looped && (i == (segmentCount - 1));
  924.  
  925.                 dc->DrawLine(left, loopSegment ? Col_SlateBlue : Col_DarkWood, right, loopSegment ? Col_SlateBlue : Col_DarkWood, 10.0f);
  926.                 dc->DrawLine(segmentCenter, loopSegment ? Col_SlateBlue : Col_Goldenrod, segmentCenter + segment.normal * 0.15f,
  927.                              loopSegment ? Col_SlateBlue : Col_Goldenrod);
  928.                 dc->DrawCone(segmentCenter + segment.normal * 0.15f, segment.normal, 0.025f, 0.05f,
  929.                              loopSegment ? Col_SlateBlue : Col_Goldenrod);
  930.         }
  931.  
  932.         // Samples
  933.         {
  934.                 for (uint32 i = 0; i < segmentCount; ++i)
  935.                 {
  936.                         const Segment& segment = m_segments[i];
  937.  
  938.                         Vec3 leftNormal = (i > 0) ?
  939.                                           (0.5f * (segment.normal + m_segments[i - 1].normal)) : segment.normal;
  940.  
  941.                         dc->DrawSphere(m_samples[segment.leftIdx].position - (leftNormal * offset) + (CoverUp * floorOffset),
  942.                                        0.035f, ColorB(Col_FireBrick), true);
  943.                 }
  944.  
  945.                 // Last Sample
  946.                 const Segment& segment = m_segments[segmentCount - 1];
  947.                 Vec3 rightNormal = segment.normal;
  948.                 dc->DrawSphere(m_samples[segment.rightIdx].position - (rightNormal * offset) + (CoverUp * floorOffset),
  949.                                0.035f, ColorB(Col_FireBrick), true);
  950.         }
  951.  
  952.         // Locations
  953.         if (gAIEnv.CVars.DebugDrawCoverLocations)
  954.         {
  955.                 uint32 locationCount = m_locations.size();
  956.                 for (uint32 i = 0; i < locationCount; ++i)
  957.                 {
  958.                         const Location& location = m_locations[i];
  959.  
  960.                         Vec3 pos = GetLocation(i, 0.5f);
  961.  
  962.                         const float height = 0.05f;
  963.                         dc->DrawCylinder(pos + CoverUp * height * 0.5f, CoverUp, 0.45f, height, ColorB(Col_Tan, 0.35f));
  964.                 }
  965.         }
  966. }
  967.  
downloadCoverSurface.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