I would like to submit a query filter for each agent type:

https://groups.google.com/forum/#!searchin/recastnavigation/dtQueryFilter|sort:relevance|spell:false/recastnavigation/t-rFg2Ku9IY/PJNNkCjARccJ

Search on
queryFilterType and m_filters to see the changes.

Also in this code there are bugfixes, that have already been submitted
as issues. They can be ignored.

Possible bug with requestMoveVelocity and navmesh regeneration
https://groups.google.com/forum/#!topic/recastnavigation/E6khmmKJkzk

Bug fix for No guard on dtCrowd::getAgent?
https://groups.google.com/forum/#!topic/recastnavigation/yJ1EEVbOaKg
This commit is contained in:
JimmyJames707 2014-04-11 16:50:57 +10:00
parent 740a7ba516
commit 0f2b03a8c0
2 changed files with 63 additions and 23 deletions

View File

@ -87,6 +87,9 @@ struct dtCrowdAgentParams
/// [Limits: 0 <= value <= #DT_CROWD_MAX_OBSTAVOIDANCE_PARAMS] /// [Limits: 0 <= value <= #DT_CROWD_MAX_OBSTAVOIDANCE_PARAMS]
unsigned char obstacleAvoidanceType; unsigned char obstacleAvoidanceType;
// [F]
unsigned char queryFilterType;
/// User defined data attached to the agent. /// User defined data attached to the agent.
void* userData; void* userData;
}; };
@ -102,6 +105,9 @@ enum MoveRequestState
DT_CROWDAGENT_TARGET_VELOCITY, DT_CROWDAGENT_TARGET_VELOCITY,
}; };
// [F]
static const int DT_CROWD_MAX_QUERY_FILTER_TYPE = 16;
/// Represents an agent managed by a #dtCrowd object. /// Represents an agent managed by a #dtCrowd object.
/// @ingroup crowd /// @ingroup crowd
struct dtCrowdAgent struct dtCrowdAgent
@ -157,6 +163,9 @@ struct dtCrowdAgent
dtPathQueueRef targetPathqRef; ///< Path finder ref. dtPathQueueRef targetPathqRef; ///< Path finder ref.
bool targetReplan; ///< Flag indicating that the current path is being replanned. bool targetReplan; ///< Flag indicating that the current path is being replanned.
float targetReplanTime; /// <Time since the agent's target was replanned. float targetReplanTime; /// <Time since the agent's target was replanned.
// [F]
unsigned char queryFilterType;
}; };
struct dtCrowdAgentAnimation struct dtCrowdAgentAnimation
@ -190,6 +199,8 @@ struct dtCrowdAgentDebugInfo
/// @ingroup crowd /// @ingroup crowd
class dtCrowd class dtCrowd
{ {
public:
int m_maxAgents; int m_maxAgents;
dtCrowdAgent* m_agents; dtCrowdAgent* m_agents;
dtCrowdAgent** m_activeAgents; dtCrowdAgent** m_activeAgents;
@ -206,7 +217,9 @@ class dtCrowd
int m_maxPathResult; int m_maxPathResult;
float m_ext[3]; float m_ext[3];
dtQueryFilter m_filter; //dtQueryFilter m_filter;
// [F]
dtQueryFilter m_filters[DT_CROWD_MAX_QUERY_FILTER_TYPE];
float m_maxAgentRadius; float m_maxAgentRadius;
@ -249,7 +262,7 @@ public:
/// Gets the specified agent from the pool. /// Gets the specified agent from the pool.
/// @param[in] idx The agent index. [Limits: 0 <= value < #getAgentCount()] /// @param[in] idx The agent index. [Limits: 0 <= value < #getAgentCount()]
/// @return The requested agent. /// @return The requested agent.
const dtCrowdAgent* getAgent(const int idx); dtCrowdAgent* getAgent(const int idx);
/// The maximum number of agents that can be managed by the object. /// The maximum number of agents that can be managed by the object.
/// @return The maximum number of agents. /// @return The maximum number of agents.
@ -301,11 +314,17 @@ public:
/// Gets the filter used by the crowd. /// Gets the filter used by the crowd.
/// @return The filter used by the crowd. /// @return The filter used by the crowd.
const dtQueryFilter* getFilter() const { return &m_filter; } //const dtQueryFilter* getFilter() const { return &m_filter; }
// [F]
//const dtQueryFilter* getFilter() const {return &m_filters[0];}
const dtQueryFilter* getIndexedFilter(const int i = 0) const { return (i >= 0 && i < DT_CROWD_MAX_QUERY_FILTER_TYPE) ? &m_filters[i] : 0; }
/// Gets the filter used by the crowd. /// Gets the filter used by the crowd.
/// @return The filter used by the crowd. /// @return The filter used by the crowd.
dtQueryFilter* getEditableFilter() { return &m_filter; } //dtQueryFilter* getEditableFilter() { return &m_filter; }
// [F]
//dtQueryFilter* getEditableFilter() {return &m_filters[0];}
dtQueryFilter* getIndexedEditableFilter(const int i = 0) { return (i >= 0 && i < DT_CROWD_MAX_QUERY_FILTER_TYPE) ? &m_filters[i] : 0; }
/// Gets the search extents [(x, y, z)] used by the crowd for query operations. /// Gets the search extents [(x, y, z)] used by the crowd for query operations.
/// @return The search extents used by the crowd. [(x, y, z)] /// @return The search extents used by the crowd. [(x, y, z)]

View File

@ -482,8 +482,10 @@ int dtCrowd::getAgentCount() const
/// @par /// @par
/// ///
/// Agents in the pool may not be in use. Check #dtCrowdAgent.active before using the returned object. /// Agents in the pool may not be in use. Check #dtCrowdAgent.active before using the returned object.
const dtCrowdAgent* dtCrowd::getAgent(const int idx) dtCrowdAgent* dtCrowd::getAgent(const int idx)
{ {
if (idx < 0 || idx >= m_maxAgents)
return 0;
return &m_agents[idx]; return &m_agents[idx];
} }
@ -514,11 +516,18 @@ int dtCrowd::addAgent(const float* pos, const dtCrowdAgentParams* params)
dtCrowdAgent* ag = &m_agents[idx]; dtCrowdAgent* ag = &m_agents[idx];
// [F]
if (params->queryFilterType < DT_CROWD_MAX_QUERY_FILTER_TYPE)
ag->queryFilterType = params->queryFilterType;
else
ag->queryFilterType = 0;
// Find nearest position on navmesh and place the agent there. // Find nearest position on navmesh and place the agent there.
float nearest[3]; float nearest[3];
dtPolyRef ref = 0; dtPolyRef ref = 0;
dtVcopy(nearest, pos); dtVcopy(nearest, pos);
dtStatus status = m_navquery->findNearestPoly(pos, m_ext, &m_filter, &ref, nearest); dtStatus status = m_navquery->findNearestPoly(pos, m_ext, &m_filters[ag->queryFilterType], &ref, nearest);
if (dtStatusFailed(status)) if (dtStatusFailed(status))
{ {
dtVcopy(nearest, pos); dtVcopy(nearest, pos);
@ -691,7 +700,7 @@ void dtCrowd::updateMoveRequest(const float /*dt*/)
// Quick seach towards the goal. // Quick seach towards the goal.
static const int MAX_ITER = 20; static const int MAX_ITER = 20;
m_navquery->initSlicedFindPath(path[0], ag->targetRef, ag->npos, ag->targetPos, &m_filter); m_navquery->initSlicedFindPath(path[0], ag->targetRef, ag->npos, ag->targetPos, &m_filters[ag->queryFilterType]);
m_navquery->updateSlicedFindPath(MAX_ITER, 0); m_navquery->updateSlicedFindPath(MAX_ITER, 0);
dtStatus status = 0; dtStatus status = 0;
if (ag->targetReplan) // && npath > 10) if (ag->targetReplan) // && npath > 10)
@ -758,7 +767,7 @@ void dtCrowd::updateMoveRequest(const float /*dt*/)
{ {
dtCrowdAgent* ag = queue[i]; dtCrowdAgent* ag = queue[i];
ag->targetPathqRef = m_pathq.request(ag->corridor.getLastPoly(), ag->targetRef, ag->targetPathqRef = m_pathq.request(ag->corridor.getLastPoly(), ag->targetRef,
ag->corridor.getTarget(), ag->targetPos, &m_filter); ag->corridor.getTarget(), ag->targetPos, &m_filters[ag->queryFilterType]);
if (ag->targetPathqRef != DT_PATHQ_INVALID) if (ag->targetPathqRef != DT_PATHQ_INVALID)
ag->targetState = DT_CROWDAGENT_TARGET_WAITING_FOR_PATH; ag->targetState = DT_CROWDAGENT_TARGET_WAITING_FOR_PATH;
} }
@ -912,7 +921,7 @@ void dtCrowd::updateTopologyOptimization(dtCrowdAgent** agents, const int nagent
for (int i = 0; i < nqueue; ++i) for (int i = 0; i < nqueue; ++i)
{ {
dtCrowdAgent* ag = queue[i]; dtCrowdAgent* ag = queue[i];
ag->corridor.optimizePathTopology(m_navquery, &m_filter); ag->corridor.optimizePathTopology(m_navquery, &m_filters[ag->queryFilterType]);
ag->topologyOptTime = 0; ag->topologyOptTime = 0;
} }
@ -930,8 +939,9 @@ void dtCrowd::checkPathValidity(dtCrowdAgent** agents, const int nagents, const
if (ag->state != DT_CROWDAGENT_STATE_WALKING) if (ag->state != DT_CROWDAGENT_STATE_WALKING)
continue; continue;
if (ag->targetState == DT_CROWDAGENT_TARGET_NONE || ag->targetState == DT_CROWDAGENT_TARGET_VELOCITY) // BUG FIX: https://groups.google.com/forum/#!topic/recastnavigation/E6khmmKJkzk
continue; //if (ag->targetState == DT_CROWDAGENT_TARGET_NONE || ag->targetState == DT_CROWDAGENT_TARGET_VELOCITY)
// continue;
ag->targetReplanTime += dt; ag->targetReplanTime += dt;
@ -942,14 +952,14 @@ void dtCrowd::checkPathValidity(dtCrowdAgent** agents, const int nagents, const
float agentPos[3]; float agentPos[3];
dtPolyRef agentRef = ag->corridor.getFirstPoly(); dtPolyRef agentRef = ag->corridor.getFirstPoly();
dtVcopy(agentPos, ag->npos); dtVcopy(agentPos, ag->npos);
if (!m_navquery->isValidPolyRef(agentRef, &m_filter)) if (!m_navquery->isValidPolyRef(agentRef, &m_filters[ag->queryFilterType]))
{ {
// Current location is not valid, try to reposition. // Current location is not valid, try to reposition.
// TODO: this can snap agents, how to handle that? // TODO: this can snap agents, how to handle that?
float nearest[3]; float nearest[3];
dtVcopy(nearest, agentPos); dtVcopy(nearest, agentPos);
agentRef = 0; agentRef = 0;
m_navquery->findNearestPoly(ag->npos, m_ext, &m_filter, &agentRef, nearest); m_navquery->findNearestPoly(ag->npos, m_ext, &m_filters[ag->queryFilterType], &agentRef, nearest);
dtVcopy(agentPos, nearest); dtVcopy(agentPos, nearest);
if (!agentRef) if (!agentRef)
@ -971,16 +981,20 @@ void dtCrowd::checkPathValidity(dtCrowdAgent** agents, const int nagents, const
replan = true; replan = true;
} }
// Davo BUG FIX: https://groups.google.com/forum/#!topic/recastnavigation/E6khmmKJkzk
if (ag->targetState == DT_CROWDAGENT_TARGET_NONE || ag->targetState == DT_CROWDAGENT_TARGET_VELOCITY)
continue;
// Try to recover move request position. // Try to recover move request position.
if (ag->targetState != DT_CROWDAGENT_TARGET_NONE && ag->targetState != DT_CROWDAGENT_TARGET_FAILED) if (ag->targetState != DT_CROWDAGENT_TARGET_NONE && ag->targetState != DT_CROWDAGENT_TARGET_FAILED)
{ {
if (!m_navquery->isValidPolyRef(ag->targetRef, &m_filter)) if (!m_navquery->isValidPolyRef(ag->targetRef, &m_filters[ag->queryFilterType]))
{ {
// Current target is not valid, try to reposition. // Current target is not valid, try to reposition.
float nearest[3]; float nearest[3];
dtVcopy(nearest, ag->targetPos); dtVcopy(nearest, ag->targetPos);
ag->targetRef = 0; ag->targetRef = 0;
m_navquery->findNearestPoly(ag->targetPos, m_ext, &m_filter, &ag->targetRef, nearest); m_navquery->findNearestPoly(ag->targetPos, m_ext, &m_filters[ag->queryFilterType], &ag->targetRef, nearest);
dtVcopy(ag->targetPos, nearest); dtVcopy(ag->targetPos, nearest);
replan = true; replan = true;
} }
@ -993,7 +1007,7 @@ void dtCrowd::checkPathValidity(dtCrowdAgent** agents, const int nagents, const
} }
// If nearby corridor is not valid, replan. // If nearby corridor is not valid, replan.
if (!ag->corridor.isValid(CHECK_LOOKAHEAD, m_navquery, &m_filter)) if (!ag->corridor.isValid(CHECK_LOOKAHEAD, m_navquery, &m_filters[ag->queryFilterType]))
{ {
// Fix current path. // Fix current path.
// ag->corridor.trimInvalidPath(agentRef, agentPos, m_navquery, &m_filter); // ag->corridor.trimInvalidPath(agentRef, agentPos, m_navquery, &m_filter);
@ -1030,6 +1044,13 @@ void dtCrowd::update(const float dt, dtCrowdAgentDebugInfo* debug)
dtCrowdAgent** agents = m_activeAgents; dtCrowdAgent** agents = m_activeAgents;
int nagents = getActiveAgents(agents, m_maxAgents); int nagents = getActiveAgents(agents, m_maxAgents);
// [F]
for (int i = 0; i < nagents; ++i)
{
dtCrowdAgent* ag = agents[i];
ag->queryFilterType = ag->params.queryFilterType;
}
// Check that all agents still have valid paths. // Check that all agents still have valid paths.
checkPathValidity(agents, nagents, dt); checkPathValidity(agents, nagents, dt);
@ -1060,10 +1081,10 @@ void dtCrowd::update(const float dt, dtCrowdAgentDebugInfo* debug)
// if it has become invalid. // if it has become invalid.
const float updateThr = ag->params.collisionQueryRange*0.25f; const float updateThr = ag->params.collisionQueryRange*0.25f;
if (dtVdist2DSqr(ag->npos, ag->boundary.getCenter()) > dtSqr(updateThr) || if (dtVdist2DSqr(ag->npos, ag->boundary.getCenter()) > dtSqr(updateThr) ||
!ag->boundary.isValid(m_navquery, &m_filter)) !ag->boundary.isValid(m_navquery, &m_filters[ag->queryFilterType]))
{ {
ag->boundary.update(ag->corridor.getFirstPoly(), ag->npos, ag->params.collisionQueryRange, ag->boundary.update(ag->corridor.getFirstPoly(), ag->npos, ag->params.collisionQueryRange,
m_navquery, &m_filter); m_navquery, &m_filters[ag->queryFilterType]);
} }
// Query neighbour agents // Query neighbour agents
ag->nneis = getNeighbours(ag->npos, ag->params.height, ag->params.collisionQueryRange, ag->nneis = getNeighbours(ag->npos, ag->params.height, ag->params.collisionQueryRange,
@ -1085,14 +1106,14 @@ void dtCrowd::update(const float dt, dtCrowdAgentDebugInfo* debug)
// Find corners for steering // Find corners for steering
ag->ncorners = ag->corridor.findCorners(ag->cornerVerts, ag->cornerFlags, ag->cornerPolys, ag->ncorners = ag->corridor.findCorners(ag->cornerVerts, ag->cornerFlags, ag->cornerPolys,
DT_CROWDAGENT_MAX_CORNERS, m_navquery, &m_filter); DT_CROWDAGENT_MAX_CORNERS, m_navquery, &m_filters[ag->queryFilterType]);
// Check to see if the corner after the next corner is directly visible, // Check to see if the corner after the next corner is directly visible,
// and short cut to there. // and short cut to there.
if ((ag->params.updateFlags & DT_CROWD_OPTIMIZE_VIS) && ag->ncorners > 0) if ((ag->params.updateFlags & DT_CROWD_OPTIMIZE_VIS) && ag->ncorners > 0)
{ {
const float* target = &ag->cornerVerts[dtMin(1,ag->ncorners-1)*3]; const float* target = &ag->cornerVerts[dtMin(1,ag->ncorners-1)*3];
ag->corridor.optimizePathVisibility(target, ag->params.pathOptimizationRange, m_navquery, &m_filter); ag->corridor.optimizePathVisibility(target, ag->params.pathOptimizationRange, m_navquery, &m_filters[ag->queryFilterType]);
// Copy data for debug purposes. // Copy data for debug purposes.
if (debugIdx == i) if (debugIdx == i)
@ -1264,7 +1285,7 @@ void dtCrowd::update(const float dt, dtCrowdAgentDebugInfo* debug)
if (debugIdx == i) if (debugIdx == i)
vod = debug->vod; vod = debug->vod;
// Sample new safe velocity. // MySample new safe velocity.
bool adaptive = true; bool adaptive = true;
int ns = 0; int ns = 0;
@ -1372,7 +1393,7 @@ void dtCrowd::update(const float dt, dtCrowdAgentDebugInfo* debug)
continue; continue;
// Move along navmesh. // Move along navmesh.
ag->corridor.movePosition(ag->npos, m_navquery, &m_filter); ag->corridor.movePosition(ag->npos, m_navquery, &m_filters[ag->queryFilterType]);
// Get valid constrained position back. // Get valid constrained position back.
dtVcopy(ag->npos, ag->corridor.getPos()); dtVcopy(ag->npos, ag->corridor.getPos());