BVB Source Codes

CRYENGINE Show CoverSampler.cpp Source code

Return Download CRYENGINE: download CoverSampler.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 "CoverSampler.h"
  5. #include "CoverSystem.h"
  6.  
  7. #include "DebugDrawContext.h"
  8.  
  9. CoverSampler::CoverSampler()
  10.         : m_externalState(None)
  11.         , m_aabb(AABB(AABB::RESET))
  12.         , m_flags(0)
  13. {
  14. }
  15.  
  16. CoverSampler::~CoverSampler()
  17. {
  18. }
  19.  
  20. void CoverSampler::Release()
  21. {
  22.         delete this;
  23. }
  24.  
  25. ICoverSampler::ESamplerState CoverSampler::StartSampling(const ICoverSampler::Params& params)
  26. {
  27.         m_state = SamplingState();
  28.         m_state.internalState = SamplerStarting;
  29.  
  30.         m_params = params;
  31.         m_externalState = InProgress;
  32.  
  33.         m_aabb = AABB(AABB::RESET);
  34.         m_flags = 0;
  35.  
  36.         return m_externalState;
  37. }
  38.  
  39. ICoverSampler::ESamplerState CoverSampler::Update(float timeLimitPerFrame, float timeLimitTotal)
  40. {
  41.         CTimeValue now = gEnv->pTimer->GetAsyncTime();
  42.         CTimeValue start = now;
  43.         CTimeValue endTime = now + CTimeValue(timeLimitPerFrame);
  44.         CTimeValue maxTime = CTimeValue(timeLimitTotal);
  45.  
  46.         do
  47.         {
  48.                 switch (m_state.internalState)
  49.                 {
  50.                 case SamplerStarting:
  51.                         {
  52.                                 m_tempSamples.clear();
  53.                                 m_samples.clear();
  54.  
  55.                                 m_state.initialDirection = m_params.direction;
  56.                                 m_state.initialDirection.z = 0.0f;
  57.                                 m_state.initialDirection += CoverSamplerBiasUp;
  58.                                 m_state.initialDirection.NormalizeSafe(Vec3Constants<float>::fVec3_OneY);
  59.                                 m_state.direction = m_state.initialDirection;
  60.  
  61.                                 Vec3 floorNormal;
  62.  
  63.                                 if (SampleFloor(m_params.position, m_params.floorSearchHeight * 2.0f, m_params.floorSearchRadius,
  64.                                                 &m_state.initialFloor, &floorNormal))
  65.                                 {
  66.                                         m_state.initialFloor += CoverUp * CoverOffsetUp;
  67.                                         m_state.floor = m_state.initialFloor;
  68.                                         m_state.initialRight = m_state.direction.Cross(floorNormal);
  69.                                         m_state.initialRight.Normalize();
  70.                                         m_state.right = m_state.initialRight;
  71.  
  72.                                         SurfaceType surfaceType;
  73.                                         float depth = -1.0f;
  74.                                         float heightSamplerInterval = max(m_params.heightSamplerInterval, 0.05f);
  75.  
  76.                                         float height = SampleHeight(m_state.floor, heightSamplerInterval, m_params.limitHeight - CoverOffsetUp,
  77.                                                                     &depth, &m_state.surfaceNormal, &surfaceType);
  78.  
  79.                                         if ((height > 0.0f) && (depth > 0.0f) && (height + CoverOffsetUp >= m_params.minHeight))
  80.                                         {
  81.                                                 height += CoverOffsetUp;
  82.  
  83.                                                 Vec3 origin = m_state.floor - (CoverUp * CoverOffsetUp);
  84.                                                 Vec3 surfaceOrigin = origin + m_state.direction * depth;
  85.  
  86.                                                 m_tempSamples.push_back(Sample(surfaceOrigin, height,
  87.                                                                                surfaceType != SolidSurface ? ICoverSampler::Sample::Dynamic : 0));
  88.  
  89.                                                 m_state.origin = origin + m_state.direction * (depth - (m_params.floorSearchRadius + CoverExtraClearance));
  90.  
  91.                                                 m_state.internalState = SamplerLeft;
  92.                                                 m_state.limitLength = m_params.limitLeft;
  93.                                                 m_state.length = 0.0f;
  94.                                                 m_state.edgeHeight = 0.0f;
  95.                                                 m_state.depth = depth;
  96.  
  97.                                                 m_state.solidDirection = m_state.direction;
  98.                                                 m_state.solidRight = m_state.initialRight;
  99.                                                 m_state.solidFloor = m_state.initialFloor;
  100.  
  101.                                                 break;
  102.                                         }
  103.                                 }
  104.  
  105.                                 m_state.internalState = SamplerError;
  106.                         }
  107.                         break;
  108.                 case SamplerLeft:
  109.                         {
  110.                                 if (!SampleWidth(Left, m_params.widthSamplerInterval, m_params.limitHeight))
  111.                                 {
  112.                                         m_state.direction = m_state.initialDirection;
  113.                                         m_state.right = m_state.initialRight;
  114.                                         m_state.floor = m_state.initialFloor;
  115.  
  116.                                         m_state.internalState = SamplerRight;
  117.                                         m_state.limitLength = m_params.limitRight;
  118.                                         m_state.length = 0.0f;
  119.                                 }
  120.                         }
  121.                         break;
  122.                 case SamplerRight:
  123.                         {
  124.                                 if (!SampleWidth(Right, m_params.widthSamplerInterval, m_params.limitHeight))
  125.                                 {
  126.                                         m_state.internalState = SamplerSimplifySurface;
  127.                                         m_state.limitLength = 0.0f;
  128.                                         m_state.length = 0.0f;
  129.                                 }
  130.                         }
  131.                         break;
  132.                 case SamplerSimplifySurface:
  133.                         {
  134.                                 if (m_tempSamples.size() < 2)
  135.                                         m_state.internalState = SamplerError;
  136.                                 else
  137.                                 {
  138.                                         if (m_tempSamples.size() > 3)
  139.                                         {
  140.                                                 float distanceSq = (m_tempSamples.front().position - m_tempSamples.back().position).GetLengthSquared2D();
  141.                                                 if (distanceSq <= sqr(m_params.widthSamplerInterval + CoverSamplerLoopExtraOffset))
  142.                                                 {
  143.                                                         m_state.looped = true;
  144.                                                         m_tempSamples.push_back(m_tempSamples.front());
  145.                                                 }
  146.                                         }
  147.  
  148.                                         m_state.originalSurfaceSamples = m_tempSamples.size();
  149.  
  150.                                         Simplify();
  151.  
  152.                                         TempSamples().swap(m_tempSamples);
  153.                                         m_state.internalState = SamplerFinished;
  154.                                 }
  155.                         }
  156.                         break;
  157.                 case SamplerFinished:
  158.                         {
  159.                                 m_state.internalState = SamplerReady;
  160.                                 m_externalState = Finished;
  161.  
  162.                                 m_flags = 0;
  163.                                 if (m_state.looped)
  164.                                         m_flags |= ICoverSystem::SurfaceInfo::Looped;
  165.                         }
  166.                         break;
  167.                 case SamplerError:
  168.                         break;
  169.                 default:
  170.                         return m_externalState;
  171.                 }
  172.  
  173.                 if (m_state.internalState == SamplerError)
  174.                 {
  175.                         m_state.internalState = SamplerReady;
  176.                         m_externalState = Error;
  177.  
  178.                         break;
  179.                 }
  180.  
  181.                 now = gEnv->pTimer->GetAsyncTime();
  182.  
  183.                 if (m_externalState != InProgress)
  184.                         break;
  185.  
  186.         }
  187.         while (now < endTime);
  188.  
  189.         ++m_state.updateCount;
  190.  
  191.         CTimeValue totalTime = m_state.totalTime + now - start;
  192.         m_state.totalTime = totalTime;
  193.  
  194.         if (totalTime >= maxTime)
  195.         {
  196.                 TempSamples().swap(m_tempSamples);
  197.                 Samples().swap(m_samples);
  198.  
  199.                 m_externalState = Error;
  200.                 m_state.internalState = SamplerError;
  201.         }
  202.  
  203.         return m_externalState;
  204. }
  205.  
  206. ICoverSampler::ESamplerState CoverSampler::GetState() const
  207. {
  208.         return m_externalState;
  209. }
  210.  
  211. uint32 CoverSampler::GetSampleCount() const
  212. {
  213.         return m_samples.size();
  214. }
  215.  
  216. const ICoverSampler::Sample* CoverSampler::GetSamples() const
  217. {
  218.         if (!m_samples.empty())
  219.                 return &m_samples[0];
  220.  
  221.         return 0;
  222. }
  223.  
  224. const AABB& CoverSampler::GetAABB() const
  225. {
  226.         return m_aabb;
  227. }
  228.  
  229. uint32 CoverSampler::GetSurfaceFlags() const
  230. {
  231.         return m_flags;
  232. }
  233.  
  234. void CoverSampler::DebugDraw() const
  235. {
  236.         CDebugDrawContext dc;
  237.  
  238.         dc->Draw3dLabel(m_state.origin + CoverUp * 0.5f, 1.35f,
  239.                         "Time: ~%.2f/%.2fms\nUpdate Count: %d\nPWI Count: %d\nSimplify: %" PRISIZE_T "/%d",
  240.                         m_state.totalTime.GetMilliSeconds() / (float)m_state.updateCount, m_state.totalTime.GetMilliSeconds(),
  241.                         m_state.updateCount, m_state.pwiCount, m_samples.size(), m_state.originalSurfaceSamples);
  242. }
  243.  
  244. bool CoverSampler::OverlapCylinder(const Vec3& bottomCenter, const Vec3& dir, float length, float radius,
  245.                                    uint32 collisionFlags) const
  246. {
  247.         ++m_state.pwiCount;
  248.  
  249.         float hh = length * 0.5f;
  250.  
  251.         primitives::cylinder cylinder;
  252.         cylinder.center = bottomCenter + dir * hh;
  253.         cylinder.axis = dir;
  254.         cylinder.hh = hh;
  255.         cylinder.r = radius;
  256.  
  257.         if (IntersectionTestResult intResult = gAIEnv.pIntersectionTester->Cast(
  258.               IntersectionTestRequest(cylinder.type, cylinder, Vec3Constants<float>::fVec3_Zero, CoverCollisionEntities)))
  259.         {
  260.                 return true;
  261.         }
  262.  
  263.         return false;
  264. }
  265.  
  266. bool CoverSampler::IntersectSweptSphere(const Vec3& center, const Vec3& dir, float radius, IPhysicalEntity** entityList,
  267.                                         size_t entityCount, IntersectionResult* result) const
  268. {
  269.         ++m_state.pwiCount;
  270.  
  271.         primitives::sphere sphere;
  272.         sphere.center = center;
  273.         sphere.r = radius;
  274.  
  275.         float closest = FLT_MAX;
  276.         Vec3 closestLocation;
  277.         Vec3 closestNormal;
  278.         IPhysicalEntity* closestEntity = 0;
  279.         int closestPart = 0;
  280.  
  281.         ray_hit hit;
  282.         for (size_t i = 0; i < entityCount; ++i)
  283.         {
  284.                 if (gEnv->pPhysicalWorld->CollideEntityWithPrimitive(entityList[i], primitives::sphere::type, &sphere, dir, &hit))
  285.                 {
  286.                         if (hit.dist < closest)
  287.                         {
  288.                                 closest = hit.dist + radius;
  289.                                 closestLocation = hit.pt;
  290.                                 closestNormal = hit.n;
  291.                                 closestEntity = entityList[i];
  292.                                 closestPart = hit.ipart;
  293.                         }
  294.                 }
  295.         }
  296.  
  297.         if (closestEntity)
  298.         {
  299.                 result->distance = closest;
  300.                 result->position = closestLocation;
  301.                 result->normal = closestNormal;
  302.                 result->surfaceType = GetSurfaceType(closestEntity, closestPart);
  303.  
  304.                 return true;
  305.         }
  306.  
  307.         return false;
  308. }
  309.  
  310. bool CoverSampler::IntersectRay(const Vec3& center, const Vec3& dir, uint32 collisionFlags, IntersectionResult* result) const
  311. {
  312.         ++m_state.rwiCount;
  313.  
  314.         if (RayCastResult rayResult = gAIEnv.pRayCaster->Cast(RayCastRequest(center, dir, collisionFlags,
  315.                                                                              rwi_stop_at_pierceable | (geom_colltype_player << rwi_colltype_bit))))
  316.         {
  317.                 if (rayResult->dist >= 0.0f)
  318.                 {
  319.                         if (collisionFlags & ent_static)
  320.                         {
  321.                                 if (rayResult->pCollider->GetType() == PE_RIGID)
  322.                                 {
  323.                                         pe_status_dynamics status;
  324.                                         if (rayResult->pCollider->GetStatus(&status))
  325.                                         {
  326.                                                 if ((status.mass > 0.00001f))
  327.                                                         return false;
  328.                                         }
  329.                                 }
  330.                         }
  331.                         if (result)
  332.                         {
  333.                                 result->distance = rayResult->dist;
  334.                                 result->position = rayResult->pt;
  335.                                 result->normal = rayResult->n;
  336.                                 result->surfaceType = GetSurfaceType(rayResult->pCollider, rayResult->ipart);
  337.                         }
  338.                         return true;
  339.                 }
  340.         }
  341.  
  342.         return false;
  343. }
  344.  
  345. CoverSampler::SurfaceType CoverSampler::GetSurfaceType(IPhysicalEntity* physicalEntity, int ipart) const
  346. {
  347.         pe_params_part pp;
  348.         pp.ipart = ipart;
  349.  
  350.         if (physicalEntity->GetParams(&pp))
  351.         {
  352.                 if (!pp.pPhysGeom || !pp.pPhysGeom->pGeom)
  353.                         return SolidSurface;
  354.  
  355.                 if ((pp.flagsOR & geom_manually_breakable) ||
  356.                     (pp.idmatBreakable >= 0) ||
  357.                     (pp.idSkeleton >= 0))
  358.                 {
  359.                         return DynamicSurface;
  360.                 }
  361.         }
  362.  
  363.         if (IEntity* entity = gEnv->pEntitySystem->GetEntityFromPhysics(physicalEntity))
  364.         {
  365.                 if (gAIEnv.pCoverSystem->IsDynamicSurfaceEntity(entity))
  366.                         return DynamicSurface;
  367.         }
  368.  
  369.         uint64 jointConnectedParts = 0;
  370.         pe_params_structural_joint sjp;
  371.         sjp.idx = 0;
  372.  
  373.         uint32 jointCount = 0;
  374.         while (physicalEntity->GetParams(&sjp))
  375.         {
  376.                 ++jointCount;
  377.                 if (sjp.bBreakable && !sjp.bBroken)
  378.                 {
  379.                         if ((sjp.partid[0] > -1) && (sjp.partid[0] < 64))
  380.                                 jointConnectedParts |= 1ll << sjp.partid[0];
  381.  
  382.                         if ((sjp.partid[1] > -1) && (sjp.partid[1] < 64))
  383.                                 jointConnectedParts |= 1ll << sjp.partid[1];
  384.                 }
  385.                 sjp.idx = jointCount;
  386.                 MARK_UNUSED sjp.id;
  387.         }
  388.  
  389.         return jointConnectedParts ? DynamicSurface : SolidSurface;
  390. }
  391.  
  392. float CoverSampler::SampleHeightInterval(const Vec3& position, const Vec3& dir, float interval,
  393.                                          IPhysicalEntity** entityList, size_t entityCount, float* depth, Vec3* normal,
  394.                                          SurfaceType* surfaceType)
  395. {
  396.         Vec3 top = position + CoverUp * interval;
  397.  
  398.         if (gAIEnv.CVars.DebugDrawCoverSampler & 2)
  399.         {
  400.                 GetAISystem()->AddDebugLine(top, top + dir, 92, 192, 0, 3.0f);
  401.         }
  402.  
  403.         IntersectionResult result;
  404.  
  405.         if (IntersectSweptSphere(top, dir, 0.00125f, entityList, entityCount, &result)
  406.             && (fabs_tpl(result.normal.z) < 0.5f))
  407.         {
  408.                 if (depth)
  409.                         *depth = result.distance;
  410.  
  411.                 if (normal)
  412.                         *normal = result.normal;
  413.  
  414.                 if (surfaceType)
  415.                         *surfaceType = result.surfaceType;
  416.  
  417.                 if (gAIEnv.CVars.DebugDrawCoverSampler & 4)
  418.                 {
  419.                         GetAISystem()->AddDebugLine(result.position, result.position + result.normal, 0, 128, 192, 3.0f);
  420.                 }
  421.  
  422.                 return interval;
  423.         }
  424.         else if (interval >= m_params.heightAccuracy * 2.0f)
  425.         {
  426.                 float intervalMid = interval * 0.5f;
  427.  
  428.                 float res = SampleHeightInterval(position, dir, intervalMid, entityList, entityCount, depth, normal, surfaceType);
  429.                 if (res > 0.0001f)
  430.                         return res;
  431.  
  432.                 res = SampleHeightInterval(position + CoverUp * intervalMid, dir, intervalMid, entityList, entityCount,
  433.                                            depth, normal, surfaceType);
  434.  
  435.                 if (res > 0.0001f)
  436.                         return res;
  437.         }
  438.  
  439.         return 0.0f;
  440. }
  441.  
  442. float CoverSampler::SampleHeight(const Vec3& position, float heightInterval, float maxHeight, float* depth,
  443.                                  Vec3* averageNormal, SurfaceType* surfaceType)
  444. {
  445.         assert(heightInterval > std::numeric_limits<float>::epsilon());
  446.         assert(maxHeight >= 0.0f);
  447.         uint32 sampleCount = (uint32)(0.5f + maxHeight / heightInterval);
  448.  
  449.         if (sampleCount <= 0)
  450.                 return 0.0f;
  451.  
  452.         float deltaHeight = maxHeight / (float)sampleCount;
  453.  
  454.         Vec3 dir = m_state.direction * (m_params.limitDepth + m_params.floorSearchRadius + CoverExtraClearance);
  455.         Vec3 end = position + dir;
  456.  
  457.         Vec3 boxMin(min(position.x, end.x), min(position.y, end.y), min(position.z, end.z));
  458.         boxMin -= Vec3(0.05f, 0.05f, 0.05f);
  459.  
  460.         Vec3 boxMax(max(position.x, end.x), max(position.y, end.y), boxMin.z + maxHeight);
  461.         boxMax += Vec3(0.05f, 0.05f, 0.05f);
  462.  
  463.         uint32 collisionEntities = CoverCollisionEntities;
  464.         if (collisionEntities & ent_static)
  465.                 collisionEntities |= ent_rigid | ent_sleeping_rigid; // support 0-mass rigid entities too
  466.  
  467.         IPhysicalEntity* physicalRefEntity = 0;
  468.         IPhysicalEntity** entityList = 0;
  469.         size_t entityCount = 0;
  470.  
  471.         if (m_params.referenceEntity)
  472.         {
  473.                 physicalRefEntity = m_params.referenceEntity->GetPhysics();
  474.                 entityList = &physicalRefEntity;
  475.                 entityCount = physicalRefEntity ? 1 : 0;
  476.         }
  477.         else
  478.         {
  479.                 entityCount = (size_t)GetPhysicalEntitiesInBox(boxMin, boxMax, entityList, collisionEntities);
  480.  
  481.                 if (entityCount == 0)
  482.                         return 0.0f;
  483.  
  484.                 if (CoverCollisionEntities & ent_static)
  485.                 {
  486.                         for (size_t i = 0; i < entityCount; ++i)
  487.                         {
  488.                                 IPhysicalEntity* entity = entityList[i];
  489.  
  490.                                 if (entity->GetType() == PE_RIGID)
  491.                                 {
  492.                                         pe_status_dynamics status;
  493.                                         if (entity->GetStatus(&status))
  494.                                         {
  495.                                                 if ((status.mass > 0.00001f))
  496.                                                 {
  497.                                                         entityList[i] = entityList[--entityCount];
  498.                                                         --i;
  499.                                                 }
  500.                                         }
  501.                                 }
  502.                         }
  503.                 }
  504.         }
  505.  
  506.         if (entityCount == 0)
  507.                 return 0.0f;
  508.  
  509.         float currHeight = 0.0f;
  510.         float currDepth = FLT_MAX;
  511.  
  512.         uint32 resultCount = 0;
  513.  
  514.         if (averageNormal)
  515.                 averageNormal->zero();
  516.  
  517.         if (surfaceType)
  518.                 *surfaceType = SolidSurface;
  519.  
  520.         for (uint32 i = 0; i <= sampleCount; ++i)
  521.         {
  522.                 float sampleStart = deltaHeight * i;
  523.                 Vec3 center = position + CoverUp * sampleStart;
  524.  
  525.                 Vec3 normal;
  526.                 float smpDepth;
  527.                 SurfaceType intervalSurfaceType;
  528.                 float height = SampleHeightInterval(center, dir, heightInterval, entityList, entityCount, &smpDepth, &normal,
  529.                                                     &intervalSurfaceType);
  530.  
  531.                 if (height > 0.001f)
  532.                 {
  533.                         if ((intervalSurfaceType != SolidSurface) && surfaceType)
  534.                                 *surfaceType = intervalSurfaceType;
  535.  
  536.                         currHeight = sampleStart + height;
  537.                         if (currDepth > smpDepth)
  538.                                 currDepth = smpDepth;
  539.  
  540.                         ++resultCount;
  541.  
  542.                         if (averageNormal)
  543.                                 *averageNormal += normal;
  544.                 }
  545.                 else
  546.                 {
  547.                         float sampleHeight = sampleStart + deltaHeight;
  548.                         if (sampleHeight >= m_params.maxStartHeight)
  549.                         {
  550.                                 if ((sampleHeight - currHeight) > heightInterval)
  551.                                         break;
  552.                         }
  553.                 }
  554.         }
  555.  
  556.         if (depth)
  557.                 *depth = currDepth;
  558.  
  559.         if (averageNormal && (resultCount > 1))
  560.                 *averageNormal /= (float)resultCount;
  561.  
  562.         return currHeight;
  563. }
  564.  
  565. bool CoverSampler::SampleFloor(const Vec3& position, float searchHeight, float searchRadius,
  566.                                Vec3* floor, Vec3* normal)
  567. {
  568.         Vec3 center = position + CoverUp * (searchHeight * 0.5f);
  569.         Vec3 dir = CoverUp * -searchHeight;
  570.  
  571.         if (gAIEnv.CVars.DebugDrawCoverSampler & 1)
  572.         {
  573.                 GetAISystem()->AddDebugLine(center, center + dir, 214, 164, 96, 3.0f);
  574.                 GetAISystem()->AddDebugSphere(center, 0.1f, 210, 183, 135, 3.0f);
  575.                 GetAISystem()->AddDebugSphere(center + dir, 0.1f, 139, 69, 19, 3.0f);
  576.         }
  577.  
  578.         IntersectionResult result;
  579.  
  580.         int collisionEntities = CoverCollisionEntities;
  581.         if (collisionEntities & ent_static)
  582.                 collisionEntities |= ent_rigid | ent_sleeping_rigid; // support 0-mass rigid entities too
  583.  
  584.         if (IntersectRay(center, dir, collisionEntities, &result))
  585.         {
  586.                 if (CoverUp.dot(result.normal) <= 0.0001f)
  587.                         return false;
  588.  
  589.                 if (floor)
  590.                         *floor = result.position;
  591.  
  592.                 if (normal)
  593.                         *normal = result.normal;
  594.  
  595.                 return true;
  596.         }
  597.  
  598.         return false;
  599. }
  600.  
  601. float CoverSampler::SampleWidthInterval(EDirection direction, float interval, float maxHeight, Vec3& floor,
  602.                                         Vec3& floorNormal, Vec3& averageNormal)
  603. {
  604.         float delta = 0.025f;
  605.         float offset = interval;
  606.  
  607.         while (offset > (delta + 0.0025f))
  608.         {
  609.                 Vec3 offsetDir = m_state.right * ((direction == Left) ? -offset : offset);
  610.                 bool ok = SampleFloor(m_state.floor + offsetDir, m_params.floorSearchHeight, m_params.floorSearchRadius, &floor, &floorNormal);
  611.                 floor += CoverUp * CoverOffsetUp;
  612.  
  613.                 ok = ok && CheckClearance(m_state.floor, floorNormal, offsetDir, maxHeight);
  614.                 ok = ok && CanSampleHeight(floor, m_state.direction, direction);
  615.  
  616.                 if (ok)
  617.                 {
  618.                         float depth = -1.0f;
  619.                         float heightSamplerInterval = max(m_params.heightSamplerInterval, 0.05f);
  620.  
  621.                         SurfaceType surfaceType;
  622.                         float height = SampleHeight(floor, heightSamplerInterval, maxHeight - CoverOffsetUp, &depth, &averageNormal,
  623.                                                     &surfaceType);
  624.  
  625.                         if ((height > 0.0f) && (depth > 0.0f) && (height + CoverOffsetUp >= m_params.minHeight))
  626.                         {
  627.                                 Sample sample(floor + (m_state.direction * depth), height);
  628.                                 sample.flags |= (surfaceType != SolidSurface) ? ICoverSampler::Sample::Dynamic : 0;
  629.  
  630.                                 Vec3 backoffDir = -m_state.direction;
  631.                                 backoffDir.z *= -1.0f; // direction.z is always 0 + small offset
  632.  
  633.                                 floor = sample.position + (backoffDir * (m_params.floorSearchRadius + CoverExtraClearance));
  634.                                 floor += CoverUp * -CoverOffsetUp;
  635.                                 height += CoverOffsetUp;
  636.  
  637.                                 CLAMP(height, 0.0f, maxHeight);
  638.  
  639.                                 float deltaSq;
  640.  
  641.                                 if (ValidateSample(floor, m_state.direction, sample, direction, &deltaSq))
  642.                                 {
  643.                                         TempSamples::iterator insertLocation = (direction == Left) ? m_tempSamples.begin() : m_tempSamples.end();
  644.                                         m_tempSamples.insert(insertLocation, sample);
  645.  
  646.                                         m_state.length += sqrt_tpl(deltaSq);
  647.                                         m_state.depth = depth;
  648.                                         m_state.edgeHeight = height;
  649.                                 }
  650.                                 else if (gAIEnv.CVars.DebugDrawCoverSampler & 8)
  651.                                 {
  652.                                         GetAISystem()->AddDebugSphere(sample.position, 0.035f, 255, 0, 0, 3.0f);
  653.                                         GetAISystem()->AddDebugLine(sample.position + CoverUp * CoverOffsetUp, floor + CoverUp * CoverOffsetUp, 255, 0, 0, 3.0f);
  654.                                 }
  655.  
  656.                                 return height;
  657.                         }
  658.                 }
  659.  
  660.                 offset -= delta;
  661.         }
  662.  
  663.         return 0.0f;
  664. }
  665.  
  666. bool CoverSampler::SampleWidth(EDirection direction, float widthInterval, float maxHeight)
  667. {
  668.         Vec3 floor(ZERO);
  669.         Vec3 floorNormal(ZERO);
  670.         Vec3 averageNormal(ZERO);
  671.  
  672.         if (SampleWidthInterval(direction, widthInterval, maxHeight, floor, floorNormal, averageNormal) < m_params.minHeight)
  673.                 return false;
  674.  
  675.         if (!Adjust(floor, floorNormal, m_state.surfaceNormal, 0.25f))
  676.                 return false;
  677.  
  678.         m_state.solidDirection = m_state.direction;
  679.         m_state.solidRight = m_state.right;
  680.         m_state.solidFloor = m_state.floor;
  681.  
  682.         averageNormal.z = 0.0f;
  683.         averageNormal.normalize();
  684.         m_state.surfaceNormal = -averageNormal;
  685.  
  686.         if (m_state.length >= m_state.limitLength)
  687.                 return false;
  688.  
  689.         // prevent overlapping if looping
  690.  
  691.         if (m_tempSamples.size() > 3)
  692.         {
  693.                 float distanceSq = (m_tempSamples.front().position - m_tempSamples.back().position).GetLengthSquared2D();
  694.                 if (distanceSq <= sqr(m_params.widthSamplerInterval + CoverSamplerLoopExtraOffset))
  695.                         return false;
  696.         }
  697.  
  698.         return true;
  699. }
  700.  
  701. bool CoverSampler::CheckClearance(const Vec3& floor, const Vec3& floorNormal, const Vec3& dir, float maxHeight)
  702. {
  703.         /*
  704.  
  705.            #ifdef CRYAISYSTEM_DEBUG
  706.            if (gAIEnv.CVars.DebugDrawCoverSampler & 16)
  707.            {
  708.             Vec3 center = floor + CoverUp * (slopeOffset + (maxHeight - slopeOffset) * 0.5f);
  709.  
  710.             GetAISystem()->AddDebugCylinder(center, CoverUp, m_params.floorSearchRadius, maxHeight - slopeOffset,
  711.               ColorB(Col_DarkWood, 0.25f), 3.0f);
  712.            }
  713.            #endif //CRYAISYSTEM_DEBUG
  714.  
  715.            if (OverlapCylinder(floor + CoverUp * slopeOffset, CoverUp, maxHeight - slopeOffset, m_params.floorSearchRadius,
  716.             CoverCollisionEntities))
  717.            {
  718.            #ifdef CRYAISYSTEM_DEBUG
  719.             Vec3 center = floor + CoverUp * (slopeOffset + (maxHeight - slopeOffset) * 0.5f);
  720.  
  721.             GetAISystem()->AddDebugCylinder(center, CoverUp, m_params.floorSearchRadius, maxHeight - slopeOffset,
  722.               ColorB(Col_Red, 0.75f), 3.0f);
  723.            #endif //CRYAISYSTEM_DEBUG
  724.  
  725.             return false;
  726.            }*/
  727.  
  728.         //if (!m_params.referenceEntity)
  729.         {
  730.                 const float slopeOffset = tan_tpl(DEG2RAD(25.0f)) * m_params.floorSearchRadius;
  731.  
  732.                 const float Radius = 0.25f;
  733.                 IntersectionResult result;
  734.  
  735.                 //      Vec3 offset = dir.normalized() * -Radius;
  736.                 Vec3 offset(ZERO);
  737.                 Vec3 center = offset + floor + CoverUp * (slopeOffset + Radius);
  738.                 //if (IntersectSweptSphere(center, dir, Radius, CoverCollisionEntities, &result))
  739.                 if (IntersectRay(center, dir, CoverCollisionEntities, &result))
  740.                         return false;
  741.  
  742.                 center = offset + floor + CoverUp * (slopeOffset + (maxHeight - slopeOffset - Radius));
  743.                 //if (IntersectSweptSphere(center, dir, Radius, CoverCollisionEntities, &result))
  744.                 if (IntersectRay(center, dir, CoverCollisionEntities, &result))
  745.                         return false;
  746.         }
  747.  
  748.         return true;
  749. }
  750.  
  751. bool CoverSampler::Adjust(const Vec3& floor, const Vec3& floorNormal, const Vec3& wantedDirection, float weight)
  752. {
  753.         Vec3 adjustedDir = (wantedDirection * weight + m_state.direction * (1.0f - weight));
  754.         adjustedDir.z = 0.0f;
  755.         adjustedDir += CoverSamplerBiasUp;
  756.         adjustedDir.Normalize();
  757.  
  758.         if (m_params.maxCurvatureAngleCos >= -1.0f)
  759.         {
  760.                 if (m_state.initialDirection.dot(adjustedDir) <= m_params.maxCurvatureAngleCos)
  761.                         return false;
  762.         }
  763.  
  764.         m_state.direction = adjustedDir;
  765.         m_state.right = m_state.direction.Cross(floorNormal);
  766.         m_state.right.Normalize();
  767.         m_state.floor = floor;
  768.  
  769.         return true;
  770. }
  771.  
  772. bool CoverSampler::CanSampleHeight(const Vec3& floor, const Vec3& direction, EDirection samplingDirection) const
  773. {
  774.         if (m_tempSamples.size() <= 1)
  775.                 return true;
  776.  
  777.         const Vec3& end =
  778.           (samplingDirection == Left) ? m_tempSamples.begin()->position : m_tempSamples.rbegin()->position;
  779.         const Vec3& start =
  780.           (samplingDirection == Left) ? (m_tempSamples.begin() + 1)->position : (m_tempSamples.rbegin() + 1)->position;
  781.  
  782.         float a, b;
  783.         Lineseg segment(start, end);
  784.         Lineseg ray(floor, floor + direction * (m_params.limitDepth + m_params.floorSearchRadius + CoverExtraClearance));
  785.  
  786.         if (Intersect::Lineseg_Lineseg2D(segment, ray, a, b))
  787.                 return false;
  788.  
  789.         return true;
  790. }
  791.  
  792. bool CoverSampler::ValidateSample(const Vec3& floor, const Vec3& direction, const Sample& sample,
  793.                                   EDirection samplingDirection, float* deltaSq) const
  794. {
  795.         assert(deltaSq);
  796.  
  797.         const Sample& previous = (samplingDirection == Left) ? m_tempSamples.front() : m_tempSamples.back();
  798.  
  799.         Vec3 delta = previous.position - sample.position;
  800.         *deltaSq = delta.GetLengthSquared2D();
  801.  
  802.         const float SmallLocationThresholdSq = sqr(0.0125f);
  803.  
  804.         if (*deltaSq < SmallLocationThresholdSq)
  805.                 return false;
  806.  
  807.         if (m_tempSamples.size() <= 1)
  808.                 return true;
  809.  
  810.         // check if the angle is not too spiky
  811.         const Vec3& mid =
  812.           (samplingDirection == Left) ? m_tempSamples.begin()->position : m_tempSamples.rbegin()->position;
  813.         const Vec3& right =
  814.           (samplingDirection == Left) ? (m_tempSamples.begin() + 1)->position : (m_tempSamples.rbegin() + 1)->position;
  815.         const Vec3& left = sample.position;
  816.  
  817.         Vec3 toLeft = left - mid;
  818.         toLeft.z = 0.0f;
  819.         toLeft.normalize();
  820.  
  821.         Vec3 toRight = right - mid;
  822.         toRight.z = 0.0f;
  823.         toRight.normalize();
  824.  
  825.         const float MinAngleCos = cos_tpl(DEG2RAD(90.5f));
  826.         if (toLeft.Dot(toRight) >= MinAngleCos)
  827.                 return false;
  828.  
  829.         return true;
  830. }
  831.  
  832. void CoverSampler::Simplify()
  833. {
  834.         uint32 coverSampleCount = m_tempSamples.size();
  835.  
  836.         if (coverSampleCount < 3)
  837.                 return;
  838.  
  839.         m_aabb = AABB(AABB::RESET);
  840.         m_samples.resize(0);
  841.  
  842.         uint32 leftIdx = 0;
  843.         uint32 midIdx = 1;
  844.         uint32 rightIdx = 2;
  845.  
  846.         if (!m_state.looped)
  847.         {
  848.                 const Sample& front = m_tempSamples.front();
  849.                 m_samples.push_back(front);
  850.                 m_aabb.Add(front.position);
  851.                 m_aabb.Add(front.position + Vec3(0.0f, 0.0f, front.GetHeight()));
  852.         }
  853.  
  854.         const float MinThreshold = 0.0025f;
  855.         const float MinThresholdSq = sqr(MinThreshold);
  856.         const float Threshold = max(m_params.simplifyThreshold, MinThreshold);
  857.         const float ThresholdSq = sqr(Threshold);
  858.         const float MaxDynamicSampleDistanceSq = sqr(0.4f);
  859.  
  860.         uint32 tempSampleCount = m_tempSamples.size();
  861.         uint32 iterationCount = m_state.looped ? tempSampleCount : (tempSampleCount - 3);
  862.  
  863.         for (uint i = 0; i < iterationCount; ++i)
  864.         {
  865.                 const Sample& left = m_tempSamples[leftIdx % tempSampleCount];
  866.                 const Sample& mid = m_tempSamples[midIdx % tempSampleCount];
  867.                 const Sample& right = m_tempSamples[rightIdx % tempSampleCount];
  868.  
  869.                 float t;
  870.                 float distanceSq = Distance::Point_LinesegSq(mid.position, Lineseg(left.position, right.position), t);
  871.  
  872.                 if (distanceSq < ThresholdSq)
  873.                 {
  874.                         float toLeftLen = (left.position - mid.position).NormalizeSafe();
  875.                         float toRightLen = (right.position - mid.position).NormalizeSafe();
  876.  
  877.                         float leftTop = left.position.z + left.GetHeight();
  878.                         float rightTop = right.position.z + right.GetHeight();
  879.                         float midTop = mid.position.z + mid.GetHeight();
  880.  
  881.                         float midFaction = toLeftLen / (toLeftLen + toRightLen);
  882.                         float goodMid = leftTop + midFaction * (rightTop - leftTop);
  883.  
  884.                         float topDiff = fabs_tpl(goodMid - midTop);
  885.  
  886.                         if (topDiff < Threshold)
  887.                         {
  888.                                 if (mid.flags & ICoverSampler::Sample::Dynamic)
  889.                                 {
  890.                                         if (m_samples.empty() || ((m_samples.back().flags & ICoverSampler::Sample::Dynamic) == 0)
  891.                                             || ((m_samples.back().position - mid.position).len2() >= MaxDynamicSampleDistanceSq))
  892.                                         {
  893.                                                 m_aabb.Add(mid.position);
  894.                                                 m_aabb.Add(mid.position + Vec3(0.0f, 0.0f, mid.GetHeight()));
  895.  
  896.                                                 m_samples.push_back(mid);
  897.                                                 ++leftIdx;
  898.                                                 ++midIdx;
  899.                                                 ++rightIdx;
  900.  
  901.                                                 continue;
  902.                                         }
  903.                                 }
  904.  
  905.                                 if ((topDiff < MinThreshold) && (distanceSq < MinThresholdSq)) // just lying on the line
  906.                                 {
  907.  
  908.                                         ++leftIdx;
  909.                                         ++midIdx;
  910.                                         ++rightIdx;
  911.                                         continue;
  912.                                 }
  913.                                 else
  914.                                 {
  915.                                         m_aabb.Add(right.position);
  916.                                         m_aabb.Add(right.position + Vec3(0.0f, 0.0f, right.GetHeight()));
  917.  
  918.                                         m_samples.push_back(right);
  919.                                         leftIdx += 2;
  920.                                         midIdx += 2;
  921.                                         rightIdx += 2;
  922.                                         iterationCount -= 1;
  923.                                         continue;
  924.                                 }
  925.                         }
  926.                 }
  927.  
  928.                 m_aabb.Add(mid.position);
  929.                 m_aabb.Add(mid.position + Vec3(0.0f, 0.0f, mid.GetHeight()));
  930.  
  931.                 m_samples.push_back(mid);
  932.                 ++leftIdx;
  933.                 ++midIdx;
  934.                 ++rightIdx;
  935.         }
  936.  
  937.         if (!m_state.looped)
  938.         {
  939.                 const Sample& back = m_tempSamples.back();
  940.                 m_samples.push_back(back);
  941.                 m_aabb.Add(back.position);
  942.                 m_aabb.Add(back.position + Vec3(0.0f, 0.0f, back.GetHeight()));
  943.         }
  944.  
  945.         // workaround for when we end up with no more than 1 sample
  946.         // (this can happen if all samples lie on a line and the last sample is looping back to the first one)
  947.         if (m_samples.size() < 2)
  948.         {
  949.                 // reject all samples
  950.                 m_aabb = AABB(AABB::RESET);
  951.                 m_samples.resize(0);
  952.         }
  953. }
  954.  
downloadCoverSampler.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