BVB Source Codes

CRYENGINE Show Shape2.cpp Source code

Return Download CRYENGINE: download Shape2.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 "Shape2.h"
  5.  
  6. static bool useForbiddenMask = false;
  7. static unsigned forbiddenMaskMaxDimension = 256; // max side of the mask (256->16KB)
  8. static float forbiddenMaskGranularity = 2.0f;
  9. static float criticalForbiddenSize = 30.0f;
  10.  
  11. //===================================================================
  12. // CShapeMask
  13. //===================================================================
  14. CShapeMask::CShapeMask() : m_nx(0), m_ny(0), m_dx(0), m_dy(0), m_bytesPerRow(0)
  15. {
  16. }
  17.  
  18. //===================================================================
  19. // CShapeMask
  20. //===================================================================
  21. CShapeMask::~CShapeMask()
  22. {
  23. }
  24.  
  25. //===================================================================
  26. // Build
  27. //===================================================================
  28. void CShapeMask::Build(const struct SShape* pShape, float granularity)
  29. {
  30.         AIAssert(pShape);
  31.         AIAssert(granularity > 0.0f);
  32.         m_aabb = pShape->aabb;
  33.         Vec3 delta = m_aabb.max - m_aabb.min;
  34.         m_nx = 1 + (unsigned)(delta.x / granularity);
  35.         m_ny = 1 + (unsigned)(delta.y / granularity);
  36.  
  37.         if (m_nx > forbiddenMaskMaxDimension)
  38.                 m_nx = forbiddenMaskMaxDimension;
  39.         if (m_ny > forbiddenMaskMaxDimension)
  40.                 m_ny = forbiddenMaskMaxDimension;
  41.  
  42.         m_dx = delta.x / m_nx;
  43.         m_dy = delta.y / m_ny;
  44.  
  45.         m_bytesPerRow = (m_nx + 3) >> 2;
  46.  
  47.         m_container.resize(m_ny * m_bytesPerRow);
  48.  
  49.         for (unsigned j = 0; j != m_ny; ++j)
  50.         {
  51.                 for (unsigned i = 0; i != m_nx; ++i)
  52.                 {
  53.                         unsigned index = (i >> 2) + m_bytesPerRow * j;
  54.                         assert(index < m_container.size());
  55.                         unsigned char& byte = m_container[index];
  56.  
  57.                         unsigned offset = (i & 3) * 2;
  58.  
  59.                         Vec3 min, max;
  60.                         GetBox(min, max, i, j);
  61.  
  62.                         unsigned char value = GetType(pShape, min, max) << offset;
  63.                         unsigned char mask = 3 << offset;
  64.                         byte = (byte & ~mask) + value;
  65.                 }
  66.         }
  67. }
  68.  
  69. //===================================================================
  70. // GetType
  71. //===================================================================
  72. CShapeMask::EType CShapeMask::GetType(const Vec3 pt) const
  73. {
  74.         if (!useForbiddenMask)
  75.                 return TYPE_EDGE;
  76.         int i = (int) ((pt.x - m_aabb.min.x) / m_dx);
  77.         if (i < 0 || i >= (int)m_nx)
  78.                 return TYPE_OUT;
  79.         int j = (int) ((pt.x - m_aabb.min.y) / m_dx);
  80.         if (j < 0 || j >= (int)m_ny)
  81.                 return TYPE_OUT;
  82.  
  83.         unsigned index = (i >> 2) + m_bytesPerRow * j;
  84.         assert(index < m_container.size());
  85.         const unsigned char& byte = m_container[index];
  86.  
  87.         unsigned offset = (i & 2) * 2;
  88.         unsigned char mask = 3 << offset;
  89.  
  90.         unsigned char value = byte & mask;
  91.         value = value >> offset;
  92.         return (EType) value;
  93. }
  94.  
  95. //===================================================================
  96. // MemStats
  97. //===================================================================
  98. size_t CShapeMask::MemStats() const
  99. {
  100.         size_t size = sizeof(*this);
  101.         size += m_container.capacity() * sizeof(unsigned char);
  102.         return size;
  103. }
  104.  
  105. //===================================================================
  106. // GetType
  107. //===================================================================
  108. CShapeMask::EType CShapeMask::GetType(const struct SShape* pShape, const Vec3& min, const Vec3& max) const
  109. {
  110.         Vec3 delta = max - min;
  111.         if (Overlap::Lineseg_Polygon2D(Lineseg(min, min + Vec3(delta.x, 0.0f, 0.0f)), pShape->shape, &pShape->aabb))
  112.                 return TYPE_EDGE;
  113.         if (Overlap::Lineseg_Polygon2D(Lineseg(min + Vec3(0.0f, delta.y, 0.0f), min + Vec3(delta.x, delta.y, 0.0f)), pShape->shape, &pShape->aabb))
  114.                 return TYPE_EDGE;
  115.         if (Overlap::Lineseg_Polygon2D(Lineseg(min, min + Vec3(0.0f, delta.y, 0.0f)), pShape->shape, &pShape->aabb))
  116.                 return TYPE_EDGE;
  117.         if (Overlap::Lineseg_Polygon2D(Lineseg(min + Vec3(delta.x, 0.0f, 0.0f), min + Vec3(delta.x, delta.y, 0.0f)), pShape->shape, &pShape->aabb))
  118.                 return TYPE_EDGE;
  119.  
  120.         Vec3 mid = 0.5f * (min + max);
  121.         if (Overlap::Point_Polygon2D(mid, pShape->shape, &pShape->aabb))
  122.                 return TYPE_IN;
  123.         else
  124.                 return TYPE_OUT;
  125. }
  126.  
  127. //===================================================================
  128. // GetBox
  129. //===================================================================
  130. void CShapeMask::GetBox(Vec3& min, Vec3& max, int i, int j)
  131. {
  132.         min = m_aabb.min + Vec3(i * m_dx, j * m_dy, 0.0f);
  133.         max = min + Vec3(m_dx, m_dy, 0.0f);
  134. }
  135.  
  136. //===================================================================
  137. // SShape
  138. //===================================================================
  139. SShape::SShape(const ListPositions& shape_, bool allowMask, IAISystem::ENavigationType navType_, int type_,
  140.                bool closed_, float height_, EAILightLevel lightLevel_, bool temp) :
  141.         shape(shape_), navType(navType_), type(type_), devalueTime(0), height(height_),
  142.         temporary(temp), enabled(true), shapeMask(0), lightLevel(lightLevel_), closed(closed_)
  143. {
  144.         RecalcAABB();
  145.         if (allowMask)
  146.                 BuildMask(forbiddenMaskGranularity);
  147. }
  148.  
  149. SShape::SShape() : navType(IAISystem::NAV_UNSET)
  150.         , type(0)
  151.         , devalueTime(0.0f)
  152.         , height(0.0f)
  153.         , temporary(false)
  154.         , aabb(AABB::RESET)
  155.         , enabled(true)
  156.         , shapeMask(0)
  157.         , lightLevel(AILL_NONE)
  158.         , closed(false)
  159. {
  160.  
  161. }
  162.  
  163. SShape::SShape(const ListPositions& shape_, const AABB& aabb_, IAISystem::ENavigationType navType /*= IAISystem::NAV_UNSET */,
  164.                int type /*= 0 */, bool closed_ /*= false */, float height_ /*= 0.0f */, EAILightLevel lightLevel_ /*= AILL_NONE */,
  165.                bool temp /*= false */)
  166.         : shape(shape_)
  167.         , aabb(aabb_)
  168.         , navType(IAISystem::NAV_UNSET)
  169.         , type(0)
  170.         , devalueTime(0)
  171.         , height(height_)
  172.         , temporary(temp)
  173.         , enabled(true)
  174.         , shapeMask(0)
  175.         , lightLevel(lightLevel_)
  176.         , closed(closed_)
  177. {
  178.  
  179. }
  180. //===================================================================
  181. // BuildMask
  182. //===================================================================
  183. void SShape::BuildMask(float granularity)
  184. {
  185.         Vec3 delta = aabb.max - aabb.min;
  186.         if (useForbiddenMask && (delta.x > criticalForbiddenSize || delta.y > criticalForbiddenSize))
  187.         {
  188.                 if (!shapeMask)
  189.                         shapeMask = new CShapeMask;
  190.                 shapeMask->Build(this, forbiddenMaskGranularity);
  191.         }
  192.         else
  193.         {
  194.                 ReleaseMask();
  195.         }
  196. }
  197.  
  198. SShape::~SShape()
  199. {
  200.         ReleaseMask();
  201. }
  202.  
  203. void SShape::RecalcAABB()
  204. {
  205.         aabb.Reset();
  206.         aabb.min.z = 10000.0f;  // avoid including limit
  207.         aabb.max.z = -10000.0f;
  208.         for (ListPositions::const_iterator it = shape.begin(); it != shape.end(); ++it)
  209.                 aabb.Add(*it);
  210. }
  211.  
  212. void SShape::ReleaseMask()
  213. {
  214.         delete shapeMask;
  215.         shapeMask = 0;
  216. }
  217.  
  218. //
  219. // offsets this shape(called when segmented world shifts)
  220. void SShape::OffsetShape(const Vec3& offset)
  221. {
  222.         for (ListPositions::iterator it = shape.begin(); it != shape.end(); ++it)
  223.         {
  224.                 (*it) += offset;
  225.         }
  226.         aabb.Move(offset);
  227. }
  228.  
  229. ListPositions::const_iterator SShape::NearestPointOnPath(const Vec3& pos, bool forceLoop, float& dist, Vec3& nearestPt,
  230.                                                          float* distAlongPath /*= 0*/, Vec3* segmentDir /*= 0*/,
  231.                                                          uint32* segmentStartIndex, float* pathLength, float* segmentFraction) const
  232. {
  233.         if (shape.empty())
  234.                 return shape.end();
  235.  
  236.         dist = FLT_MAX;
  237.  
  238.         size_t nearest = 0;
  239.         size_t cur = 0;
  240.         size_t next = 1;
  241.         size_t size = shape.size();
  242.         size_t loopEnd = size;
  243.  
  244.         if (forceLoop && !closed)
  245.                 loopEnd += 1;
  246.  
  247.         float pathLen = 0.0f;
  248.  
  249.         while (next != loopEnd)
  250.         {
  251.                 Lineseg seg(shape[cur], shape[next % size]);
  252.                 float t;
  253.                 float d = Distance::Point_Lineseg(pos, seg, t);
  254.                 if (d < dist)
  255.                 {
  256.                         dist = d;
  257.                         nearestPt = seg.GetPoint(t);
  258.                         if (distAlongPath)
  259.                                 *distAlongPath = pathLen + Distance::Point_Point(seg.start, nearestPt);
  260.                         if (segmentDir)
  261.                                 *segmentDir = seg.end - seg.start;
  262.                         if (segmentStartIndex)
  263.                                 *segmentStartIndex = cur;
  264.                         if (segmentFraction)
  265.                                 *segmentFraction = t;
  266.                         nearest = next;
  267.                 }
  268.                 pathLen += Distance::Point_Point(seg.start, seg.end);
  269.                 cur = next;
  270.                 ++next;
  271.         }
  272.  
  273.         if (pathLength)
  274.                 *pathLength = pathLen;
  275.  
  276.         return shape.begin() + nearest;
  277. }
  278.  
  279. int SShape::GetIntersectionDistances(const Vec3& start, const Vec3& end, float intersectDistArray[], int maxIntersections, bool testHeight /*=false*/, bool testTopBottom /*=false*/) const
  280. {
  281.         Lineseg ray(start, end);
  282.         float rayLength = sqrtf(start.GetSquaredDistance2D(end));
  283.  
  284.         int intersects = 0;
  285.         float tA, tB;  // Intersection parameters as distances along each line
  286.  
  287.         ListPositions::const_iterator cur = shape.begin();
  288.         ListPositions::const_iterator next = cur;
  289.         ++next;
  290.         while (next != shape.end())
  291.         {
  292.                 Lineseg seg(*cur, *next);
  293.                 bool hit = Intersect::Lineseg_Lineseg2D(ray, seg, tA, tB);
  294.  
  295.                 // Test height
  296.                 if (hit && testHeight)
  297.                 {
  298.                         // Treat all sides as being the full AABB height, so we don't get any gaps
  299.                         // between sides and top and bottom planes
  300.                         float z(ray.GetPoint(tA).z);
  301.                         if (z < aabb.min.z || z > aabb.max.z)
  302.                                 hit = false;
  303.                 }
  304.  
  305.                 if (hit)
  306.                 {
  307.                         intersectDistArray[intersects++] = tA * rayLength;
  308.                         if (intersects == maxIntersections) break;
  309.                 }
  310.                 ++next;
  311.                 ++cur;
  312.         }
  313.  
  314.         // Test top and bottom sides of shape for intersection
  315.         // Note that we cheat a bit and use horizontal shapes at AABB min and max heights,
  316.         // rather than making them properly conform to heights at each shape vertex
  317.         // Should be good enough for most shapes in practice, and is a lot cheaper
  318.         if (testTopBottom)
  319.         {
  320.                 Vec3 pt, norm;
  321.  
  322.                 // test top
  323.                 norm = Vec3(0.f, 0.f, (end.z > start.z) ? -1.f : 1.f); // because plane test is one sided
  324.                 if (Intersect::Line_Plane(Line(start, end), Plane::CreatePlane(norm, aabb.max), pt) &&
  325.                     IsPointInsideShape(pt, false) &&
  326.                     intersects < maxIntersections)
  327.                         intersectDistArray[intersects++] = (pt - start).len();
  328.  
  329.                 // test bottom
  330.                 norm.z *= -1;
  331.                 if (Intersect::Line_Plane(Line(start, end), Plane::CreatePlane(norm, aabb.min), pt) &&
  332.                     IsPointInsideShape(pt, false) &&
  333.                     intersects < maxIntersections)
  334.                         intersectDistArray[intersects++] = (pt - start).len();
  335.         }
  336.  
  337.         std::sort(&intersectDistArray[0], &intersectDistArray[intersects]);
  338.  
  339.         return intersects;
  340. }
  341.  
  342. Vec3 SShape::GetPointAlongPath(float dist) const
  343. {
  344.         if (shape.empty())
  345.                 return ZERO;
  346.  
  347.         if (dist < 0.0f)
  348.                 return shape.front();
  349.  
  350.         ListPositions::const_iterator cur = shape.begin();
  351.         ListPositions::const_iterator next(cur);
  352.         ++next;
  353.  
  354.         float d = 0.0f;
  355.         while (next != shape.end())
  356.         {
  357.                 Vec3 delta = *next - *cur;
  358.                 float len = delta.GetLength();
  359.                 if (len > 0.0f && dist >= d && dist < d + len)
  360.                 {
  361.                         float t = (dist - d) / len;
  362.                         return *cur + delta * t;
  363.                 }
  364.                 d += len;
  365.                 cur = next;
  366.                 ++next;
  367.         }
  368.         return *cur;
  369. }
  370.  
  371. bool SShape::IsPointInsideShape(const Vec3& pos, bool checkHeight) const
  372. {
  373.         // Check height.
  374.         if (checkHeight && height > 0.01f)
  375.         {
  376.                 float h = pos.z - aabb.min.z;
  377.                 if (h < 0.0f || h > height)
  378.                         return false;
  379.         }
  380.         // Is the request point inside the shape.
  381.         if (Overlap::Point_Polygon2D(pos, shape, &aabb))
  382.                 return true;
  383.         return false;
  384. }
  385.  
  386. bool SShape::ConstrainPointInsideShape(Vec3& pos, bool checkHeight) const
  387. {
  388.         if (!IsPointInsideShape(pos, checkHeight))
  389.         {
  390.                 // Target is outside the territory, find closest point on the edge of the territory.
  391.                 float dist = 0;
  392.                 Vec3 nearest;
  393.                 NearestPointOnPath(pos, false, dist, nearest);
  394.                 // adjust height.
  395.                 nearest.z = pos.z;
  396.                 if (checkHeight && height > 0.00001f)
  397.                         nearest.z = clamp_tpl(nearest.z, aabb.min.z, aabb.min.z + height);
  398.                 pos = nearest;
  399.                 return true;
  400.         }
  401.         return false;
  402. }
  403.  
  404. size_t SShape::MemStats() const
  405. {
  406.         size_t size = sizeof(*this) + shape.size() * sizeof(Vec3);
  407.         if (shapeMask.Get())
  408.                 size += shapeMask->MemStats();
  409.         return size;
  410. }
  411.  
  412. SPerceptionModifierShape::SPerceptionModifierShape(const ListPositions& shape, float reductionPerMetre, float reductionMax, float fHeight, bool isClosed) : SShape(shape)
  413. {
  414.         height = fHeight;
  415.         closed = isClosed;
  416.         fReductionPerMetre = clamp_tpl(reductionPerMetre, 0.0f, 1.0f);
  417.         fReductionMax = clamp_tpl(reductionMax, 0.0f, 1.0f);
  418.  
  419.         // Recalc AABB
  420.         aabb.Reset();
  421.         for (ListPositions::const_iterator it = shape.begin(); it != shape.end(); ++it)
  422.                 aabb.Add(*it);
  423.         aabb.max.z = aabb.min.z + height;
  424. }
  425.  
downloadShape2.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