Optimise obstruction grid updates in the common case when terrain hasn't changed
This was SVN commit r9001.
This commit is contained in:
parent
794584ea11
commit
dbc6d27411
@ -216,7 +216,7 @@ public:
|
||||
m_WorldZ0 = z0;
|
||||
m_WorldX1 = x1;
|
||||
m_WorldZ1 = z1;
|
||||
MakeDirty();
|
||||
MakeDirtyAll();
|
||||
|
||||
// Subdivision system bounds:
|
||||
debug_assert(x0.IsZero() && z0.IsZero()); // don't bother implementing non-zero offsets yet
|
||||
@ -250,7 +250,7 @@ public:
|
||||
UnitShape shape = { ent, x, z, r, flags, group };
|
||||
size_t id = m_UnitShapeNext++;
|
||||
m_UnitShapes[id] = shape;
|
||||
MakeDirtyUnits();
|
||||
MakeDirtyUnit(flags);
|
||||
|
||||
m_UnitSubdivision.Add(id, CFixedVector2D(x - r, z - r), CFixedVector2D(x + r, z + r));
|
||||
|
||||
@ -267,7 +267,7 @@ public:
|
||||
StaticShape shape = { ent, x, z, u, v, w/2, h/2, flags };
|
||||
size_t id = m_StaticShapeNext++;
|
||||
m_StaticShapes[id] = shape;
|
||||
MakeDirty();
|
||||
MakeDirtyStatic(flags);
|
||||
|
||||
CFixedVector2D center(x, z);
|
||||
CFixedVector2D bbHalfSize = Geometry::GetHalfBoundingBox(u, v, CFixedVector2D(w/2, h/2));
|
||||
@ -312,7 +312,7 @@ public:
|
||||
shape.x = x;
|
||||
shape.z = z;
|
||||
|
||||
MakeDirtyUnits();
|
||||
MakeDirtyUnit(shape.flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -336,7 +336,7 @@ public:
|
||||
shape.u = u;
|
||||
shape.v = v;
|
||||
|
||||
MakeDirty();
|
||||
MakeDirtyStatic(shape.flags);
|
||||
}
|
||||
}
|
||||
|
||||
@ -351,8 +351,6 @@ public:
|
||||
shape.flags |= FLAG_MOVING;
|
||||
else
|
||||
shape.flags &= ~FLAG_MOVING;
|
||||
|
||||
MakeDirtyUnits();
|
||||
}
|
||||
}
|
||||
|
||||
@ -364,7 +362,6 @@ public:
|
||||
{
|
||||
UnitShape& shape = m_UnitShapes[TAG_TO_INDEX(tag)];
|
||||
shape.group = group;
|
||||
MakeDirtyUnits();
|
||||
}
|
||||
}
|
||||
|
||||
@ -379,8 +376,8 @@ public:
|
||||
CFixedVector2D(shape.x - shape.r, shape.z - shape.r),
|
||||
CFixedVector2D(shape.x + shape.r, shape.z + shape.r));
|
||||
|
||||
MakeDirtyUnit(shape.flags);
|
||||
m_UnitShapes.erase(TAG_TO_INDEX(tag));
|
||||
MakeDirtyUnits();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -390,8 +387,8 @@ public:
|
||||
CFixedVector2D bbHalfSize = Geometry::GetHalfBoundingBox(shape.u, shape.v, CFixedVector2D(shape.hw, shape.hh));
|
||||
m_StaticSubdivision.Remove(TAG_TO_INDEX(tag), center - bbHalfSize, center + bbHalfSize);
|
||||
|
||||
MakeDirtyStatic(shape.flags);
|
||||
m_StaticShapes.erase(TAG_TO_INDEX(tag));
|
||||
MakeDirty();
|
||||
}
|
||||
}
|
||||
|
||||
@ -426,7 +423,7 @@ public:
|
||||
virtual void SetPassabilityCircular(bool enabled)
|
||||
{
|
||||
m_PassabilityCircular = enabled;
|
||||
MakeDirty();
|
||||
MakeDirtyAll();
|
||||
}
|
||||
|
||||
virtual void SetDebugOverlay(bool enabled)
|
||||
@ -448,20 +445,35 @@ private:
|
||||
|
||||
/**
|
||||
* Mark all previous Rasterise()d grids as dirty, and the debug display.
|
||||
* Call this when any static shapes or world bounds have changed.
|
||||
* Call this when the world bounds have changed.
|
||||
*/
|
||||
void MakeDirty()
|
||||
void MakeDirtyAll()
|
||||
{
|
||||
++m_DirtyID;
|
||||
m_DebugOverlayDirty = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the debug display as dirty.
|
||||
* Call this when any unit shapes (which don't affect Rasterise) have changed.
|
||||
* Mark all previous Rasterise()d grids as dirty, if they depend on this shape.
|
||||
* Call this when a static shape has changed.
|
||||
*/
|
||||
void MakeDirtyUnits()
|
||||
void MakeDirtyStatic(u8 flags)
|
||||
{
|
||||
if (flags & (FLAG_BLOCK_PATHFINDING|FLAG_BLOCK_FOUNDATION))
|
||||
++m_DirtyID;
|
||||
|
||||
m_DebugOverlayDirty = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark all previous Rasterise()d grids as dirty, if they depend on this shape.
|
||||
* Call this when a unit shape has changed.
|
||||
*/
|
||||
void MakeDirtyUnit(u8 flags)
|
||||
{
|
||||
if (flags & (FLAG_BLOCK_PATHFINDING|FLAG_BLOCK_FOUNDATION))
|
||||
++m_DirtyID;
|
||||
|
||||
m_DebugOverlayDirty = true;
|
||||
}
|
||||
|
||||
|
@ -277,8 +277,6 @@ const Grid<u16>& CCmpPathfinder::GetPassabilityGrid()
|
||||
|
||||
void CCmpPathfinder::UpdateGrid()
|
||||
{
|
||||
PROFILE("UpdateGrid");
|
||||
|
||||
// Initialise the terrain data when first needed
|
||||
if (!m_Grid)
|
||||
{
|
||||
@ -291,16 +289,53 @@ void CCmpPathfinder::UpdateGrid()
|
||||
m_ObstructionGrid = new Grid<u8>(m_MapSize, m_MapSize);
|
||||
}
|
||||
|
||||
CmpPtr<ICmpWaterManager> cmpWaterMan(GetSimContext(), SYSTEM_ENTITY);
|
||||
|
||||
CTerrain& terrain = GetSimContext().GetTerrain();
|
||||
|
||||
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY);
|
||||
if (cmpObstructionManager->Rasterise(*m_ObstructionGrid) || m_TerrainDirty)
|
||||
|
||||
bool obstructionsDirty = cmpObstructionManager->Rasterise(*m_ObstructionGrid);
|
||||
|
||||
if (obstructionsDirty && !m_TerrainDirty)
|
||||
{
|
||||
PROFILE("UpdateGrid obstructions");
|
||||
|
||||
// Obstructions changed - we need to recompute passability
|
||||
// Since terrain hasn't changed we only need to update the obstruction bits
|
||||
// and can skip the rest of the data
|
||||
|
||||
// TODO: if ObstructionManager::SetPassabilityCircular was called at runtime
|
||||
// (which should probably never happen, but that's not guaranteed),
|
||||
// then TILE_OUTOFBOUNDS will change and we can't use this fast path, but
|
||||
// currently it'll just set obstructionsDirty and we won't notice
|
||||
|
||||
for (u16 j = 0; j < m_MapSize; ++j)
|
||||
{
|
||||
for (u16 i = 0; i < m_MapSize; ++i)
|
||||
{
|
||||
TerrainTile& t = m_Grid->get(i, j);
|
||||
|
||||
u8 obstruct = m_ObstructionGrid->get(i, j);
|
||||
|
||||
if (obstruct & ICmpObstructionManager::TILE_OBSTRUCTED_PATHFINDING)
|
||||
t |= 1;
|
||||
else
|
||||
t &= ~1;
|
||||
|
||||
if (obstruct & ICmpObstructionManager::TILE_OBSTRUCTED_FOUNDATION)
|
||||
t |= 2;
|
||||
else
|
||||
t &= ~2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (obstructionsDirty || m_TerrainDirty)
|
||||
{
|
||||
PROFILE("UpdateGrid full");
|
||||
|
||||
// Obstructions or terrain changed - we need to recompute passability
|
||||
// TODO: only bother recomputing the region that has actually changed
|
||||
// TODO: if only obstructions changed, don't recompute the terrain masks
|
||||
|
||||
CmpPtr<ICmpWaterManager> cmpWaterMan(GetSimContext(), SYSTEM_ENTITY);
|
||||
|
||||
CTerrain& terrain = GetSimContext().GetTerrain();
|
||||
|
||||
for (u16 j = 0; j < m_MapSize; ++j)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user