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; int* resultCount, const int maxResult) const;
// Returns wall segments of specified polygon. // 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: // Params:
// ref - (in) ref to the polygon. // ref - (in) ref to the polygon.
// filter - (in) path polygon filter. // 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. // segmentCount - (out) number of wall segments.
// maxSegments - (in) max number of segments that can be stored in 'segments'. // maxSegments - (in) max number of segments that can be stored in 'segments'.
dtStatus getPolyWallSegments(dtPolyRef ref, const dtQueryFilter* filter, 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. // Returns closest point on navigation polygon.
// Uses detail polygons to find the closest point to the navigation polygon surface. // 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 struct dtSegInterval
{ {
dtPolyRef ref;
short tmin, tmax; short tmin, tmax;
}; };
static void insertInterval(dtSegInterval* ints, int& nints, const int maxInts, 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; if (nints+1 > maxInts) return;
// Find insertion point. // Find insertion point.
@ -2372,13 +2373,15 @@ static void insertInterval(dtSegInterval* ints, int& nints, const int maxInts,
if (nints-idx) if (nints-idx)
memmove(ints+idx+1, ints+idx, sizeof(dtSegInterval)*(nints-idx)); memmove(ints+idx+1, ints+idx, sizeof(dtSegInterval)*(nints-idx));
// Store // Store
ints[idx].ref = ref;
ints[idx].tmin = tmin; ints[idx].tmin = tmin;
ints[idx].tmax = tmax; ints[idx].tmax = tmax;
nints++; nints++;
} }
dtStatus dtNavMeshQuery::getPolyWallSegments(dtPolyRef ref, const dtQueryFilter* filter, 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); dtAssert(m_nav);
@ -2394,6 +2397,8 @@ dtStatus dtNavMeshQuery::getPolyWallSegments(dtPolyRef ref, const dtQueryFilter*
dtSegInterval ints[MAX_INTERVAL]; dtSegInterval ints[MAX_INTERVAL];
int nints; int nints;
const bool storePortals = segmentRefs != 0;
dtStatus status = DT_SUCCESS; dtStatus status = DT_SUCCESS;
for (int i = 0, j = (int)poly->vertCount-1; i < (int)poly->vertCount; j = i++) 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); m_nav->getTileAndPolyByRefUnsafe(link->ref, &neiTile, &neiPoly);
if (filter->passFilter(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 // Internal edge
const unsigned int idx = (unsigned int)(poly->neis[j]-1); dtPolyRef ref = 0;
const dtPolyRef ref = m_nav->getPolyRefBase(tile) | idx; if (poly->neis[j])
if (filter->passFilter(ref, tile, &tile->polys[idx])) {
const unsigned int idx = (unsigned int)(poly->neis[j]-1);
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; 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 // Add sentinels
insertInterval(ints, nints, MAX_INTERVAL, -1, 0); insertInterval(ints, nints, MAX_INTERVAL, -1, 0, 0);
insertInterval(ints, nints, MAX_INTERVAL, 255, 256); insertInterval(ints, nints, MAX_INTERVAL, 255, 256, 0);
// Store segment. // Store segments.
const float* vj = &tile->verts[poly->verts[j]*3]; const float* vj = &tile->verts[poly->verts[j]*3];
const float* vi = &tile->verts[poly->verts[i]*3]; const float* vi = &tile->verts[poly->verts[i]*3];
for (int k = 1; k < nints; ++k) for (int k = 1; k < nints; ++k)
{ {
// Find the space inbetween the opening areas. // Portal segment.
const int imin = ints[k-1].tmax; if (storePortals && ints[k].ref)
const int imax = ints[k].tmin;
if (imin == imax) continue;
if (imin == 0 && imax == 255)
{ {
const float tmin = ints[k].tmin/255.0f;
const float tmax = ints[k].tmax/255.0f;
if (n < maxSegments) 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++; n++;
dtVcopy(seg+0, vj);
dtVcopy(seg+3, vi);
} }
else else
{ {
status |= DT_BUFFER_TOO_SMALL; 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 tmin = imin/255.0f;
const float tmax = imax/255.0f; const float tmax = imax/255.0f;
if (n < maxSegments) if (n < maxSegments)
{ {
float* seg = &segments[n*6]; float* seg = &segmentVerts[n*6];
n++;
dtVlerp(seg+0, vj,vi, tmin); dtVlerp(seg+0, vj,vi, tmin);
dtVlerp(seg+3, vj,vi, tmax); dtVlerp(seg+3, vj,vi, tmax);
if (segmentRefs)
segmentRefs[n] = 0;
n++;
} }
else else
{ {

View File

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

View File

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