mirror of
https://github.com/recastnavigation/recastnavigation.git
synced 2026-09-17 07:44:35 +00:00
Added better state control for tile cache obstacles.
This commit is contained in:
@@ -363,7 +363,7 @@ dtObstacleRef dtTileCache::addObstacle(const float* pos, const float radius, con
|
||||
unsigned short salt = ob->salt;
|
||||
memset(ob, 0, sizeof(dtTileCacheObstacle));
|
||||
ob->salt = salt;
|
||||
ob->state = OBS_NEW;
|
||||
ob->state = DT_OBSTACLE_PROCESSING;
|
||||
dtVcopy(ob->pos, pos);
|
||||
ob->radius = radius;
|
||||
ob->height = height;
|
||||
@@ -454,8 +454,6 @@ dtStatus dtTileCache::update(const float /*dt*/, dtNavMesh* navmesh)
|
||||
|
||||
if (req->action == REQUEST_ADD)
|
||||
{
|
||||
// Add and init obstacle.
|
||||
ob->state = OBS_PROCESSED;
|
||||
// Find touched tiles.
|
||||
float bmin[3], bmax[3];
|
||||
getObstacleBounds(ob, bmin, bmax);
|
||||
@@ -464,29 +462,32 @@ dtStatus dtTileCache::update(const float /*dt*/, dtNavMesh* navmesh)
|
||||
queryTiles(bmin, bmax, ob->touched, &ntouched, DT_MAX_TOUCHED_TILES);
|
||||
ob->ntouched = (unsigned char)ntouched;
|
||||
// Add tiles to update list.
|
||||
ob->npending = 0;
|
||||
for (int j = 0; j < ob->ntouched; ++j)
|
||||
{
|
||||
if (m_nupdate < MAX_UPDATE && !contains(m_update, m_nupdate, ob->touched[j]))
|
||||
m_update[m_nupdate++] = ob->touched[j];
|
||||
if (m_nupdate < MAX_UPDATE)
|
||||
{
|
||||
if (!contains(m_update, m_nupdate, ob->touched[j]))
|
||||
m_update[m_nupdate++] = ob->touched[j];
|
||||
ob->pending[ob->npending++] = ob->touched[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (req->action == REQUEST_REMOVE)
|
||||
{
|
||||
// Remove obstacle.
|
||||
ob->state = OBS_EMPTY;
|
||||
// Prepare to remove obstacle.
|
||||
ob->state = DT_OBSTACLE_REMOVING;
|
||||
// Add tiles to update list.
|
||||
ob->npending = 0;
|
||||
for (int j = 0; j < ob->ntouched; ++j)
|
||||
{
|
||||
if (m_nupdate < MAX_UPDATE && !contains(m_update, m_nupdate, ob->touched[j]))
|
||||
m_update[m_nupdate++] = ob->touched[j];
|
||||
if (m_nupdate < MAX_UPDATE)
|
||||
{
|
||||
if (!contains(m_update, m_nupdate, ob->touched[j]))
|
||||
m_update[m_nupdate++] = ob->touched[j];
|
||||
ob->pending[ob->npending++] = ob->touched[j];
|
||||
}
|
||||
}
|
||||
// Update salt, salt should never be zero.
|
||||
ob->salt = (ob->salt+1) & ((1<<16)-1);
|
||||
if (ob->salt == 0)
|
||||
ob->salt++;
|
||||
// Return obstacle to free list.
|
||||
ob->next = m_nextFreeObstacle;
|
||||
m_nextFreeObstacle = ob;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -496,8 +497,52 @@ dtStatus dtTileCache::update(const float /*dt*/, dtNavMesh* navmesh)
|
||||
// Process updates
|
||||
if (m_nupdate)
|
||||
{
|
||||
dtStatus status = buildNavMeshTile(m_update[m_nupdate-1], navmesh);
|
||||
// Build mesh
|
||||
const dtCompressedTileRef ref = m_update[0];
|
||||
dtStatus status = buildNavMeshTile(ref, navmesh);
|
||||
m_nupdate--;
|
||||
if (m_nupdate > 0)
|
||||
memmove(m_update, m_update+1, m_nupdate*sizeof(dtCompressedTileRef));
|
||||
|
||||
// Update obstacle states.
|
||||
for (int i = 0; i < m_params.maxObstacles; ++i)
|
||||
{
|
||||
dtTileCacheObstacle* ob = &m_obstacles[i];
|
||||
if (ob->state == DT_OBSTACLE_PROCESSING || ob->state == DT_OBSTACLE_REMOVING)
|
||||
{
|
||||
// Remove handled tile from pending list.
|
||||
for (int j = 0; j < (int)ob->npending; j++)
|
||||
{
|
||||
if (ob->pending[j] == ref)
|
||||
{
|
||||
ob->pending[j] = ob->pending[(int)ob->npending-1];
|
||||
ob->npending--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If all pending tiles processed, change state.
|
||||
if (ob->npending == 0)
|
||||
{
|
||||
if (ob->state == DT_OBSTACLE_PROCESSING)
|
||||
{
|
||||
ob->state = DT_OBSTACLE_PROCESSED;
|
||||
}
|
||||
else if (ob->state == DT_OBSTACLE_REMOVING)
|
||||
{
|
||||
ob->state = DT_OBSTACLE_EMPTY;
|
||||
// Update salt, salt should never be zero.
|
||||
ob->salt = (ob->salt+1) & ((1<<16)-1);
|
||||
if (ob->salt == 0)
|
||||
ob->salt++;
|
||||
// Return obstacle to free list.
|
||||
ob->next = m_nextFreeObstacle;
|
||||
m_nextFreeObstacle = ob;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dtStatusFailed(status))
|
||||
return status;
|
||||
}
|
||||
@@ -550,7 +595,7 @@ dtStatus dtTileCache::buildNavMeshTile(const dtCompressedTileRef ref, dtNavMesh*
|
||||
for (int i = 0; i < m_params.maxObstacles; ++i)
|
||||
{
|
||||
const dtTileCacheObstacle* ob = &m_obstacles[i];
|
||||
if (ob->state != OBS_PROCESSED)
|
||||
if (ob->state == DT_OBSTACLE_EMPTY || ob->state == DT_OBSTACLE_REMOVING)
|
||||
continue;
|
||||
if (contains(ob->touched, ob->ntouched, ref))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user