Collect neighbours once and use them in local avoidance and collision detection. Moved movement request update to separate function.
This commit is contained in:
parent
347071a563
commit
7e69ce1296
@ -749,6 +749,7 @@ int CrowdManager::addAgent(const float* pos, const float radius, const float hei
|
|||||||
ag->height = height;
|
ag->height = height;
|
||||||
ag->collisionQueryRange = radius * 8;
|
ag->collisionQueryRange = radius * 8;
|
||||||
ag->pathOptimizationRange = radius * 30;
|
ag->pathOptimizationRange = radius * 30;
|
||||||
|
ag->nneis = 0;
|
||||||
|
|
||||||
dtVset(ag->dvel, 0,0,0);
|
dtVset(ag->dvel, 0,0,0);
|
||||||
dtVset(ag->nvel, 0,0,0);
|
dtVset(ag->nvel, 0,0,0);
|
||||||
@ -822,8 +823,49 @@ int CrowdManager::getActiveAgents(Agent** agents, const int maxAgents)
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int addNeighbour(const int idx, const float dist,
|
||||||
|
Neighbour* neis, const int nneis, const int maxNeis)
|
||||||
|
{
|
||||||
|
// Insert neighbour based on the distance.
|
||||||
|
Neighbour* nei = 0;
|
||||||
|
if (!nneis)
|
||||||
|
{
|
||||||
|
nei = &neis[nneis];
|
||||||
|
}
|
||||||
|
else if (dist >= neis[nneis-1].dist)
|
||||||
|
{
|
||||||
|
if (nneis >= maxNeis)
|
||||||
|
return nneis;
|
||||||
|
nei = &neis[nneis];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < nneis; ++i)
|
||||||
|
if (dist <= neis[i].dist)
|
||||||
|
break;
|
||||||
|
|
||||||
|
const int tgt = i+1;
|
||||||
|
const int n = dtMin(nneis-i, maxNeis-tgt);
|
||||||
|
|
||||||
|
dtAssert(tgt+n <= maxNeis);
|
||||||
|
|
||||||
|
if (n > 0)
|
||||||
|
memmove(&neis[tgt], &neis[i], sizeof(Neighbour)*n);
|
||||||
|
nei = &neis[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(nei, 0, sizeof(Neighbour));
|
||||||
|
|
||||||
|
nei->idx = idx;
|
||||||
|
nei->dist = dist;
|
||||||
|
|
||||||
|
return dtMin(nneis+1, maxNeis);
|
||||||
|
}
|
||||||
|
|
||||||
int CrowdManager::getNeighbours(const float* pos, const float height, const float range,
|
int CrowdManager::getNeighbours(const float* pos, const float height, const float range,
|
||||||
const Agent* skip, Agent** result, const int maxResult)
|
const Agent* skip, Neighbour* result, const int maxResult)
|
||||||
{
|
{
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
@ -838,6 +880,7 @@ int CrowdManager::getNeighbours(const float* pos, const float height, const floa
|
|||||||
|
|
||||||
if (ag == skip) continue;
|
if (ag == skip) continue;
|
||||||
|
|
||||||
|
// Check for overlap.
|
||||||
float diff[3];
|
float diff[3];
|
||||||
dtVsub(diff, pos, ag->npos);
|
dtVsub(diff, pos, ag->npos);
|
||||||
if (fabsf(diff[1]) >= (height+ag->height)/2.0f)
|
if (fabsf(diff[1]) >= (height+ag->height)/2.0f)
|
||||||
@ -847,36 +890,20 @@ int CrowdManager::getNeighbours(const float* pos, const float height, const floa
|
|||||||
if (distSqr > dtSqr(range))
|
if (distSqr > dtSqr(range))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (n < maxResult)
|
n = addNeighbour(ids[i], distSqr, result, n, maxResult);
|
||||||
result[n++] = ag;
|
|
||||||
}
|
}
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CrowdManager::update(const float dt, unsigned int flags, dtNavMeshQuery* navquery)
|
void CrowdManager::updateMoveRequest(const float dt, dtNavMeshQuery* navquery)
|
||||||
{
|
{
|
||||||
m_sampleCount = 0;
|
|
||||||
m_totalTime = 0;
|
|
||||||
m_rvoTime = 0;
|
|
||||||
|
|
||||||
if (!navquery)
|
|
||||||
return;
|
|
||||||
|
|
||||||
TimeVal startTime = getPerfTime();
|
|
||||||
|
|
||||||
Agent* agents[MAX_AGENTS];
|
|
||||||
Agent* neis[MAX_AGENTS];
|
|
||||||
int nagents = getActiveAgents(agents, MAX_AGENTS);
|
|
||||||
|
|
||||||
static const float MAX_ACC = 8.0f;
|
|
||||||
static const float MAX_SPEED = 3.5f;
|
|
||||||
|
|
||||||
// Update move requests.
|
// Update move requests.
|
||||||
for (int i = 0; i < m_moveRequestCount; ++i)
|
for (int i = 0; i < m_moveRequestCount; ++i)
|
||||||
{
|
{
|
||||||
MoveRequest* req = &m_moveRequests[i];
|
MoveRequest* req = &m_moveRequests[i];
|
||||||
Agent* ag = &m_agents[req->idx];
|
Agent* ag = &m_agents[req->idx];
|
||||||
|
|
||||||
|
// Agent not active anymore, kill request.
|
||||||
if (!ag->active)
|
if (!ag->active)
|
||||||
req->state = MR_TARGET_FAILED;
|
req->state = MR_TARGET_FAILED;
|
||||||
|
|
||||||
@ -990,7 +1017,27 @@ void CrowdManager::update(const float dt, unsigned int flags, dtNavMeshQuery* na
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_pathq.update(navquery);
|
m_pathq.update(navquery);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CrowdManager::update(const float dt, unsigned int flags, dtNavMeshQuery* navquery)
|
||||||
|
{
|
||||||
|
m_sampleCount = 0;
|
||||||
|
m_totalTime = 0;
|
||||||
|
m_rvoTime = 0;
|
||||||
|
|
||||||
|
if (!navquery)
|
||||||
|
return;
|
||||||
|
|
||||||
|
TimeVal startTime = getPerfTime();
|
||||||
|
|
||||||
|
Agent* agents[MAX_AGENTS];
|
||||||
|
int nagents = getActiveAgents(agents, MAX_AGENTS);
|
||||||
|
|
||||||
|
static const float MAX_ACC = 8.0f;
|
||||||
|
static const float MAX_SPEED = 3.5f;
|
||||||
|
|
||||||
|
// Update async move request and path finder.
|
||||||
|
updateMoveRequest(dt, navquery);
|
||||||
|
|
||||||
// Register agents to proximity grid.
|
// Register agents to proximity grid.
|
||||||
m_grid.clear();
|
m_grid.clear();
|
||||||
@ -999,19 +1046,17 @@ void CrowdManager::update(const float dt, unsigned int flags, dtNavMeshQuery* na
|
|||||||
Agent* ag = agents[i];
|
Agent* ag = agents[i];
|
||||||
const float* p = ag->npos;
|
const float* p = ag->npos;
|
||||||
const float r = ag->radius;
|
const float r = ag->radius;
|
||||||
const float minx = p[0] - r;
|
m_grid.addItem((unsigned short)i, p[0]-r, p[2]-r, p[0]+r, p[2]+r);
|
||||||
const float miny = p[2] - r;
|
|
||||||
const float maxx = p[0] + r;
|
|
||||||
const float maxy = p[2] + r;
|
|
||||||
m_grid.addItem((unsigned short)i, minx, miny, maxx, maxy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get nearby navmesh segments and agents to collide with.
|
||||||
// Get nearby navmesh segments to collide with.
|
|
||||||
for (int i = 0; i < nagents; ++i)
|
for (int i = 0; i < nagents; ++i)
|
||||||
{
|
{
|
||||||
Agent* ag = agents[i];
|
Agent* ag = agents[i];
|
||||||
|
// Update collision segments
|
||||||
ag->corridor.updateLocalNeighbourhood(ag->collisionQueryRange, navquery, &m_filter);
|
ag->corridor.updateLocalNeighbourhood(ag->collisionQueryRange, navquery, &m_filter);
|
||||||
|
// Query neighbour agents
|
||||||
|
ag->nneis = getNeighbours(ag->npos, ag->height, ag->collisionQueryRange, ag, ag->neis, MAX_NEIGHBOURS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find next corner to steer to.
|
// Find next corner to steer to.
|
||||||
@ -1034,8 +1079,6 @@ void CrowdManager::update(const float dt, unsigned int flags, dtNavMeshQuery* na
|
|||||||
else
|
else
|
||||||
ag->corridor.calcStraightSteerDirection(dvel);
|
ag->corridor.calcStraightSteerDirection(dvel);
|
||||||
|
|
||||||
// Calculate steering speed.
|
|
||||||
|
|
||||||
// Calculate speed scale, which tells the agent to slowdown at the end of the path.
|
// Calculate speed scale, which tells the agent to slowdown at the end of the path.
|
||||||
const float slowDownRadius = ag->radius*2; // TODO: make less hacky.
|
const float slowDownRadius = ag->radius*2; // TODO: make less hacky.
|
||||||
const float speedScale = ag->corridor.getDistanceToGoal(slowDownRadius) / slowDownRadius;
|
const float speedScale = ag->corridor.getDistanceToGoal(slowDownRadius) / slowDownRadius;
|
||||||
@ -1080,11 +1123,10 @@ void CrowdManager::update(const float dt, unsigned int flags, dtNavMeshQuery* na
|
|||||||
{
|
{
|
||||||
m_obstacleQuery->reset();
|
m_obstacleQuery->reset();
|
||||||
|
|
||||||
// Find neighbours and add them as obstacles.
|
// Add neighbours as obstacles.
|
||||||
const int nneis = getNeighbours(ag->npos, ag->height, ag->collisionQueryRange, ag, neis, MAX_AGENTS);
|
for (int j = 0; j < ag->nneis; ++j)
|
||||||
for (int j = 0; j < nneis; ++j)
|
|
||||||
{
|
{
|
||||||
const Agent* nei = neis[j];
|
const Agent* nei = &m_agents[ag->neis[j].idx];
|
||||||
m_obstacleQuery->addCircle(nei->npos, nei->radius, nei->vel, nei->dvel,
|
m_obstacleQuery->addCircle(nei->npos, nei->radius, nei->vel, nei->dvel,
|
||||||
dtVdist2DSqr(ag->npos, nei->npos));
|
dtVdist2DSqr(ag->npos, nei->npos));
|
||||||
}
|
}
|
||||||
@ -1100,7 +1142,7 @@ void CrowdManager::update(const float dt, unsigned int flags, dtNavMeshQuery* na
|
|||||||
m_obstacleQuery->addSegment(s, s+3, distSqr);
|
m_obstacleQuery->addSegment(s, s+3, distSqr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sample new safe velocity.
|
||||||
bool adaptive = true;
|
bool adaptive = true;
|
||||||
|
|
||||||
if (adaptive)
|
if (adaptive)
|
||||||
@ -1144,10 +1186,9 @@ void CrowdManager::update(const float dt, unsigned int flags, dtNavMeshQuery* na
|
|||||||
|
|
||||||
float w = 0;
|
float w = 0;
|
||||||
|
|
||||||
for (int j = 0; j < nagents; ++j)
|
for (int j = 0; j < ag->nneis; ++j)
|
||||||
{
|
{
|
||||||
if (i == j) continue;
|
const Agent* nei = &m_agents[ag->neis[j].idx];
|
||||||
Agent* nei = agents[j];
|
|
||||||
|
|
||||||
float diff[3];
|
float diff[3];
|
||||||
dtVsub(diff, ag->npos, nei->npos);
|
dtVsub(diff, ag->npos, nei->npos);
|
||||||
@ -1193,9 +1234,9 @@ void CrowdManager::update(const float dt, unsigned int flags, dtNavMeshQuery* na
|
|||||||
dtVcopy(ag->npos, ag->corridor.getPos());
|
dtVcopy(ag->npos, ag->corridor.getPos());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TimeVal endTime = getPerfTime();
|
TimeVal endTime = getPerfTime();
|
||||||
|
|
||||||
|
// Debug/demo book keeping
|
||||||
int ns = 0;
|
int ns = 0;
|
||||||
for (int i = 0; i < nagents; ++i)
|
for (int i = 0; i < nagents; ++i)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user