123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- //
- // Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
- //
- // This software is provided 'as-is', without any express or implied
- // warranty. In no event will the authors be held liable for any damages
- // arising from the use of this software.
- // Permission is granted to anyone to use this software for any purpose,
- // including commercial applications, and to alter it and redistribute it
- // freely, subject to the following restrictions:
- // 1. The origin of this software must not be misrepresented; you must not
- // claim that you wrote the original software. If you use this software
- // in a product, an acknowledgment in the product documentation would be
- // appreciated but is not required.
- // 2. Altered source versions must be plainly marked as such, and must not be
- // misrepresented as being the original software.
- // 3. This notice may not be removed or altered from any source distribution.
- //
- #include <float.h>
- #include <string.h>
- #include "DetourLocalBoundary.h"
- #include "DetourNavMeshQuery.h"
- #include "DetourCommon.h"
- #include "DetourAssert.h"
- dtLocalBoundary::dtLocalBoundary() :
- m_nsegs(0),
- m_npolys(0)
- {
- dtVset(m_center, FLT_MAX,FLT_MAX,FLT_MAX);
- }
- dtLocalBoundary::~dtLocalBoundary()
- {
- }
- void dtLocalBoundary::reset()
- {
- dtVset(m_center, FLT_MAX,FLT_MAX,FLT_MAX);
- m_npolys = 0;
- m_nsegs = 0;
- }
- void dtLocalBoundary::addSegment(const float dist, const float* s)
- {
- // Insert neighbour based on the distance.
- Segment* seg = 0;
- if (!m_nsegs)
- {
- // First, trivial accept.
- seg = &m_segs[0];
- }
- else if (dist >= m_segs[m_nsegs-1].d)
- {
- // Further than the last segment, skip.
- if (m_nsegs >= MAX_LOCAL_SEGS)
- return;
- // Last, trivial accept.
- seg = &m_segs[m_nsegs];
- }
- else
- {
- // Insert inbetween.
- int i;
- for (i = 0; i < m_nsegs; ++i)
- if (dist <= m_segs[i].d)
- break;
- const int tgt = i+1;
- const int n = dtMin(m_nsegs-i, MAX_LOCAL_SEGS-tgt);
- dtAssert(tgt+n <= MAX_LOCAL_SEGS);
- if (n > 0)
- memmove(&m_segs[tgt], &m_segs[i], sizeof(Segment)*n);
- seg = &m_segs[i];
- }
-
- seg->d = dist;
- memcpy(seg->s, s, sizeof(float)*6);
-
- if (m_nsegs < MAX_LOCAL_SEGS)
- m_nsegs++;
- }
- void dtLocalBoundary::update(dtPolyRef ref, const float* pos, const float collisionQueryRange,
- dtNavMeshQuery* navquery, const dtQueryFilter* filter)
- {
- static const int MAX_SEGS_PER_POLY = DT_VERTS_PER_POLYGON*3;
-
- if (!ref)
- {
- dtVset(m_center, FLT_MAX,FLT_MAX,FLT_MAX);
- m_nsegs = 0;
- m_npolys = 0;
- return;
- }
-
- dtVcopy(m_center, pos);
-
- // First query non-overlapping polygons.
- navquery->findLocalNeighbourhood(ref, pos, collisionQueryRange,
- filter, m_polys, 0, &m_npolys, MAX_LOCAL_POLYS);
-
- // Secondly, store all polygon edges.
- m_nsegs = 0;
- float segs[MAX_SEGS_PER_POLY*6];
- int nsegs = 0;
- for (int j = 0; j < m_npolys; ++j)
- {
- navquery->getPolyWallSegments(m_polys[j], filter, segs, 0, &nsegs, MAX_SEGS_PER_POLY);
- for (int k = 0; k < nsegs; ++k)
- {
- const float* s = &segs[k*6];
- // Skip too distant segments.
- float tseg;
- const float distSqr = dtDistancePtSegSqr2D(pos, s, s+3, tseg);
- if (distSqr > dtSqr(collisionQueryRange))
- continue;
- addSegment(distSqr, s);
- }
- }
- }
- bool dtLocalBoundary::isValid(dtNavMeshQuery* navquery, const dtQueryFilter* filter)
- {
- if (!m_npolys)
- return false;
-
- // Check that all polygons still pass query filter.
- for (int i = 0; i < m_npolys; ++i)
- {
- if (!navquery->isValidPolyRef(m_polys[i], filter))
- return false;
- }
-
- return true;
- }
|