Added better state control for tile cache obstacles.
This commit is contained in:
parent
bcf8b2ac03
commit
d2148ff57d
@ -29,9 +29,10 @@ struct dtCompressedTile
|
|||||||
|
|
||||||
enum ObstacleState
|
enum ObstacleState
|
||||||
{
|
{
|
||||||
OBS_EMPTY,
|
DT_OBSTACLE_EMPTY,
|
||||||
OBS_NEW,
|
DT_OBSTACLE_PROCESSING,
|
||||||
OBS_PROCESSED,
|
DT_OBSTACLE_PROCESSED,
|
||||||
|
DT_OBSTACLE_REMOVING,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int DT_MAX_TOUCHED_TILES = 8;
|
static const int DT_MAX_TOUCHED_TILES = 8;
|
||||||
@ -39,9 +40,11 @@ struct dtTileCacheObstacle
|
|||||||
{
|
{
|
||||||
float pos[3], radius, height;
|
float pos[3], radius, height;
|
||||||
dtCompressedTileRef touched[DT_MAX_TOUCHED_TILES];
|
dtCompressedTileRef touched[DT_MAX_TOUCHED_TILES];
|
||||||
|
dtCompressedTileRef pending[DT_MAX_TOUCHED_TILES];
|
||||||
unsigned short salt;
|
unsigned short salt;
|
||||||
unsigned char state;
|
unsigned char state;
|
||||||
unsigned char ntouched;
|
unsigned char ntouched;
|
||||||
|
unsigned char npending;
|
||||||
dtTileCacheObstacle* next;
|
dtTileCacheObstacle* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -363,7 +363,7 @@ dtObstacleRef dtTileCache::addObstacle(const float* pos, const float radius, con
|
|||||||
unsigned short salt = ob->salt;
|
unsigned short salt = ob->salt;
|
||||||
memset(ob, 0, sizeof(dtTileCacheObstacle));
|
memset(ob, 0, sizeof(dtTileCacheObstacle));
|
||||||
ob->salt = salt;
|
ob->salt = salt;
|
||||||
ob->state = OBS_NEW;
|
ob->state = DT_OBSTACLE_PROCESSING;
|
||||||
dtVcopy(ob->pos, pos);
|
dtVcopy(ob->pos, pos);
|
||||||
ob->radius = radius;
|
ob->radius = radius;
|
||||||
ob->height = height;
|
ob->height = height;
|
||||||
@ -454,8 +454,6 @@ dtStatus dtTileCache::update(const float /*dt*/, dtNavMesh* navmesh)
|
|||||||
|
|
||||||
if (req->action == REQUEST_ADD)
|
if (req->action == REQUEST_ADD)
|
||||||
{
|
{
|
||||||
// Add and init obstacle.
|
|
||||||
ob->state = OBS_PROCESSED;
|
|
||||||
// Find touched tiles.
|
// Find touched tiles.
|
||||||
float bmin[3], bmax[3];
|
float bmin[3], bmax[3];
|
||||||
getObstacleBounds(ob, bmin, bmax);
|
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);
|
queryTiles(bmin, bmax, ob->touched, &ntouched, DT_MAX_TOUCHED_TILES);
|
||||||
ob->ntouched = (unsigned char)ntouched;
|
ob->ntouched = (unsigned char)ntouched;
|
||||||
// Add tiles to update list.
|
// Add tiles to update list.
|
||||||
|
ob->npending = 0;
|
||||||
for (int j = 0; j < ob->ntouched; ++j)
|
for (int j = 0; j < ob->ntouched; ++j)
|
||||||
{
|
{
|
||||||
if (m_nupdate < MAX_UPDATE && !contains(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];
|
m_update[m_nupdate++] = ob->touched[j];
|
||||||
|
ob->pending[ob->npending++] = ob->touched[j];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (req->action == REQUEST_REMOVE)
|
else if (req->action == REQUEST_REMOVE)
|
||||||
{
|
{
|
||||||
// Remove obstacle.
|
// Prepare to remove obstacle.
|
||||||
ob->state = OBS_EMPTY;
|
ob->state = DT_OBSTACLE_REMOVING;
|
||||||
// Add tiles to update list.
|
// Add tiles to update list.
|
||||||
|
ob->npending = 0;
|
||||||
for (int j = 0; j < ob->ntouched; ++j)
|
for (int j = 0; j < ob->ntouched; ++j)
|
||||||
{
|
{
|
||||||
if (m_nupdate < MAX_UPDATE && !contains(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];
|
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
|
// Process updates
|
||||||
if (m_nupdate)
|
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--;
|
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))
|
if (dtStatusFailed(status))
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -550,7 +595,7 @@ dtStatus dtTileCache::buildNavMeshTile(const dtCompressedTileRef ref, dtNavMesh*
|
|||||||
for (int i = 0; i < m_params.maxObstacles; ++i)
|
for (int i = 0; i < m_params.maxObstacles; ++i)
|
||||||
{
|
{
|
||||||
const dtTileCacheObstacle* ob = &m_obstacles[i];
|
const dtTileCacheObstacle* ob = &m_obstacles[i];
|
||||||
if (ob->state != OBS_PROCESSED)
|
if (ob->state == DT_OBSTACLE_EMPTY || ob->state == DT_OBSTACLE_REMOVING)
|
||||||
continue;
|
continue;
|
||||||
if (contains(ob->touched, ob->ntouched, ref))
|
if (contains(ob->touched, ob->ntouched, ref))
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user