BVB Source Codes

CRYENGINE Show AIRadialOcclusion.cpp Source code

Return Download CRYENGINE: download AIRadialOcclusion.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. /********************************************************************
  4.    -------------------------------------------------------------------------
  5.    File name:   AIRadialOcclusion.cpp
  6.    $Id$
  7.    Description:
  8.  
  9.    -------------------------------------------------------------------------
  10.    History:
  11.    - 2007                               : Created by Mikko Mononen
  12.    - 2 Mar 2009 : Evgeny Adamenkov: Replaced IRenderer with CDebugDrawContext
  13.  
  14.  *********************************************************************/
  15.  
  16. #include "StdAfx.h"
  17. #include "AIRadialOcclusion.h"
  18. #include <CryMath/Cry_Vector3.h>
  19. #include "DebugDrawContext.h"
  20. #include <math.h>
  21.  
  22. // Comment this out to do immediate raycasts.
  23. #define USE_ASYNC_RAYCASTS 1
  24.  
  25. //====================================================================
  26. // CAIRadialOcclusion
  27. //====================================================================
  28. void CAIRadialOcclusion::Reset(const Vec3& c, float r)
  29. {
  30.         m_center = c;
  31.         for (unsigned i = 0; i < SAMPLE_COUNT; ++i)
  32.                 m_buffer[i] = r;
  33. }
  34.  
  35. //====================================================================
  36. // RasterizeCircle
  37. // Rasterize circle like object into the buffer.
  38. //====================================================================
  39. void CAIRadialOcclusion::RasterizeCircle(const Vec3& pos, float r)
  40. {
  41.         Vec3 dir = pos - m_center;
  42.         dir.z = 0;
  43.  
  44.         // Rasterize the span
  45.         float a = atan2f(dir.y, dir.x);
  46.         float d = dir.len();
  47.         float w = r / d;
  48.         float a0 = a - w;
  49.         float a1 = a + w;
  50.  
  51.         // Move the cover a bit closer.
  52.         d -= r / 2;
  53.  
  54.         int ia0 = (int)ceilf(a0 / gf_PI2 * SAMPLE_COUNT);
  55.         int ia1 = (int)floorf(a1 / gf_PI2 * SAMPLE_COUNT);
  56.  
  57.         if (ia1 >= ia0)
  58.         {
  59.                 for (int i = ia0; i < ia1; ++i)
  60.                 {
  61.                         int x = i & SAMPLE_MASK;
  62.                         if (d < m_buffer[x])
  63.                                 m_buffer[x] = d;
  64.                 }
  65.         }
  66. }
  67.  
  68. //====================================================================
  69. // RasterizeEdge
  70. // Rasterize linear object into the buffer.
  71. //====================================================================
  72. void CAIRadialOcclusion::RasterizeEdge(const Vec3& start, const Vec3& end, bool cull)
  73. {
  74.         Vec3 v0(start - m_center);
  75.         v0.z = 0;
  76.         Vec3 v1(end - m_center);
  77.         v1.z = 0;
  78.  
  79.         Vec3 edge(v1 - v0);
  80.         if (cull)
  81.         {
  82.                 Vec3 edgen(edge.y, -edge.x, 0);
  83.                 if (edgen.Dot(v0) < 0.0f)
  84.                         return;
  85.         }
  86.  
  87.         // Rasterize the span
  88.         float d0 = v0.len();
  89.         float d1 = v1.len();
  90.         float a0 = atan2f(v0.y, v0.x);
  91.         float a1 = atan2f(v1.y, v1.x);
  92.  
  93.         if (a1 < a0)
  94.                 a1 += gf_PI2;
  95.  
  96.         int ia0 = (int)floorf(a0 / gf_PI2 * SAMPLE_COUNT);
  97.         int ia1 = (int)floorf(a1 / gf_PI2 * SAMPLE_COUNT);
  98.  
  99.         int n = (ia1 - ia0);
  100.         if (n >= 0)
  101.         {
  102.                 float a = (float)(ia0 + 0.5f) / (float)SAMPLE_COUNT * gf_PI2;
  103.                 float da = (float)1.0f / (float)SAMPLE_COUNT * gf_PI2;
  104.  
  105.                 if (fabsf(edge.x) > fabsf(edge.y))
  106.                 {
  107.                         // y = mx + c
  108.                         // sin(a)*r = m*cos(a)*r + c
  109.                         // r = c / (sin(a) - m_cos(a))
  110.                         float m = (v1.y - v0.y) / (v1.x - v0.x);
  111.                         float c = v0.y - m * v0.x;
  112.  
  113.                         for (int i = ia0; i <= ia1; ++i)
  114.                         {
  115.                                 int x = i & SAMPLE_MASK;
  116.                                 float aa = clamp_tpl(a, a0, a1);
  117.                                 float d = c / (sinf(aa) - m * cosf(aa));
  118.                                 if (d > 0 && d < m_buffer[x])
  119.                                         m_buffer[x] = d;
  120.                                 a += da;
  121.                         }
  122.                 }
  123.                 else
  124.                 {
  125.                         // x = my + c
  126.                         // sin(a)*r = m*cos(a)*r + c
  127.                         // r = c / (sin(a) - m_cos(a))
  128.                         float m = (v1.x - v0.x) / (v1.y - v0.y);
  129.                         float c = v0.x - m * v0.y;
  130.  
  131.                         for (int i = ia0; i <= ia1; ++i)
  132.                         {
  133.                                 int x = i & SAMPLE_MASK;
  134.                                 float aa = clamp_tpl(a, a0, a1);
  135.                                 float d = c / (cosf(aa) - m * sinf(aa));
  136.                                 if (d > 0 && d < m_buffer[x])
  137.                                         m_buffer[x] = d;
  138.                                 a += da;
  139.                         }
  140.                 }
  141.         }
  142. }
  143.  
  144. //====================================================================
  145. // operator=
  146. //====================================================================
  147. void CAIRadialOcclusion::operator=(const CAIRadialOcclusion& rhs)
  148. {
  149.         for (unsigned i = 0; i < SAMPLE_COUNT; ++i)
  150.                 m_buffer[i] = rhs.m_buffer[i];
  151.         m_center = rhs.m_center;
  152. }
  153.  
  154. //====================================================================
  155. // CAIRadialOcclusionRaycast
  156. //====================================================================
  157. CAIRadialOccypancy::CAIRadialOccypancy() :
  158.         m_center(0, 0, 0),
  159.         m_axisy(0, 1, 0), m_axisx(1, 0, 0),
  160.         m_radius(1.0f)
  161. {
  162. }
  163.  
  164. CAIRadialOccypancy::~CAIRadialOccypancy()
  165. {
  166. }
  167.  
  168. void CAIRadialOccypancy::Reset(const Vec3& center, const Vec3& forward, float radius)
  169. {
  170.         m_spans.clear();
  171.         m_center = center;
  172.         m_axisx = forward;
  173.         m_axisx.z = 0;
  174.         m_axisx.Normalize();
  175.         m_axisy.Set(m_axisx.y, -m_axisx.x, 0.0f);
  176.         m_radius = radius;
  177. }
  178.  
  179. Vec3 CAIRadialOccypancy::GetNearestUnoccupiedDirection(const Vec3& dir, float& bias)
  180. {
  181.         float x = m_axisx.Dot(dir);
  182.         float y = m_axisy.Dot(dir);
  183.         float a = atan2f(y, x);
  184.  
  185.         for (unsigned i = 0, ni = m_spans.size(); i < ni; ++i)
  186.         {
  187.                 if (a >= m_spans[i].smin && a <= m_spans[i].smax)
  188.                 {
  189.                         float w0 = a - m_spans[i].smin;
  190.                         float w1 = m_spans[i].smax - a;
  191.                         if (bias < -0.1f)
  192.                                 w0 *= 0.4f;
  193.                         else if (bias > 0.1f)
  194.                                 w1 *= 0.4f;
  195.                         else
  196.                                 w1 *= 0.75f;
  197.  
  198.                         if (w0 < w1)
  199.                         {
  200.                                 a = m_spans[i].smin;
  201.                                 bias = -1.0f;
  202.                         }
  203.                         else
  204.                         {
  205.                                 a = m_spans[i].smax;
  206.                                 bias = 1.0f;
  207.                         }
  208.  
  209.                         return m_axisx * cosf(a) + m_axisy * sinf(a);
  210.                 }
  211.         }
  212.  
  213.         bias = 0.0f;
  214.  
  215.         return dir;
  216. }
  217.  
  218. void CAIRadialOccypancy::AddObstructionCircle(const Vec3& pos, float radius)
  219. {
  220.         Vec3 diff = pos - m_center;
  221.         float x = m_axisx.Dot(diff);
  222.         float y = m_axisy.Dot(diff);
  223.  
  224.         float dist = sqrtf(sqr(x) + sqr(y));
  225.  
  226.         if (dist > (m_radius + radius))
  227.         {
  228.                 // The circles do not touch at all.
  229.                 return;
  230.         }
  231.         else if (dist < radius)
  232.         {
  233.                 // The circle contains the center, add half circle to the buffer.
  234.                 float a = atan2f(y, x);
  235.                 AddAndMergeSpan(a - gf_PI / 2, a + gf_PI / 2);
  236.         }
  237.         else
  238.         {
  239.                 // The circle is
  240.                 float s = clamp_tpl(radius / dist, -1.0f, 1.0f);
  241.                 float ra = asinf(s);
  242.                 float a = atan2f(y, x);
  243.  
  244.                 if (dist > m_radius)
  245.                 {
  246.                         float ss = (dist - m_radius) / radius;
  247.                         ss = ss * ss * ss;
  248.                         ra *= 1 - ss;
  249.                 }
  250.  
  251.                 AddAndMergeSpan(a - ra, a + ra);
  252.         }
  253. }
  254.  
  255. void CAIRadialOccypancy::AddObstructionLine(const Vec3& p0, const Vec3& p1)
  256. {
  257.         float t0, t1;
  258.         if (!IntersectSegmentCircle(p0, p1, m_center, m_radius, t0, t1))
  259.                 return;
  260.         if ((t0 < 0.0f && t1 < 0.0f) || (t0 > 1.0f && t1 > 1.0f))
  261.                 return;
  262.         if (t0 < 0) t0 = 0;
  263.         if (t1 > 1) t1 = 1;
  264.         Vec3 dir = p1 - p0;
  265.         AddAndMergeSegment(p0 + dir * t0, p0 + dir * t1);
  266. }
  267.  
  268. void CAIRadialOccypancy::AddObstructionDirection(const Vec3& dir)
  269. {
  270.         float x = m_axisx.Dot(dir);
  271.         float y = m_axisy.Dot(dir);
  272.         float a = atan2f(y, x);
  273.         AddAndMergeSpan(a - gf_PI / 2, a + gf_PI / 2);
  274. }
  275.  
  276. void CAIRadialOccypancy::AddAndMergeSegment(const Vec3& p0, const Vec3& p1)
  277. {
  278.         Vec3 diff;
  279.         float x, y;
  280.  
  281.         diff = p0 - m_center;
  282.         x = m_axisx.Dot(diff);
  283.         y = m_axisy.Dot(diff);
  284.         float a = atan2f(y, x);
  285.  
  286.         diff = p1 - m_center;
  287.         x = m_axisx.Dot(diff);
  288.         y = m_axisy.Dot(diff);
  289.         float b = atan2f(y, x);
  290.  
  291.         float range = b - a;
  292.         if (range > gf_PI)
  293.                 range -= gf_PI2;
  294.         if (range < -gf_PI)
  295.                 range += gf_PI2;
  296.         b = a + range;
  297.  
  298.         if (a > b)
  299.                 std::swap(a, b);
  300.  
  301.         AddAndMergeSpan(a, b);
  302. }
  303.  
  304. inline bool OverlapSegment(float min0, float max0, float min1, float max1, float eps)
  305. {
  306.         if (min0 - eps >= max1) return false;
  307.         if (max0 + eps <= min1) return false;
  308.         return true;
  309. }
  310.  
  311. void CAIRadialOccypancy::AddAndMergeSpan(float a, float b)
  312. {
  313.         float range = b - a;
  314.         a = fmodf(a, gf_PI2);
  315.         if (a < -gf_PI)
  316.                 a += gf_PI2;
  317.  
  318.         float smin[2];
  319.         float smax[2];
  320.  
  321.         unsigned ns = 1;
  322.         smin[0] = a;
  323.         smax[0] = a + range;
  324.         if (smax[0] > gf_PI)
  325.         {
  326.                 smin[1] = -gf_PI;
  327.                 smax[1] = smax[0] - gf_PI2;
  328.                 smax[0] = gf_PI;
  329.                 ++ns;
  330.         }
  331.  
  332.         for (unsigned k = 0; k < ns; ++k)
  333.         {
  334.                 for (unsigned i = 0; i < m_spans.size(); )
  335.                 {
  336.                         if (OverlapSegment(smin[k], smax[k], m_spans[i].smin, m_spans[i].smax, 0.0001f))
  337.                         {
  338.                                 smin[k] = min(smin[k], m_spans[i].smin);
  339.                                 smax[k] = max(smax[k], m_spans[i].smax);
  340.                                 unsigned n = m_spans.size();
  341.                                 if (i + 1 < n)
  342.                                 {
  343.                                         for (unsigned j = i; j < n - 1; ++j)
  344.                                                 m_spans[j] = m_spans[j + 1];
  345.                                 }
  346.                                 m_spans.pop_back();
  347.                         }
  348.                         else
  349.                                 ++i;
  350.                 }
  351.  
  352.                 unsigned mergedIdx = m_spans.size();
  353.                 for (unsigned i = 0; i < m_spans.size(); ++i)
  354.                 {
  355.                         if (m_spans[i].smin > smax[k])
  356.                         {
  357.                                 mergedIdx = i;
  358.                                 break;
  359.                         }
  360.                 }
  361.  
  362.                 m_spans.insert(m_spans.begin() + mergedIdx, SSpan(smin[k], smax[k]));
  363.         }
  364. }
  365.  
  366. bool CAIRadialOccypancy::IntersectSegmentCircle(const Vec3& p0, const Vec3& p1, const Vec3& center, float rad, float& t0, float& t1)
  367. {
  368.         float dx = p1.x - p0.x;
  369.         float dy = p1.y - p0.y;
  370.  
  371.         float a = sqr(dx) + sqr(dy);
  372.         float pdx = p0.x - center.x;
  373.         float pdy = p0.y - center.y;
  374.         float b = (dx * pdx + dy * pdy) * 2.0f;
  375.         float c = sqr(pdx) + sqr(pdy) - sqr(rad);
  376.         float desc = (b * b) - (4 * a * c);
  377.  
  378.         if (desc >= 0.0f)
  379.         {
  380.                 desc = sqrtf(desc);
  381.                 t0 = (-b - desc) / (2.0f * a);
  382.                 t1 = (-b + desc) / (2.0f * a);
  383.                 return true;
  384.         }
  385.         return false;
  386. }
  387.  
  388. void CAIRadialOccypancy::DebugDraw(const Vec3& center, ColorB color)
  389. {
  390.         const unsigned maxpts = 40;
  391.         Vec3 pts[maxpts + 1];
  392.  
  393.         CDebugDrawContext dc;
  394.  
  395.         ColorB colorTrans(color);
  396.         colorTrans.a /= 4;
  397.  
  398.         for (unsigned i = 0, ni = m_spans.size(); i < ni; ++i)
  399.         {
  400.                 const SSpan& span = m_spans[i];
  401.  
  402.                 unsigned npts = (unsigned)ceilf((span.smax - span.smin) / gf_PI2 * (float)maxpts);
  403.                 if (npts < 2) npts = 2;
  404.                 if (npts > maxpts) npts = maxpts;
  405.  
  406.                 for (unsigned j = 0; j < npts; ++j)
  407.                 {
  408.                         const float u = (float)j / (float)(npts - 1);
  409.                         const float a = span.smin + (span.smax - span.smin) * u;
  410.                         pts[j] = m_axisx * (cosf(a) * m_radius) + m_axisy * (sinf(a) * m_radius) + center;
  411.                 }
  412.                 pts[npts] = center;
  413.                 npts++;
  414.  
  415.                 //              for (unsigned j = 0; j < npts-1; ++j)
  416.                 //                      dc->DrawTriangle(center, colorTrans, pts[j+1], colorTrans, pts[j], colorTrans);
  417.  
  418.                 dc->DrawPolyline(pts, npts, true, color, 1.0f);
  419.         }
  420.  
  421.         //      dc->DrawLine(center, ColorB(255,   0, 0), center + m_axisx * m_radius, ColorB(255,   0, 0), 3.0f);
  422.         //      dc->DrawLine(center, ColorB(  0, 255, 0), center + m_axisy * m_radius, ColorB(  0, 255, 0), 3.0f);
  423. }
  424.  
  425. //====================================================================
  426. // CAIRadialOcclusionRaycast
  427. //====================================================================
  428. bool CAIRadialOcclusionRaycast::m_physListenerInit = false;
  429. std::vector<CAIRadialOcclusionRaycast*> CAIRadialOcclusionRaycast::m_physListeners;
  430.  
  431. //====================================================================
  432. // InitPhysCallback
  433. //====================================================================
  434. void CAIRadialOcclusionRaycast::InitPhysCallback(CAIRadialOcclusionRaycast* occ)
  435. {
  436.         if (!m_physListenerInit)
  437.         {
  438.                 gEnv->pPhysicalWorld->AddEventClient(EventPhysRWIResult::id, OnRwiResult, 1);
  439.                 for (unsigned i = 0; i < MAX_QUERIES; ++i)
  440.                 {
  441.                         m_queries[i].id = 0;
  442.                         m_queries[i].i = 0;
  443.                         m_queries[i].pRaycaster = 0;
  444.                 }
  445.                 m_physListenerInit = true;
  446.         }
  447.         std::vector<CAIRadialOcclusionRaycast*>::iterator it = std::find(m_physListeners.begin(), m_physListeners.end(), occ);
  448.         if (it == m_physListeners.end())
  449.                 m_physListeners.push_back(occ);
  450. }
  451.  
  452. //====================================================================
  453. // RemovePhysCallback
  454. //====================================================================
  455. void CAIRadialOcclusionRaycast::RemovePhysCallback(CAIRadialOcclusionRaycast* occ)
  456. {
  457.         if (!occ) return;
  458.         for (unsigned i = 0; i < MAX_QUERIES; ++i)
  459.         {
  460.                 if (m_queries[i].id == occ->m_id)
  461.                 {
  462.                         m_queries[i].id = 0;
  463.                         m_queries[i].i = 0;
  464.                         m_queries[i].pRaycaster = 0;
  465.                 }
  466.         }
  467.         std::vector<CAIRadialOcclusionRaycast*>::iterator it = std::find(m_physListeners.begin(), m_physListeners.end(), occ);
  468.         if (it != m_physListeners.end())
  469.                 m_physListeners.erase(it);
  470. }
  471.  
  472. //====================================================================
  473. // UpdateActiveCount
  474. //====================================================================
  475. void CAIRadialOcclusionRaycast::UpdateActiveCount()
  476. {
  477.         m_activeCount = 0;
  478.         CTimeValue curTime = GetAISystem()->GetFrameStartTime();
  479.         for (unsigned i = 0, ni = m_physListeners.size(); i < ni; ++i)
  480.         {
  481.                 float dt = (curTime - m_physListeners[i]->m_lastUpdatedTime).GetSeconds();
  482.                 if (dt < 0.3f)
  483.                         m_activeCount++;
  484.         }
  485. }
  486.  
  487. #define PHYS_FOREIGN_ID_RADIAL_OCCLUSION PHYS_FOREIGN_ID_USER + 2
  488.  
  489. //====================================================================
  490. // OnRwiResult
  491. //====================================================================
  492. int CAIRadialOcclusionRaycast::OnRwiResult(const EventPhys* pEvent)
  493. {
  494.         EventPhysRWIResult* pRWIResult = (EventPhysRWIResult*)pEvent;
  495.         if (pRWIResult->iForeignData != PHYS_FOREIGN_ID_RADIAL_OCCLUSION)
  496.                 return 1;
  497.  
  498.         SSampleRayQuery* pQuery = (SSampleRayQuery*)pRWIResult->pForeignData;
  499.         if (!pQuery->pRaycaster)
  500.                 return 1;
  501.  
  502.         SSample& sample = pQuery->pRaycaster->m_samples[pQuery->i];
  503.         if (pRWIResult->nHits != 0)
  504.         {
  505.                 sample.dist = pRWIResult->pHits[0].dist;
  506.                 sample.height = pRWIResult->pHits[0].pt.z;
  507.         }
  508.  
  509.         sample.pending = false;
  510.  
  511.         pQuery->id = 0;
  512.         pQuery->i = 0;
  513.         pQuery->pRaycaster = 0;
  514.  
  515.         return 1;
  516. }
  517.  
  518. int CAIRadialOcclusionRaycast::m_idGen = 1;
  519. CAIRadialOcclusionRaycast::SSampleRayQuery CAIRadialOcclusionRaycast::m_queries[MAX_QUERIES];
  520. int CAIRadialOcclusionRaycast::m_activeCount = 0;
  521.  
  522. //====================================================================
  523. // CAIRadialOcclusionRaycast
  524. //====================================================================
  525. CAIRadialOcclusionRaycast::CAIRadialOcclusionRaycast(float depthRange, float heightRange, float spread,
  526.                                                      unsigned width, unsigned height) :
  527.         m_center(0, 0, 0),
  528.         m_target(0, 0, 0),
  529.         m_heightMin(0),
  530.         m_heightMax(0),
  531.         m_spread(spread),
  532.         m_width(width),
  533.         m_height(height),
  534.         m_cx(0),
  535.         m_cy(0),
  536.         m_depthRange(depthRange),
  537.         m_heightRange(heightRange),
  538.         m_firstUpdate(true)
  539. {
  540.         m_basis.SetIdentity();
  541.         m_combined.resize(width);
  542.         m_samples.resize(width * height);
  543.  
  544.         for (unsigned i = 0; i < m_width * m_height; ++i)
  545.         {
  546.                 m_samples[i].dist = 0;
  547.                 m_samples[i].height = 0;
  548.                 m_samples[i].pending = false;
  549.         }
  550.         for (unsigned i = 0; i < m_width; ++i)
  551.                 m_combined[i] = 0.0f;
  552.  
  553.         m_id = m_idGen++;
  554.  
  555. #ifdef USE_ASYNC_RAYCASTS
  556.         InitPhysCallback(this);
  557. #endif
  558. }
  559.  
  560. //====================================================================
  561. // ~CAIRadialOcclusionRaycast
  562. //====================================================================
  563. CAIRadialOcclusionRaycast::~CAIRadialOcclusionRaycast()
  564. {
  565. #ifdef USE_ASYNC_RAYCASTS
  566.         RemovePhysCallback(this);
  567. #endif
  568. }
  569.  
  570. //====================================================================
  571. // Reset
  572. //====================================================================
  573. void CAIRadialOcclusionRaycast::Reset()
  574. {
  575.         m_center.Set(0, 0, 0);
  576.         m_target.Set(0, 0, 0);
  577.         m_basis.SetIdentity();
  578.         m_heightMin = 0.0f;
  579.         m_heightMax = 0.0f;
  580.         m_cx = 0;
  581.         m_cy = 0;
  582.         m_firstUpdate = true;
  583.         for (unsigned i = 0; i < m_width * m_height; ++i)
  584.         {
  585.                 m_samples[i].dist = 0;
  586.                 m_samples[i].height = 0;
  587.                 m_samples[i].pending = false;
  588.         }
  589.         for (unsigned i = 0; i < m_width; ++i)
  590.                 m_combined[i] = 0.0f;
  591. }
  592.  
  593. //====================================================================
  594. // Update
  595. //====================================================================
  596. void CAIRadialOcclusionRaycast::Update(const Vec3& center, const Vec3& target, float unitHeight,
  597.                                        bool flat, unsigned raysPerUpdate)
  598. {
  599.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  600.  
  601.         m_lastUpdatedTime = GetAISystem()->GetFrameStartTime();
  602.  
  603.         m_center = center;
  604.         m_target = target;
  605.  
  606.         if (m_firstUpdate)
  607.         {
  608.                 m_firstUpdate = false;
  609.                 for (unsigned i = 0; i < m_width * m_height; ++i)
  610.                 {
  611.                         m_samples[i].dist = 0;
  612.                         m_samples[i].height = m_center.z;
  613.                 }
  614.                 for (unsigned i = 0; i < m_width; ++i)
  615.                         m_combined[i] = 0.0f;
  616.         }
  617.  
  618.         Vec3 dirToTarget = m_target - m_center;
  619.         if (flat)
  620.         {
  621.                 dirToTarget.z = 0;
  622.         }
  623.         else
  624.         {
  625.                 float len = sqrtf(sqr(dirToTarget.x) + sqr(dirToTarget.y));
  626.                 if (fabsf(dirToTarget.z) > len * 0.25f)
  627.                         dirToTarget.z = (len * 0.25f) * (dirToTarget.z < 0.0f ? -1.0f : 1.0f);
  628.         }
  629.         dirToTarget.NormalizeSafe();
  630.  
  631.         m_basis.SetRotationVDir(dirToTarget);
  632.  
  633.         m_heightMin = FLT_MAX;
  634.         m_heightMax = -FLT_MAX;
  635.  
  636.         // Combine samples into one radial buffer.
  637.         unsigned pendingRays = 0;
  638.         const SSample* src = &m_samples[0];
  639.         float* dst = &m_combined[0];
  640.         for (unsigned ix = 0; ix < m_width; ++ix)
  641.         {
  642.                 *dst = 0.0f;
  643.                 for (unsigned i = 0; i < m_height; ++i)
  644.                 {
  645.                         *dst = max(*dst, src->dist);
  646.                         m_heightMax = max(m_heightMax, src->height);
  647.                         m_heightMin = min(m_heightMin, src->height);
  648.                         if (src->pending)
  649.                                 pendingRays++;
  650.                         src++;
  651.                 }
  652.                 dst++;
  653.         }
  654.  
  655.         // Do not allow to be too greedy.
  656.         raysPerUpdate = clamp_tpl((unsigned)MAX_QUERIES / (unsigned)max(1, m_activeCount), (unsigned)2, raysPerUpdate);
  657.  
  658.         // Update buffer
  659.         if (pendingRays < raysPerUpdate / 4)
  660.         {
  661.                 for (unsigned i = 0; i < raysPerUpdate; ++i)
  662.                 {
  663.                         int idx = m_cx * m_height + m_cy;
  664.  
  665. #ifdef USE_ASYNC_RAYCASTS
  666.                         SSampleRayQuery* pQuery = GetQuery(idx, this);
  667.                         if (!pQuery)
  668.                                 break;
  669. #endif
  670.  
  671.                         float offset = (m_cy & 1) * 0.6f;
  672.                         const float ay = (m_cy + 0.5f - m_height / 2) / (float)m_height;
  673.                         const float ax = (m_cx + 0.5f + offset - m_width / 2) / (float)m_width * m_spread;
  674.  
  675.                         Vec3 dir;
  676.                         dir.x = sinf(ax) * m_depthRange;
  677.                         dir.y = cosf(ax) * m_depthRange;
  678.                         dir.z = m_heightRange * ay - unitHeight * ay;
  679.  
  680.                         Vec3 up(0, 0, unitHeight * ay);
  681.  
  682.                         dir = m_basis.TransformVector(dir);
  683.                         up = m_basis.TransformVector(up);
  684.  
  685.                         SSample* pSample = &m_samples[idx];
  686.  
  687. #ifdef USE_ASYNC_RAYCASTS
  688.                         pSample->dist = m_depthRange * 2.0f;
  689.                         pSample->height = m_center.z + up.z + dir.z;
  690.                         pSample->pending = true;
  691.  
  692.                         gEnv->pPhysicalWorld->RayWorldIntersection(m_center + up, dir,
  693.                                                                    ent_terrain | ent_static | ent_rigid | ent_sleeping_rigid,
  694.                                                                    (geom_colltype_ray << rwi_colltype_bit) | rwi_colltype_any | (10 & rwi_pierceability_mask) | rwi_queue,
  695.                                                                    0, 1, 0, 0, (void*)pQuery, PHYS_FOREIGN_ID_RADIAL_OCCLUSION);
  696. #else
  697.                         ray_hit hit;
  698.                         pSample->dist = m_depthRange * 2.0f;
  699.                         pSample->height = m_center.z + up.z + dir.z;
  700.  
  701.                         if (gEnv->pPhysicalWorld->RayWorldIntersection(m_center + up, dir,
  702.                                                                        ent_terrain | ent_static | ent_rigid | ent_sleeping_rigid,
  703.                                                                        (geom_colltype_ray << rwi_colltype_bit) | rwi_colltype_any | (10 & rwi_pierceability_mask),
  704.                                                                        &hit, 1))
  705.                         {
  706.                                 pSample->dist = hit.dist;
  707.                                 pSample->height = hit.pt.z;
  708.                         }
  709.                         pSample->pending = false;
  710. #endif
  711.  
  712.                         // Update indices
  713.                         m_cx++;
  714.                         if (m_cx >= m_width)
  715.                         {
  716.                                 m_cx = 0;
  717.                                 m_cy++;
  718.                                 if (m_cy >= m_height)
  719.                                         m_cy = 0;
  720.                         }
  721.                 }
  722.         }
  723.  
  724. }
  725.  
  726. //====================================================================
  727. // DebugDraw
  728. //====================================================================
  729. void CAIRadialOcclusionRaycast::DebugDraw(bool drawFilled)
  730. {
  731.         if (m_firstUpdate)
  732.                 return;
  733.  
  734.         std::vector<Vec3> points;
  735.         points.resize(m_width * 2 + 1);
  736.         unsigned n = 1;
  737.         points[0] = m_center;
  738.         points[0].z = m_heightMin;
  739.  
  740.         for (unsigned i = 0; i < m_width; ++i)
  741.         {
  742.                 float ax = (i + 0.5f - m_width / 2) / (float)m_width * m_spread;
  743.                 float d = m_combined[i];
  744.                 Vec3 dir(sinf(ax), cosf(ax), 0.0f);
  745.                 Vec3 norm(dir.y, -dir.x, 0.0f);
  746.                 dir *= d;
  747.                 norm *= tanf(m_spread / (float)m_width * 0.5f) * d;
  748.  
  749.                 if (i == 0 || fabsf(m_combined[i - 1]) > 0.1f)
  750.                 {
  751.                         Vec3 p0(m_center + m_basis.TransformVector(dir - norm));
  752.                         p0.z = m_heightMin + 0.1f;
  753.                         points[n++] = p0;
  754.                 }
  755.                 {
  756.                         Vec3 p1(m_center + m_basis.TransformVector(dir + norm));
  757.                         p1.z = m_heightMin + 0.1f;
  758.                         points[n++] = p1;
  759.                 }
  760.         }
  761.         if (n > 1)
  762.         {
  763.                 if (drawFilled)
  764.                 {
  765.                         CDebugDrawContext dc;
  766.                         dc->SetAlphaBlended(true);
  767.                         dc->SetBackFaceCulling(false);
  768.  
  769.                         Vec3 p0 = points[1];
  770.                         p0.z = m_heightMin;
  771.                         Vec3 p1 = points[1];
  772.                         p1.z = m_heightMax;
  773.                         for (unsigned i = 2; i < n; ++i)
  774.                         {
  775.                                 Vec3 q0 = points[i];
  776.                                 q0.z = m_heightMin;
  777.                                 Vec3 q1 = points[i];
  778.                                 q1.z = m_heightMax;
  779.                                 dc->DrawTriangle(p0, ColorB(255, 0, 0, 32), p1, ColorB(255, 0, 0, 128), q1, ColorB(255, 0, 0, 128));
  780.                                 dc->DrawTriangle(p0, ColorB(255, 0, 0, 32), q1, ColorB(255, 0, 0, 128), q0, ColorB(255, 0, 0, 32));
  781.                                 p0 = q0;
  782.                                 p1 = q1;
  783.                         }
  784.                 }
  785.  
  786.                 CDebugDrawContext dc;
  787.                 dc->DrawPolyline(&points[0], n, true, ColorB(255, 0, 0), 3.0f);
  788.         }
  789. }
  790.  
downloadAIRadialOcclusion.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