getPolyWallSegments can return both walls and portals. Added userData pointer to dtCrowdAgent.

This commit is contained in:
Mikko Mononen 2011-02-11 08:43:05 +00:00
parent 1080b6c249
commit fdb4ad30f7
5 changed files with 86 additions and 33 deletions

View File

@ -304,14 +304,18 @@ public:
int* resultCount, const int maxResult) const;
// Returns wall segments of specified polygon.
// If 'segmentRefs' is specified, both the wall and portal segments are returned.
// Wall segments will have null (0) polyref, and portal segments store the polygon they lead to.
// Params:
// ref - (in) ref to the polygon.
// filter - (in) path polygon filter.
// segments[6*maxSegments] - (out) wall segments (2 endpoints per segment).
// segmentVerts[6*maxSegments] - (out) wall segments (2 endpoints per segment).
// segmentRefs[maxSegments] - (out,opt) reference to a neighbour.
// segmentCount - (out) number of wall segments.
// maxSegments - (in) max number of segments that can be stored in 'segments'.
dtStatus getPolyWallSegments(dtPolyRef ref, const dtQueryFilter* filter,
float* segments, int* segmentCount, const int maxSegments) const;
float* segmentVerts, dtPolyRef* segmentRefs, int* segmentCount,
const int maxSegments) const;
// Returns closest point on navigation polygon.
// Uses detail polygons to find the closest point to the navigation polygon surface.

View File

@ -2353,11 +2353,12 @@ dtStatus dtNavMeshQuery::findLocalNeighbourhood(dtPolyRef startRef, const float*
struct dtSegInterval
{
dtPolyRef ref;
short tmin, tmax;
};
static void insertInterval(dtSegInterval* ints, int& nints, const int maxInts,
const short tmin, const short tmax)
const short tmin, const short tmax, const dtPolyRef ref)
{
if (nints+1 > maxInts) return;
// Find insertion point.
@ -2372,13 +2373,15 @@ static void insertInterval(dtSegInterval* ints, int& nints, const int maxInts,
if (nints-idx)
memmove(ints+idx+1, ints+idx, sizeof(dtSegInterval)*(nints-idx));
// Store
ints[idx].ref = ref;
ints[idx].tmin = tmin;
ints[idx].tmax = tmax;
nints++;
}
dtStatus dtNavMeshQuery::getPolyWallSegments(dtPolyRef ref, const dtQueryFilter* filter,
float* segments, int* segmentCount, const int maxSegments) const
float* segmentVerts, dtPolyRef* segmentRefs, int* segmentCount,
const int maxSegments) const
{
dtAssert(m_nav);
@ -2394,6 +2397,8 @@ dtStatus dtNavMeshQuery::getPolyWallSegments(dtPolyRef ref, const dtQueryFilter*
dtSegInterval ints[MAX_INTERVAL];
int nints;
const bool storePortals = segmentRefs != 0;
dtStatus status = DT_SUCCESS;
for (int i = 0, j = (int)poly->vertCount-1; i < (int)poly->vertCount; j = i++)
@ -2415,58 +2420,91 @@ dtStatus dtNavMeshQuery::getPolyWallSegments(dtPolyRef ref, const dtQueryFilter*
m_nav->getTileAndPolyByRefUnsafe(link->ref, &neiTile, &neiPoly);
if (filter->passFilter(link->ref, neiTile, neiPoly))
{
insertInterval(ints, nints, MAX_INTERVAL, link->bmin, link->bmax);
insertInterval(ints, nints, MAX_INTERVAL, link->bmin, link->bmax, link->ref);
}
}
}
}
}
else if (poly->neis[j])
else
{
// Internal edge
dtPolyRef ref = 0;
if (poly->neis[j])
{
const unsigned int idx = (unsigned int)(poly->neis[j]-1);
const dtPolyRef ref = m_nav->getPolyRefBase(tile) | idx;
if (filter->passFilter(ref, tile, &tile->polys[idx]))
ref = m_nav->getPolyRefBase(tile) | idx;
if (!filter->passFilter(ref, tile, &tile->polys[idx]))
ref = 0;
}
// If the edge leads to another polygon and portals are not stored, skip.
if (ref != 0 && !storePortals)
continue;
if (n < maxSegments)
{
const float* vj = &tile->verts[poly->verts[j]*3];
const float* vi = &tile->verts[poly->verts[i]*3];
float* seg = &segmentVerts[n*6];
dtVcopy(seg+0, vj);
dtVcopy(seg+3, vi);
if (segmentRefs)
segmentRefs[n] = ref;
n++;
}
else
{
status |= DT_BUFFER_TOO_SMALL;
}
continue;
}
// Add sentinels
insertInterval(ints, nints, MAX_INTERVAL, -1, 0);
insertInterval(ints, nints, MAX_INTERVAL, 255, 256);
insertInterval(ints, nints, MAX_INTERVAL, -1, 0, 0);
insertInterval(ints, nints, MAX_INTERVAL, 255, 256, 0);
// Store segment.
// Store segments.
const float* vj = &tile->verts[poly->verts[j]*3];
const float* vi = &tile->verts[poly->verts[i]*3];
for (int k = 1; k < nints; ++k)
{
// Find the space inbetween the opening areas.
const int imin = ints[k-1].tmax;
const int imax = ints[k].tmin;
if (imin == imax) continue;
if (imin == 0 && imax == 255)
// Portal segment.
if (storePortals && ints[k].ref)
{
const float tmin = ints[k].tmin/255.0f;
const float tmax = ints[k].tmax/255.0f;
if (n < maxSegments)
{
float* seg = &segments[n*6];
float* seg = &segmentVerts[n*6];
dtVlerp(seg+0, vj,vi, tmin);
dtVlerp(seg+3, vj,vi, tmax);
if (segmentRefs)
segmentRefs[n] = ints[k].ref;
n++;
dtVcopy(seg+0, vj);
dtVcopy(seg+3, vi);
}
else
{
status |= DT_BUFFER_TOO_SMALL;
}
}
else
// Wall segment.
const int imin = ints[k-1].tmax;
const int imax = ints[k].tmin;
if (imin != imax)
{
const float tmin = imin/255.0f;
const float tmax = imax/255.0f;
if (n < maxSegments)
{
float* seg = &segments[n*6];
n++;
float* seg = &segmentVerts[n*6];
dtVlerp(seg+0, vj,vi, tmin);
dtVlerp(seg+3, vj,vi, tmax);
if (segmentRefs)
segmentRefs[n] = 0;
n++;
}
else
{

View File

@ -106,7 +106,7 @@ void dtLocalBoundary::update(dtPolyRef ref, const float* pos, const float collis
int nsegs = 0;
for (int j = 0; j < nlocals; ++j)
{
navquery->getPolyWallSegments(locals[j], filter, segs, &nsegs, MAX_SEGS_PER_POLY);
navquery->getPolyWallSegments(locals[j], filter, segs, 0, &nsegs, MAX_SEGS_PER_POLY);
for (int k = 0; k < nsegs; ++k)
{
const float* s = &segs[k*6];

View File

@ -1127,10 +1127,12 @@ void NavMeshTesterTool::handleRender()
dd.depthMask(true);
}
static const int MAX_SEGS = DT_VERTS_PER_POLYGON*2;
static const int MAX_SEGS = DT_VERTS_PER_POLYGON*4;
float segs[MAX_SEGS*6];
dtPolyRef refs[MAX_SEGS];
memset(refs, 0, sizeof(dtPolyRef)*MAX_SEGS);
int nsegs = 0;
m_navQuery->getPolyWallSegments(m_polys[i], &m_filter, segs, &nsegs, MAX_SEGS);
m_navQuery->getPolyWallSegments(m_polys[i], &m_filter, segs, refs, &nsegs, MAX_SEGS);
dd.begin(DU_DRAW_LINES, 2.0f);
for (int j = 0; j < nsegs; ++j)
{
@ -1152,16 +1154,25 @@ void NavMeshTesterTool::handleRender()
dtVmad(p1, p0, norm, agentRadius*0.5f);
// Skip backfacing segments.
unsigned int col = duRGBA(255,255,255,192);
if (refs[j])
{
unsigned int col = duRGBA(255,255,255,32);
dd.vertex(s[0],s[1]+agentClimb,s[2],col);
dd.vertex(s[3],s[4]+agentClimb,s[5],col);
}
else
{
unsigned int col = duRGBA(192,32,16,192);
if (dtTriArea2D(m_spos, s, s+3) < 0.0f)
col = duRGBA(255,255,255,64);
col = duRGBA(96,32,16,192);
dd.vertex(p0[0],p0[1]+agentClimb,p0[2],duRGBA(0,0,0,128));
dd.vertex(p1[0],p1[1]+agentClimb,p1[2],duRGBA(0,0,0,128));
dd.vertex(p0[0],p0[1]+agentClimb,p0[2],col);
dd.vertex(p1[0],p1[1]+agentClimb,p1[2],col);
dd.vertex(s[0],s[1]+agentClimb,s[2],col);
dd.vertex(s[3],s[4]+agentClimb,s[5],col);
}
}
dd.end();
dd.depthMask(true);