BVB Source Codes

CRYENGINE Show WalkabilityCache.cpp Source code

Return Download CRYENGINE: download WalkabilityCache.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 "WalkabilityCache.h"
  5. #include "WalkabilityCacheManager.h"
  6. #include "DebugDrawContext.h"
  7.  
  8. ILINE float cbrt_halley_step(float a, float R)
  9. {
  10.         const float a3 = a * a * a;
  11.         const float b = a * (a3 + R + R) / (a3 + a3 + R);
  12.  
  13.         return b;
  14. }
  15.  
  16. float cbrt_fast(float cube)
  17. {
  18.         union intfloat
  19.         {
  20.                 size_t i;
  21.                 float  f;
  22.         };
  23.  
  24.         intfloat x;
  25.         x.f = cube;
  26.         x.i = x.i / 3 + 709921077;
  27.  
  28.         float a = x.f;
  29.  
  30.         a = cbrt_halley_step(a, cube);
  31.         return cbrt_halley_step(a, cube);
  32. };
  33.  
  34. WalkabilityCache::WalkabilityCache(tAIObjectID actorID)
  35.         : m_center(ZERO)
  36.         , m_aabb(AABB::RESET)
  37.         , m_entititesHash(0)
  38.         , m_actorID(actorID)
  39. {
  40.         m_floorCache.Reset();
  41. }
  42.  
  43. void WalkabilityCache::Reset(bool resetFloorCache)
  44. {
  45.         m_aabb.Reset();
  46.  
  47.         if (resetFloorCache)
  48.                 m_floorCache.Reset();
  49.  
  50.         m_entities.clear();
  51.         m_aabbs.clear();
  52.         m_entititesHash = 0;
  53. }
  54.  
  55. bool WalkabilityCache::Cache(const AABB& aabb)
  56. {
  57.         const float ExtraBorder = 2.0f;
  58.  
  59.         // we always calculate a bit extra border and avoid clearing the floor cache if nothing changed inside this border
  60.         if (!m_aabb.ContainsBox(aabb) || ((cbrt_fast(m_aabb.GetVolume()) / cbrt_fast(aabb.GetVolume())) > 2.0f))
  61.         {
  62.                 m_aabb = aabb;
  63.                 m_aabb.min.z = aabb.min.z - (WalkabilityFloorDownDist - WalkabilityFloorUpDist) - 0.2f;
  64.                 m_aabb.max.z = aabb.max.z + WalkabilityTotalHeight + 0.2f;
  65.  
  66.                 m_aabb.Expand(Vec3(ExtraBorder, ExtraBorder, ExtraBorder * 0.25f));
  67.         }
  68.  
  69.         const size_t capacity = m_entities.capacity();
  70.  
  71.         m_entities.resize(capacity);
  72.         IPhysicalEntity** entityListPtr = &m_entities.front();
  73.  
  74.         size_t entityCount = (size_t)gEnv->pPhysicalWorld->GetEntitiesInBox(m_aabb.min, m_aabb.max, entityListPtr,
  75.                                                                             AICE_ALL | ent_allocate_list, capacity);
  76.  
  77.         if (entityCount <= capacity)
  78.                 m_entities.resize(entityCount);
  79.         else
  80.         {
  81.                 assert(entityListPtr != &m_entities[0]);
  82.                 memcpy(&m_entities[0], entityListPtr, sizeof(IPhysicalEntity*) * capacity);
  83.                 entityCount = capacity;
  84.  
  85.                 gEnv->pPhysicalWorld->GetPhysUtils()->DeletePointer(entityListPtr);
  86.         }
  87.  
  88.         m_aabbs.resize(entityCount);
  89.  
  90.         size_t entitiesHash = 0;
  91.         pe_status_pos status;
  92.  
  93.         const float HashVec3Precision = 0.05f;
  94.         const float InvHashVec3Precision = 1.0f / HashVec3Precision;
  95.         const float HashQuatPrecision = 0.01f;
  96.         const float InvHashQuatPrecision = 1.0f / HashQuatPrecision;
  97.  
  98.         for (size_t i = 0; i < entityCount; ++i)
  99.         {
  100.                 const IPhysicalEntity* entity = m_entities[i];
  101.  
  102.                 if (entity->GetStatus(&status))
  103.                 {
  104.                         entitiesHash += HashFromUInt((size_t)(UINT_PTR)entity);
  105.                         entitiesHash += HashFromVec3(status.pos, HashVec3Precision, InvHashVec3Precision);
  106.                         entitiesHash += HashFromQuat(status.q, HashQuatPrecision, InvHashQuatPrecision);
  107.  
  108.                         const Vec3 aabbMin(status.BBox[0]);
  109.                         const Vec3 aabbMax(status.BBox[1]);
  110.  
  111.                         // terrain will have a zeroed bbox
  112.                         if (!aabbMin.IsZero() && !aabbMax.IsZero())
  113.                                 m_aabbs[i] = AABB(aabbMin + status.pos, aabbMax + status.pos);
  114.                         else
  115.                                 m_aabbs[i] = m_aabb;
  116.                 }
  117.                 else
  118.                         m_aabbs[i] = AABB(AABB::RESET);
  119.         }
  120.  
  121.         if (entityCount && !entitiesHash)
  122.                 entitiesHash = 0x1337d00d;
  123.  
  124.         if (entitiesHash != m_entititesHash)
  125.         {
  126.                 m_floorCache.Reset();
  127.                 m_entititesHash = entitiesHash;
  128.  
  129.                 return true;
  130.         }
  131.  
  132.         return false;
  133. }
  134.  
  135. void WalkabilityCache::Draw()
  136. {
  137.         CDebugDrawContext dc;
  138.  
  139.         dc->DrawAABB(m_aabb, IDENTITY, false, Col_BlueViolet, eBBD_Faceted);
  140.         m_floorCache.Draw(Col_DarkGreen, Col_Red);
  141. }
  142.  
  143. const AABB& WalkabilityCache::GetAABB() const
  144. {
  145.         return m_aabb;
  146. }
  147.  
  148. bool WalkabilityCache::FullyContaints(const AABB& aabb) const
  149. {
  150.         return (m_aabb.ContainsBox(aabb));
  151. }
  152.  
  153. size_t WalkabilityCache::GetOverlapping(const AABB& aabb, Entities& entities) const
  154. {
  155.         size_t entityCount = m_entities.size();
  156.         size_t count = 0;
  157.  
  158.         for (size_t i = 0; i < entityCount; ++i)
  159.         {
  160.                 const AABB entityAABB = m_aabbs[i];
  161.                 if (entityAABB.IsIntersectBox(aabb))
  162.                 {
  163.                         entities.push_back(m_entities[i]);
  164.                         ++count;
  165.                 }
  166.         }
  167.  
  168.         return count;
  169. }
  170.  
  171. size_t WalkabilityCache::GetOverlapping(const AABB& aabb, Entities& entities, AABBs& aabbs) const
  172. {
  173.         size_t entityCount = m_entities.size();
  174.         size_t count = 0;
  175.  
  176.         for (size_t i = 0; i < entityCount; ++i)
  177.         {
  178.                 const AABB entityAABB = m_aabbs[i];
  179.                 if (entityAABB.IsIntersectBox(aabb))
  180.                 {
  181.                         entities.push_back(m_entities[i]);
  182.                         aabbs.push_back(entityAABB);
  183.                         ++count;
  184.                 }
  185.         }
  186.  
  187.         return count;
  188. }
  189.  
  190. bool WalkabilityCache::IsFloorCached(const Vec3& position, Vec3& floor) const
  191. {
  192.         float height;
  193.  
  194.         if (m_floorCache.GetHeight(position, height))
  195.         {
  196.                 floor = Vec3(position.x, position.y, height);
  197.  
  198.                 return true;
  199.         }
  200.  
  201.         return false;
  202. }
  203.  
  204. bool WalkabilityCache::FindFloor(const Vec3& position, Vec3& floor)
  205. {
  206.         return FindFloor(position, floor, &m_entities.front(), &m_aabbs.front(), m_entities.size(), m_aabb);
  207. }
  208.  
  209. bool WalkabilityCache::FindFloor(const Vec3& position, Vec3& floor, IPhysicalEntity** entities, AABB* aabbs,
  210.                                  size_t entityCount, const AABB& enclosingAABB)
  211. {
  212.         if (!entityCount)
  213.                 return false;
  214.  
  215.         if (gAIEnv.pWalkabilityCacheManager->IsFloorCached(m_actorID, position, floor))
  216.                 return floor.z < FLT_MAX;
  217.  
  218.         Vec3 dir = Vec3(0.0f, 0.0f, -(WalkabilityFloorDownDist + WalkabilityFloorUpDist));
  219.         const Vec3 start = m_floorCache.GetCellCenter(position) + Vec3(0, 0, WalkabilityFloorUpDist);
  220.         const Lineseg line(start, start + dir);
  221.  
  222.         AABB cell = m_floorCache.GetAABB(position);
  223.         cell.min.z -= (WalkabilityFloorDownDist - WalkabilityFloorUpDist);
  224.         cell.max.z += WalkabilityFloorUpDist;
  225.  
  226.         assert(enclosingAABB.ContainsBox(cell));
  227.  
  228.         ray_hit hit;
  229.         float height = FLT_MAX;
  230.         float closest = FLT_MAX;
  231.         IPhysicalWorld* const physicalWorld = gEnv->pPhysicalWorld;
  232.  
  233.         for (size_t i = 0; i < entityCount; ++i)
  234.         {
  235.                 const AABB entityAABB = aabbs[i];
  236.  
  237.                 if ((entityAABB.min.x < start.x) && (entityAABB.max.x > start.x) &&
  238.                     (entityAABB.min.y < start.y) && (entityAABB.max.y > start.y) &&
  239.                     physicalWorld->RayTraceEntity(entities[i], start, dir, &hit, 0, geom_colltype_player))
  240.                 {
  241.                         if (hit.dist < closest)
  242.                         {
  243.                                 closest = hit.dist;
  244.                                 height = start.z - closest;
  245.                         }
  246.                 }
  247.         }
  248.  
  249.         m_floorCache.SetHeight(position, height);
  250.  
  251.         if (height < FLT_MAX)
  252.         {
  253.                 floor = Vec3(position.x, position.y, height);
  254.  
  255.                 if (gAIEnv.CVars.DebugCheckWalkability)
  256.                 {
  257.                         CDebugDrawContext dc;
  258.  
  259.                         dc->DrawLine(line.start, Col_Green, line.end, Col_Green);
  260.                         dc->DrawCone(line.start, Vec3(0.0f, 0.0f, -1.0f), 0.125f, 0.25f, Col_Green);
  261.                         dc->DrawCone(floor + Vec3(0.0f, 0.0f, 0.35f), Vec3(0.0f, 0.0f, -1.0f), 0.125f, 0.35f, Col_SteelBlue);
  262.                 }
  263.  
  264.                 return true;
  265.         }
  266.  
  267.         if (gAIEnv.CVars.DebugCheckWalkability)
  268.         {
  269.                 CDebugDrawContext dc;
  270.  
  271.                 dc->DrawLine(line.start, Col_Red, line.end, Col_Red);
  272.                 dc->DrawCone(line.start, Vec3(0.0f, 0.0f, -1.0f), 0.175f, 0.45f, Col_Red);
  273.         }
  274.  
  275.         return false;
  276. }
  277.  
  278. bool WalkabilityCache::CheckWalkability(const Vec3& origin, const Vec3& target, float radius, Vec3* finalFloor, bool* flatFloor) PREFAST_SUPPRESS_WARNING(6262)
  279. {
  280.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  281.  
  282.         bool floorHeightChanged = false;
  283.  
  284.         Vec3 direction2D(Vec2(target - origin));
  285.         float distanceSq = direction2D.GetLengthSquared2D();
  286.  
  287.         if (distanceSq < sqr(0.125f))
  288.         {
  289.                 if (finalFloor)
  290.                         *finalFloor = origin;
  291.  
  292.                 if (flatFloor)
  293.                         *flatFloor = true;
  294.  
  295.                 return true;
  296.         }
  297.  
  298.         // Marcio: HAX for Crysis2 ticks
  299.         bool isCritter = radius < 0.2f;
  300.         const Vec3 TorsoUp(0.0f, 0.0f, max(radius * 0.65f, isCritter ? WalkabilityCritterTorsoOffset : WalkabilityTorsoOffset));
  301.         const float TorsoTotalHeight = isCritter ? WalkabilityCritterTotalHeight : WalkabilityTotalHeight;
  302.         const float NextFloorMaxZDiff = isCritter ? 0.25f : 0.75f;
  303.         const float NextFloorZOffset = isCritter ? 0.25f : max(radius, 0.5f);
  304.  
  305.         float distance = direction2D.NormalizeSafe() + radius;
  306.  
  307.         const float OptimalSampleOffset = max(0.225f, radius * 0.85f);
  308.         const float OptimalSegmentLength = gAIEnv.CVars.CheckWalkabilityOptimalSectionLength;
  309.         const size_t OptimalSegmentSampleCount = std::max<size_t>(1, (size_t)(OptimalSegmentLength / OptimalSampleOffset));
  310.  
  311.         size_t sampleCount = (size_t)(distance / OptimalSampleOffset);
  312.         const float sampleOffsetAmount = (sampleCount > 1) ? (distance / (float)sampleCount) : distance;
  313.         const Vec3 sampleOffset = direction2D * sampleOffsetAmount;
  314.  
  315.         const float segmentLength = OptimalSegmentSampleCount * sampleOffsetAmount;
  316.         const size_t segmentCount = 1 + (size_t)(distance / segmentLength);
  317.         const Vec3 segmentOffset = direction2D * segmentLength;
  318.         const size_t segmentSampleCount = OptimalSegmentSampleCount;
  319.  
  320.         float minZ = min(origin.z, target.z) - WalkabilityFloorDownDist - 0.2f;
  321.         float maxZ = max(origin.z, target.z) + TorsoTotalHeight + 0.2f;
  322.         float Zdiff = fabs_tpl(maxZ - minZ);
  323.  
  324.         Vec3 segmentStart = origin;
  325.         Vec3 segmentStartFloor;
  326.         Vec3 newFloor;
  327.  
  328.         Vec3 startOBB(ZERO);
  329.         Vec3 endOBB(ZERO);
  330.  
  331.         Entities segmentEntities;
  332.         AABBs segmentAABBs;
  333.         Entities overlapTorsoEntities;
  334.  
  335.         for (size_t i = 0; i < segmentCount; ++i)
  336.         {
  337.                 segmentAABBs.clear();
  338.                 segmentEntities.clear();
  339.  
  340.                 Vec3 segmentEnd = segmentStart + segmentOffset;
  341.  
  342.                 // find all entities for this segment
  343.                 AABB enclosingAABB(AABB::RESET);
  344.  
  345.                 enclosingAABB.Add(Vec3(segmentStart.x, segmentStart.y, minZ), radius);
  346.                 enclosingAABB.Add(Vec3(segmentEnd.x, segmentEnd.y, maxZ), radius);
  347.  
  348.                 if (!GetOverlapping(enclosingAABB, segmentEntities, segmentAABBs))
  349.                         return false; // no floor
  350.  
  351.                 // first segment - get the floor
  352.                 if (i == 0)
  353.                 {
  354.                         if (!FindFloor(segmentStart, segmentStartFloor, &segmentEntities.front(), &segmentAABBs.front(),
  355.                                        segmentEntities.size(), enclosingAABB))
  356.                                 return false;
  357.  
  358.                         newFloor = segmentStartFloor;
  359.  
  360.                         assert(newFloor.IsValid());
  361.                         assert(newFloor.z < FLT_MAX);
  362.                 }
  363.  
  364.                 Vec3 locationFloor = segmentStartFloor;
  365.                 Vec3 checkLocation;
  366.  
  367.                 for (size_t j = 0; (sampleCount > 1) && (j < segmentSampleCount); ++j, --sampleCount)
  368.                 {
  369.                         checkLocation = locationFloor + sampleOffset;
  370.                         checkLocation.z += NextFloorZOffset;
  371.  
  372.                         if (!FindFloor(checkLocation, newFloor, &segmentEntities.front(), &segmentAABBs.front(),
  373.                                        segmentEntities.size(), enclosingAABB))
  374.                                 return false;
  375.  
  376.                         assert(newFloor.IsValid());
  377.                         assert(newFloor.z < FLT_MAX);
  378.  
  379.                         float deltaZ = locationFloor.z - newFloor.z;
  380.                         if (fabs_tpl(deltaZ) > NextFloorMaxZDiff)
  381.                                 return false;
  382.  
  383.                         locationFloor = newFloor;
  384.  
  385.                         // check if we need to do the overlap torso check
  386.                         if (!startOBB.IsZero())
  387.                         {
  388.                                 // find entities for this segment
  389.                                 Vec3 base = locationFloor + TorsoUp;
  390.  
  391.                                 AABB cylinderAABB(Vec3(base.x - radius, base.y - radius, base.z), Vec3(base.x + radius, base.y + radius, base.z + TorsoTotalHeight - TorsoUp.z));
  392.  
  393.                                 for (size_t k = 0; k < (size_t)segmentAABBs.size(); ++k)
  394.                                 {
  395.                                         if (segmentAABBs[k].IsIntersectBox(cylinderAABB))
  396.                                                 overlapTorsoEntities.push_back(segmentEntities[k]);
  397.                                 }
  398.  
  399.                                 // remove duplicate entries
  400.                                 std::sort(overlapTorsoEntities.begin(), overlapTorsoEntities.end());
  401.                                 overlapTorsoEntities.erase(std::unique(overlapTorsoEntities.begin(), overlapTorsoEntities.end()),
  402.                                                            overlapTorsoEntities.end());
  403.  
  404.                                 // check for planar floor, TODO add code for ramps and a like
  405.                                 if (fabs_tpl(startOBB.z - locationFloor.z) > 0.005f)
  406.                                 {
  407.                                         floorHeightChanged = true;
  408.                                         if (OverlapTorsoSegment(startOBB, endOBB, radius, &overlapTorsoEntities.front(), overlapTorsoEntities.size()))
  409.                                                 return false;
  410.  
  411.                                         overlapTorsoEntities.clear();
  412.                                         startOBB = locationFloor;
  413.                                 }
  414.                         }
  415.                         else
  416.                                 startOBB = locationFloor;
  417.  
  418.                         endOBB = locationFloor;
  419.                 }
  420.  
  421.                 segmentStart = newFloor;
  422.                 segmentStartFloor = newFloor;
  423.         }
  424.  
  425.         if (fabs_tpl(target.z - newFloor.z) > WalkabilityFloorDownDist + WalkabilityFloorUpDist)
  426.                 return false;
  427.  
  428.         // check the last segment also
  429.         if (!overlapTorsoEntities.empty())
  430.         {
  431.                 if (OverlapTorsoSegment(startOBB, endOBB, radius, &overlapTorsoEntities.front(), overlapTorsoEntities.size()))
  432.                         return false;
  433.         }
  434.  
  435.         if (finalFloor)
  436.                 *finalFloor = newFloor;
  437.  
  438.         if (flatFloor)
  439.                 *flatFloor = !floorHeightChanged;
  440.  
  441.         return true;
  442. }
  443.  
  444. bool WalkabilityCache::OverlapTorsoSegment(const Vec3& startOBB, const Vec3& endOBB, float radius,
  445.                                            IPhysicalEntity** entities, size_t entityCount)
  446. {
  447.         if (!entityCount)
  448.                 return false;
  449.  
  450.         // Marcio: HAX for Crysis2 ticks
  451.         bool isCritter = radius < 0.2f;
  452.         const Vec3 TorsoUp(0.0f, 0.0f, max(radius * 0.65f, isCritter ? WalkabilityCritterTorsoOffset : WalkabilityTorsoOffset));
  453.         const float TorsoTotalHeight = isCritter ? WalkabilityCritterTotalHeight : WalkabilityTotalHeight;
  454.  
  455.         const float height = (TorsoTotalHeight - TorsoUp.z);
  456.  
  457.         intersection_params ip;
  458.         ip.bStopAtFirstTri = true;
  459.         ip.bNoAreaContacts = true;
  460.         ip.bNoIntersection = 1;
  461.         ip.bNoBorder = true;
  462.         ip.bThreadSafe = true;
  463.  
  464.         ray_hit hit;
  465.  
  466.         IPhysicalWorld::SPWIParams params;
  467.         params.pSkipEnts = entities;
  468.         params.nSkipEnts = -(int)entityCount;
  469.         params.sweepDir = Vec3(0.0f, 0.0f, 0.0f);
  470.         params.pip = &ip;
  471.  
  472.         // short cut if start equals end
  473.         if (endOBB.IsEquivalent(startOBB))
  474.         {
  475.                 primitives::cylinder cylinder;
  476.                 cylinder.axis = Vec3(0.0f, 0.0f, 1.0f);
  477.                 cylinder.center = Vec3(startOBB.x, startOBB.y, startOBB.z + height * 0.5f);
  478.                 cylinder.center += TorsoUp;
  479.                 cylinder.hh = height * 0.5f;
  480.                 cylinder.r = radius;
  481.  
  482.                 params.itype = primitives::cylinder::type;
  483.                 params.pprim = &cylinder;
  484.  
  485.                 bool result = gEnv->pPhysicalWorld->PrimitiveWorldIntersection(params) > 0.0f;
  486.  
  487.                 if (gAIEnv.CVars.DebugCheckWalkability)
  488.                 {
  489.                         CDebugDrawContext()->DrawCylinder(cylinder.center, cylinder.axis,
  490.                                                           cylinder.r, cylinder.hh * 2.0f, result ? Col_Red : Col_Green);
  491.                 }
  492.  
  493.                 return result;
  494.         }
  495.  
  496.         Vec3 forward = (endOBB - startOBB);
  497.         const float length = forward.NormalizeSafe(Vec3Constants<float>::fVec3_OneY);
  498.         Vec3 right = forward.Cross(Vec3Constants<float>::fVec3_OneZ).GetNormalizedSafe(Vec3Constants<float>::fVec3_OneX);
  499.         Vec3 up = right.Cross(forward);
  500.  
  501.         primitives::box physBox;
  502.         physBox.center = 0.5f * (startOBB + endOBB);
  503.         physBox.center += TorsoUp;
  504.         physBox.center.z += 0.5f * height;
  505.         physBox.size.Set(radius, (0.5f * length), 0.5f * height);
  506.         physBox.bOriented = 1;
  507.         physBox.Basis.SetFromVectors(right, forward, up);
  508.         physBox.Basis.Transpose();
  509.  
  510.         // test obb for plane path
  511.         params.itype = primitives::box::type;
  512.         params.pprim = &physBox;
  513.  
  514.         bool result = gEnv->pPhysicalWorld->PrimitiveWorldIntersection(params) > 0.0f;
  515.  
  516.         if (gAIEnv.CVars.DebugCheckWalkability)
  517.         {
  518.                 OBB obb(OBB::CreateOBB(physBox.Basis.GetTransposed(), physBox.size, ZERO));
  519.  
  520.                 CDebugDrawContext()->DrawOBB(obb, Matrix34::CreateTranslationMat(physBox.center), true, result ? Col_Red : Col_Green,
  521.                                              eBBD_Faceted);
  522.  
  523.                 /*
  524.                    if (const bool drawOverlappingAABB = true)
  525.                    {
  526.                    for (size_t i = 0; i < overlapTorsoEntities.size(); ++i)
  527.                    {
  528.                     IPhysicalEntity* entity = overlapTorsoEntities[i];
  529.                     Matrix34 worldTM;
  530.  
  531.                     pe_status_pos ppos;
  532.                     ppos.pMtx3x4 = &worldTM;
  533.  
  534.                     if (entity->GetStatus(&ppos))
  535.                     {
  536.                       CDebugDrawContext dc;
  537.  
  538.                       dc->DrawAABB(AABB(ppos.BBox[0], ppos.BBox[1]), worldTM, false, Col_Red, eBBD_Faceted);
  539.                     }
  540.                    }
  541.                    }
  542.                  */
  543.         }
  544.  
  545.         if (!result)
  546.         {
  547.                 primitives::cylinder cylinderStart;
  548.                 cylinderStart.axis = Vec3(0.0f, 0.0f, 1.0f);
  549.                 cylinderStart.center = Vec3(startOBB.x, startOBB.y, startOBB.z + height * 0.5f);
  550.                 cylinderStart.center += TorsoUp;
  551.                 cylinderStart.hh = height * 0.5f;
  552.                 cylinderStart.r = radius;
  553.  
  554.                 params.itype = primitives::cylinder::type;
  555.                 params.pprim = &cylinderStart;
  556.                 result |= gEnv->pPhysicalWorld->PrimitiveWorldIntersection(params) > 0.0f;
  557.  
  558.                 if (gAIEnv.CVars.DebugCheckWalkability)
  559.                 {
  560.                         CDebugDrawContext()->DrawCylinder(cylinderStart.center, cylinderStart.axis,
  561.                                                           cylinderStart.r, cylinderStart.hh * 2.0f, result ? Col_Red : Col_Green);
  562.                 }
  563.         }
  564.  
  565.         if (!result)
  566.         {
  567.                 primitives::cylinder cylinderEnd;
  568.                 cylinderEnd.axis = Vec3(0.0f, 0.0f, 1.0f);
  569.                 cylinderEnd.center = Vec3(endOBB.x, endOBB.y, endOBB.z + height * 0.5f);
  570.                 cylinderEnd.center += TorsoUp;
  571.                 cylinderEnd.hh = height * 0.5f;
  572.                 cylinderEnd.r = radius;
  573.  
  574.                 params.pprim = &cylinderEnd;
  575.                 result |= gEnv->pPhysicalWorld->PrimitiveWorldIntersection(params) > 0.0f;
  576.  
  577.                 if (gAIEnv.CVars.DebugCheckWalkability)
  578.                 {
  579.                         CDebugDrawContext()->DrawCylinder(cylinderEnd.center, cylinderEnd.axis,
  580.                                                           cylinderEnd.r, cylinderEnd.hh * 2.0f, result ? Col_Red : Col_Green);
  581.                 }
  582.         }
  583.  
  584.         return result;
  585. }
  586.  
  587. size_t WalkabilityCache::GetMemoryUsage() const
  588. {
  589.         return sizeof(m_floorCache) + m_floorCache.GetMemoryUsage();
  590. }
  591.  
downloadWalkabilityCache.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